home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-10-12 | 46.6 KB | 1,485 lines |
- 2 AMIGADOS
-
- 2.1 INTRODUCTION
-
- In this chapter are we going to discuss how to read and write
- files from/to different devices (disk drivers etc). How to
- protect your data from being corrupted by other tasks working
- with the same file, and how to attach comments to files, how
- to rename them etc...
-
- However, before we start it is best to look at how AmigaDOS
- works, and explain some commonly used words. If you are familiar
- with AmigaDOS and CLI you can skip the following chapters and
- immediately start on chapter 2.2 (OPEN AND CLOSE FILES).
-
-
-
- 2.1.1 PHYSICAL DEVICES
-
- Physical devices are parts of the Amiga to which files can be
- read from and sent to. The most commonly used physical device
- is undoubtedly the internal disk drive (DF0:).
-
- Here is the list of the standard AmigaDOS devices:
- -------------------------------------------------------------
- DF0: Diskdrive 0. File/Directory access
- DF1: Diskdrive 1. File/Directory access
- DF2: Diskdrive 2. File/Directory access
- DF3: Diskdrive 3. File/Directory access
- RAM: RAMdisk, File/Directory access
-
- SER: Serial port, Input/Output
- PAR: Parallel port, Input/Output
- PRT: Printerdevice, Output to printer (trough Preferences)
-
- CON: Console, (window) Input/Output
- RAW: RAW, (window) Input/Output
- NIL: Nothing, Output to nothing
- -------------------------------------------------------------
-
- (Note that all device-names end with a colon.)
-
- If you want to copy a file called "program.c" from the internal
- disk drive (DF0:) to the second disk drive (DF1:) you write:
-
- copy from DF0:program.c to DF1:
-
- If you want to copy a file called "program.c" from the internal
- disk drive (DF0:) to the parallel port (PAR:) you write:
-
- copy from DF0:program.c to PAR:
-
- If a printer was connected to the parallel port the file
- "program.c" would be printed out with the printers default
- mode. If the printer was connected to the serial port (SER:)
- you write:
-
- copy from DF0:program.c to SER:
-
- However, if you want to copy a file to the printer, and you
- want to use the printer mode you have chosen with Preferences,
- you use the printer device (PRT:). (With Preferences you can
- decide which device you want to use (PAR: or SER:), and if the
- text should be printed with letter quality or in draft mode
- etc.)
-
- copy from DF0:program.c to PRT:
-
-
- AmigaDOS allows you even to use special windows (CON:) for
- input/output. The only thing you need to remember is to tell
- AmigaDOS what size and position of the window you want. The
- syntax is:
-
- CON:x/y/width/height/(title)
-
- Remember to include all four slashes! (The window title is
- optional.) To copy the file "program.c" to a special window
- you write:
-
- copy from DF0:program.c to CON:10/20/320/100/Text
-
- This will print the file program.c to a window positioned at
- x position 10, y position 20, width 320, height 100, with the
- title "Text". If you want to use spaces in the title you need
- to put quotes around the whole expression:
-
- copy from DF0:program.c to "CON:10/20/320/100/Spacy Window"
-
-
-
- 2.1.2 VOLUMES
-
- To access a disk you can either use the physical device name of
- the drive in which the disk is, or use the volume name of the
- disk. If you want to copy a file from the RAMdisk called
- "program.c", to a disk called "DOCUMENTS", and the disk is in
- the second disk drive, you can either write:
-
- copy from RAM:program.c to DF1:
-
- or
-
- copy from RAM:program.c to DOCUMENTS:
-
- (Note the colon after the volume name!) The advantage with the
- last example is that you do not need to bother in which drive
- the DOCUMENTS disk is in. Furthermore, if the right disk was not
- in any drive, AmigaDOS will ask you to insert it, and you
- do not need to worry about writing to the wrong disk.
-
-
-
- 2.1.3 DIRECTORIES/SUBDIRECTORIES/FILES
-
- On a disk there exist directories/subdirectories and files. A
- subdirectory is a directory inside another directory. (There
- may be subdirectories inside other subdirectories and so on.)
- See picture:
-
- DEVICE/VOLUME
- |
- /---------------------+---------------------\
- | | |
- FILES DIRECTORY DIRECTORY
- | |
- FILES SUBDIRECTORIES
- |
- FILES
-
- How to gain access to files:
-
- Left of the colon Right of the colon Right of a slash
- ------------------------------------------------------------
- Device name Directory name Subdirectory name
- or or or
- Volume name Filename Filename
- ------------------------------------------------------------
-
-
- For example. Here is a disk named "CPrograms" on which there is
- a program called "Example" and two directories named "Games"
- and "Utilities". In the Utilities directory there is a program
- called FileWindow, and in the Games directory there are two
- games called Car and MiniBlast. There exist also a subdirectory
- called "SourceCode" which contains two files "Car.c" and
- "MiniBlast.c". See drawing:
-
- CPrograms
- |
- /----------------------+--------------------------\
- | | |
- Example Games Utilities
- | |
- /-------------+-------------\ FileWindow
- | | |
- Car MiniBlast SourceCode
- |
- /-------------\
- | |
- Car.c MiniBlast.c
-
-
- Here is how to access all the files:
-
- CPrograms:Example
- CPrograms:Utilities/FileWindow
- CPrograms:Games/Car
- CPrograms:Games/MiniBlast
- CPrograms:Games/SourceCode/Car.c
- CPrograms:Games/SourceCode/MiniBlast.c
-
-
-
- 2.1.4 LOGICAL DEVICES
-
- Logical devices is a simple way to find files, regardless of
- where the file actually is. For example: If you have all your
- C programs on a disk called "Programs", placed i directory
- named "Examples", and you want to run the program "test1" you
- need to write:
-
- Programs:Examples/test1
-
- If you often want to access files in that directory you can
- assign a logical device to it. You then only need to write the
- logical device name and the filename, and AmigaDOS will
- automatically look on the right disk and directory.
-
- You assign logical devices by using the CLI command "Assign"
- which is called like this:
-
- Assign [logical device name]: [device/(directory/subdirectory)]
-
- For example:
-
- Assign EX: Programs:Examples
-
- To gain access to the file "test1" you then only need to write:
-
- EX:test1
-
-
- When you boot up the computer it will automatically create some
- commonly used logical devices. A good example is the logical
- device "FONTS:". It is automatically assigned to the system
- disk's "fonts" directory. Here is the list of some of the most
- commonly used logical devices:
-
- Logical device Description
- ---------------------------
- SYS: system disk
- C: CLI commands
- FONTS: fonts
- L: handlers
- LIBS: libraries
- S: sequence library
- DEVS: devices
-
- The logical device "C:" is assigned to the system disk's "c"
- directory, where all CLI commands are. If you have copied some
- CLI commands to the RAMdisk, and you want AmigaDOS to look
- there instead of looking on the system disk's c directory you
- simply reassign the C: device. For example:
-
- Assign C: RAM:
-
-
- If you call Assign without any parameters, it will list all
- logical devices, and their assignments. If you have booted up
- the system with the Lattice C Compiler disk, the following
- logical devices are assigned:
-
- Automatically assigned:
- --------------------------------------
- S Lattice_C_5.0.1:s
- L Lattice_C_5.0.1:l
- C Lattice_C_5.0.1:c
- FONTS Lattice_C_5.0.1:fonts
- DEVS Lattice_C_5.0.1:devs
- LIBS Lattice_C_5.0.1:libs
- SYS Lattice_C_5.0.1:
-
- Specially assigned: (Lattice C)
- --------------------------------------
- LIB Volume: Lattice_C_5.0.2
- INCLUDE Volume: Lattice_C_5.0.2
- LC Lattice_C_5.0.1:c
- QUAD RAM DISK:
- ENV RAM DISK:env
- CLIPS RAM DISK:clipboards
-
-
-
- 2.2 OPEN AND CLOSE FILES
-
- Before you can do anything with a file you have to ask the
- operating system to "open it". This is because AmigaDOS needs
- to know what you are going to do with the file. Are you going
- to create a new file or are you going to work with an already
- opened file. You open a file by calling the function Open():
-
- Synopsis: file_handle = Open( file_name, mode );
-
- file_handle: (BPTR) Actually a pointer to a FileHandle
- structure. If the system could not open the file
- with our requirements Open() returns NULL.
-
- file_name: (char *) Pointer to a text string which contains
- the file name including any necessary device/
- directory names.
-
- mode: (long) When you open a file you need to tell the
- system what you are going to do with it. This
- field should therefore contain one of the
- following flags:
-
- MODE_OLDFILE: Opens an existing file for reading
- and writing.
-
- MODE_NEWFILE: Opens a new file for writing.
-
- MODE_READWRITE: Opens an old file with an
- exclusive lock. (Explained later
- in this chapter.)
-
- MODE_READONLY: Same as MODE_OLDFILE.
-
- For example, if you want to create a new file called
- "Highscore.dat" you write:
-
- /* Try to open the file: */
- file_handle = Open( "Highscore.dat", MODE_NEWFILE );
-
- /* Check if we have opened the file: */
- if( file_handle == NULL )
- /* Could NOT open file! */
-
-
- Once you have finished reading/writing the file you need to
- close it. You do it by calling the function Close():
-
- Synopsis: Close( file_handle );
-
- file_handle: (BPTR) Actually a pointer to a FileHandle
- structure which has been initialized by a previous
- Open() call.
-
- Remember to close ALL files you have opened!
-
-
-
- 2.3 READ AND WRITE FILES
-
- Once you have successfully opened a file you can start to
- read/write. AmigaDOS consider files to be a stream of bytes,
- and when you read/write something you need to specify how many
- bytes you want to read/write.
-
-
-
- 2.3.1 READ()
-
- You read data by calling the function Read():
-
- Synopsis: bytes_read = Read( file_handle, buffer, size );
-
- bytes_read: (long) Number of bytes actually read. Even if you
- tell AmigaDOS that you want to read x number of
- bytes, it is not certain that you actually can
- do it. The file is maybe corrupted, not as big as
- you thought etc.
-
- file_handle: (BPTR) Actually a pointer to a FileHandle
- structure which has been initialized by a previous
- Open() call.
-
- buffer: (char *) Pointer to the data buffer you want to
- read the data into.
-
- size: (long) Number of bytes you want to read.
-
- For example, if you want to read a file which contains an array
- (highscore) of ten integers, you write: (the file has already
- been opened.)
-
- bytes_read = Read( file_handle, highscore, sizeof( highscore ) );
-
- if( bytes_read != sizeof( highscore ) )
- /* ERROR while reading! */
-
-
-
- 2.3.2 WRITE()
-
- When you what to write to a file you use the function Write():
-
- Synopsis: bytes_written = Write( file_handle, buffer, size );
-
- bytes_writtten: (long) Number of bytes actually written. Even
- if you tell AmigaDOS that you want to write x
- number of bytes, it is not certain that you
- actually can do it. Maybe the disk was full,
- writeprotected etc.
-
- file_handle: (BPTR) Actually a pointer to a FileHandle
- structure which has been initialized by a
- previous Open() call.
-
- buffer: (char *) Pointer to the data buffer which you
- want to write.
-
- size: (long) Number of bytes you want to write.
-
- For example, if you want to save an array (highscore) of
- ten integers to a file, you simply write: (the file has
- already been opened.)
-
- bytes_written = Write( file_handle, highscore, sizeof( highscore ) );
-
- if( bytes_written != sizeof( highscore ) )
- /* ERROR while writing! */
-
-
-
- 2.4 MOVE INSIDE FILES
-
- If you write something to a disk the "file cursor" will be
- positioned where you stopped writing. So if you start writing
- again, the new data will be placed after the first data. If
- you on the other hand wanted to write over the old data you
- need to move the file cursor to beginning of the data before
- you start writing. You move the file cursor by calling the
- function Seek():
-
- Synopsis: old_pos = Seek( file_handle, new_pos, mode );
-
- old_pos: (long) Previous position in the file, or -1 if
- an error occurred.
-
- file_handle: (BPTR) Actually a pointer to a FileHandle
- structure which has been initialized by a
- previous Open() call.
-
- new_pos: (long) New position relative to the "mode".
-
- mode: (long) The new_pos can be relative to:
- OFFSET_BEGINNING: Beginning of the file.
- OFFSET_CURRENT: Current position.
- OFFSET_END: The end of the file.
-
- So if you want to move the cursor to the beginning of the file
- you set mode to OFFSET_BEGINNING, and new_pos to 0. (When you
- open a file by calling the function Open(), the file cursor is
- automatically placed at the beginning of the file.)
-
- If you on the other hand want to move the cursor to the end of
- the file you set mode to OFFSET_END, and new_pos still to 0.
-
- To move 10 bytes forward from the current position you set mode
- to OFFSET_CURRENT, and new_pos to 10. To move 10 bytes
- backwards you set new_pos to -10.
-
-
-
- 2.5 FILES AND MULTITASKING
-
- Since the Amiga can have several tasks running at the same time
- it can happen that more than one task work with the same file.
- This can be very dangerous since one process may destroy some
- data another process has created.
-
- Imagine two tasks, one will read a file and multiply a value
- with two, while the other tasks should add 3. Since the two
- tasks can run at the same time it could happen that they would
- update the file at the same time:
-
- FILE:
- ---------------
- Process A reads the <- | number = 10 | -> Process B reads also
- value. (number=10) --------------- the value. (number=10)
-
- | |
- V |
- |
- Process A changes |
- the value to 20, --------------- |
- and writes the new -> | number = 20 | |
- value to the file. --------------- V
- (10 * 2 = 20)
- --------------- Process B adds 3 to
- | number = 13 | <- the number and writes
- --------------- the new value to the
- file. (10 + 3 = 13)
-
-
- As you can see, the number that was updated by process A, has
- been lost. What should have happen was that process A should
- have "locked" the file so no other tasks could work with it.
- Process B would then have been forced to wait for Process A
- to "unlock" the file before it could read the value.
-
- On large mainframe computers there exist different "locks"
- with different priorities, but on the Amiga there exist only
- two different types of lock. You can lock a file so other
- processes may read it but not change it (SHARED_LOCK), or if
- you do not want any other tasks to even read the file you set
- an EXCLUSIVE_LOCK. Call the function Lock() to set a lock:
-
- Synopsis: lock = Lock( file_name, mode );
-
- lock: (BPTR) Actually a pointer to a FileLock structure.
-
- file_name: (char *) Pointer to a text string which contains
- the file name including any necessary devices/
- directories.
-
- mode: (long) Accessmode:
- SHARED_LOCK: Other processes may read the file.
- ACCESS_READ: - " -
- EXCLUSIVE_LOCK: No other processes may use this f.
- ACCESS_WRITE: - " -
-
- Here is an example how to lock a file so no other processes
- may use the file:
-
- struct FileLock *lock;
-
- lock = Lock( "HighScore.dat", EXCLUSIVE_LOCK );
-
- if( lock == NULL )
- /* ERROR Could NOT create lock! */
-
-
- When you do not need the file any more you must "unlock" it.
- You do it by calling the function UnLock():
-
- Synopsis: UnLock( lock );
-
- lock: (BPTR) Actually a pointer to FileLock structure
- which has been initialized by a previous Lock()
- call.
-
- Remember to unlock ALL files you have locked!
-
-
-
- 2.6 OTHER USEFUL FUNCTIONS
-
- Here is a list of some other useful functions that you probably
- want to use. AmigaDOS allows you to rename and delete files,
- attach comments to them, set protection bits etc. All these
- things can be done with help of the functions listed below:
-
-
-
- 2.6.1 CREATE DIRECTORIES
-
- If you want to create a directory you use the function
- CreateDir(). You only need to give the function a pointer to
- the name of the directory you want to create, and it will
- either return a pointer to a Lock (the new directory is
- automatically given an EXCLUSIVE Lock), or NULL if something
- went wrong.
-
- Remember to unlock the new directory before your program
- determinates.
-
- If there already exist a directory with the same name, it is
- simply locked and your program will not notice any difference.
-
-
- Synopsis: lock = CreateDir( name );
-
- lock: (BPTR) Actually a pointer to a FileLock structure.
- If lock is equal to NULL, AmigaDOS have not been
- able to create the new directory.
-
- name: (char *) Pointer to a string containing the name
- of the new directory.
-
-
- Here is a short example:
-
- struct FileLock *lock;
-
- lock = CreateDir( "RAM:MyDirectory" );
-
- if( lock == NULL )
- exit( ERROR );
-
- ...
-
- UnLock( lock );
-
-
-
- 2.6.2 DELETE FILES AND DIRECTORIES
-
- If you want to delete a file you call the function
- DeleteFile(). You only need to give it a file/directory name
- and it will either return TRUE (file was deleted) or FALSE
- (file could not be deleted). Remember that you can only delete
- a directory if it is empty.
-
- Synopsis: ok = DeleteFile( name );
-
- ok: (long) Actually a Boolean. It is TRUE if AmigaDOS
- could delete the file/directory, else FALSE which
- means something went wrong. (Eg. disk write-
- protected, directory not empty etc.)
-
- name: (char *) Pointer to a string containing the name of
- the file/directory you want to delete.
-
-
-
- 2.6.3 RENAME FILES AND DIRECTORIES
-
- When you want to rename a file/directory you use the function
- Rename(). You can even move a file between directories by
- renaming it. For example:
-
- Rename( "df0:Documents/Sale.doc", "df0:Letters/Sale.doc" );
-
- will move the file Sale.doc from the directory "Documents" to
- directory "Letters". Note! You can not rename a file from one
- volume to another.
-
- Synopsis: ok = Rename( old_name, new_name );
-
- ok: (long) Actually a Boolean. It is TRUE if AmigaDOS
- could rename the file/directory, else FALSE which
- means something went wrong. (Eg. disk write-
- protected.)
-
- old_name: (char *) Pointer to a string containing the old
- file/directory name.
-
- new_name: (char *) Pointer to a string containing the new
- file/directory name.
-
-
-
- 2.6.4 ATTACH COMMENTS TO FILES AND DIRECTORIES
-
- AmigaDOS allows you to set a comment on a file or directory.
- The comment can give a brief description of what the file is,
- and is very handy to use when you want to give some extra
- information about the file etc. The comment can be up to 80
- characters long.
-
- A program can set a comment to a file/directory by using the
- function SetComment().
-
- Synopsis: ok = SetComment( name, comment );
-
- ok: (long) Actually a Boolean. It is TRUE if AmigaDOS
- could attach the new comment, else FALSE which
- means something went wrong. (Eg. disk write-
- protected.)
-
- name: (char *) Pointer to a string containing the name
- of the file/directory you want to attach the
- comment to.
-
- comment: (char *) Pointer to a string containing the
- comment. (A comment may be up to 80 characters
- long.)
-
-
- Here is a short example:
-
- if( SetComment( "Letter.doc", "Letter to Mr Smith" ) == FALSE )
- printf("ERROR! Could not attach the comment to the file!\n");
-
-
-
- 2.6.5 PROTECT FILES AND DIRECTORIES
-
- You can protect files and directory from being accidentally
- deleted or changed. You do it by calling the function
- SetProtection() which will alter the protection bits as
- desired. Here are a list of the protection bits (flags) you
- can change:
-
- FIBF_DELETE : the file/directory can not be deleted.
- FIBF_EXECUTE : the file can not be executed.
- FIBF_WRITE : you can not write to the file.
- FIBF_READ : you can not read the file.
- FIBF_ARCHIVE : Archive bit.
- FIBF_PURE : Pure bit.
- FIBF_SCRIPT : Script bit.
-
- Note! All of the flags are for the moment not working!
-
- Synopsis: ok = SetProtection( name, mask );
-
- ok: (long) Actually a Boolean. It is TRUE if AmigaDOS
- could alter the protection bits, else FALSE which
- means something went wrong. (Eg. disk write-
- protected.)
-
- name: (char *) Pointer to a string containing the name of
- the file/directory you want to change the protection
- bits.
-
- mask: (long) The protection bits. (For example, if you
- want to make the file/directory not deletable, and
- that it can not be executed you should set the
- protection bits: FIBF_DELETE | FIBF_EXECUTE.)
-
-
-
- 2.7 EXAMINE FILES AND DIRECTORIES
-
- You can examine a file or directory with the function
- Examine(). You give the function a pointer to a "lock" on
- the file/directory you want to examine, and it will initializes
- a FileInfoBlock structure for you. The FileInfoBlock structure
- contains several interesting fields which you then can look at.
-
-
-
- 2.7.1 FILEINFOBLOCK AND DATESTAMP STRUCTURE
-
- The FileInfoBlock look like this:
-
- struct FileInfoBlock
- {
- LONG fib_DiskKey;
- LONG fib_DirEntryType;
- char fib_FileName[108];
- LONG fib_Protection;
- LONG fib_EntryType;
- LONG fib_Size;
- LONG fib_NumBlocks;
- struct DateStamp fib_Date;
- char fib_Comment[80];
- char fib_Reserved[36];
- };
-
- fib_DiskKey: Key number for the disk. Usually of no
- interest for us.
-
- fib_DirEntryType: If the number is smaller than zero it is a
- file. On the other hand, if the number is
- larger than zero it is a directory.
-
- fib_FileName: Null terminated string containing the file-
- name. (Do not use longer filenames than 30
- characters.)
-
- fib_Protection: Field containing the protection flags:
-
- FIBF_DELETE : the file/directory can not be
- deleted.
- FIBF_EXECUTE : the file can not be executed.
- FIBF_WRITE : you can not write to the file.
- FIBF_READ : you can not read the file.
- FIBF_ARCHIVE : Archive bit.
- FIBF_PURE : Pure bit.
- FIBF_SCRIPT : Script bit.
-
- (Note! All of the flags are for the moment
- not working!)
-
- fib_EntryType: File/Directory entry type number. Usually of no
- interest for us.
-
- fib_Size: Size of the file (in bytes).
-
- fib_NumBlocks: Number of blocks in the file.
-
- fib_Date: Structure containing the date when the file
- was latest updated/created.
-
- fib_Comment: Null terminated string containing the file
- comment. (Max 80 characters including the NULL
- sign.)
-
- fib_Reserved: This field is for the moment reserved, and may
- therefore not be used.
-
-
- The DateStamp structure look like this:
-
- struct DateStamp
- {
- LONG ds_Days;
- LONG ds_Minute;
- LONG ds_Tick;
- };
-
- ds_Days: Number of days since 01-Jan-1978.
-
- ds_Minute: Number of minutes past midnight.
-
- ds_Tick: Number of ticks past the last minute. There are 50
- ticks / second. (50 * 60 = 3000 ticks / minute.)
-
-
-
- 2.7.2 EXAMINE()
-
- The Examine() function is called like this:
-
- Synopsis: ok = Examine( lock, fib_ptr );
-
- ok: (long) Actually a Boolean. It is TRUE if AmigaDOS
- could get information about the file/directory, else
- FALSE which means something went wrong.
-
- lock: (BPTR) Actually a pointer to a FileLock structure.
-
- fib_ptr: (struct FileInfoBlock *) Pointer to a FileInfoBlock
- structure which will be initialized with some
- information about the file/directory. IMPORTANT! the
- structure must be on a 4 byte boundary. (See below
- for more information.)
-
-
-
- 2.7.3 4 BYTE BOUNDARY
-
- There is one problem left. (Who said it should be easy?)
- AmigaDOS was not, as everything else on the Amiga, written in
- C. They used the BCPL programming language which is the
- predecessor of C. The problem is that BCPL only uses one data
- type - longword (LONG). ALL data which is handled by AmigaDOS
- must therefore be on a "4 byte boundary". (Are you with me?) To
- make sure that a structure starts on a 4 byte boundary you
- need to allocate the memory by using the function AllocMem().
- (Remember to deallocate the memory once you do not need it any
- more!)
-
- So instead of writing:
-
- --------------------------------------------------------------
- struct FileInfoBlock fib; /* Declare a FileInfoBlock called */
- /* fib. This structure may NOT */
- /* necessary start on a 4 byte */
- /* boundary! */
- --------------------------------------------------------------
-
- You write:
-
- --------------------------------------------------------------
- struct FileInfoBlock *fib_ptr; /* Declare a FileInfoBlock */
- /* pointer called fib_ptr. */
-
- /* Allocate enough memory for a FileInfoBlock structure: */
- /* This memory WILL be on a 4 byte boundary! */
- fib_ptr = AllocMem( sizeof( struct FileInfoBlock ),
- MEMF_PUBLIC | MEMF_CLEAR )
-
- /* Check if we have allocated the memory successfully: */
- if( fib_ptr == NULL )
- exit(); /* NOT ENOUGH MEMORY! */
-
-
- ... your program ...
-
-
- /* Deallocate the memory we have allocated for the fib. struct: */
- FreeMem( fib_ptr, sizeof( struct FileInfoBlock ) );
-
- --------------------------------------------------------------
-
-
-
- 2.7.4 EXAMPLE
-
- Here is an example which shows how to use the Examine()
- function: (Remember to deallocate all allocated memory and to
- unlock all locked files when your program terminates!)
-
- #include <libraries/dos.h>
- #include <exec/memory.h>
-
- main()
- {
- struct FileLock *lock;
- struct FileInfoBlock *fib_ptr; /* Declare a FileInfoBlock */
- /* pointer called fib_ptr. */
-
-
- /* 1. Allocate enough memory for a FileInfoBlock structure: */
- fib_ptr = AllocMem( sizeof( struct FileInfoBlock ),
- MEMF_PUBLIC | MEMF_CLEAR )
-
- /* Check if we have allocated the memory successfully: */
- if( fib_ptr == NULL )
- exit(); /* NOT ENOUGH MEMORY! */
-
-
- /* 2. Try to lock the file: */
- lock = Lock( "highscore.dat", SHARED_LOCK )
-
- /* Could we lock the file? */
- if( lock == NULL )
- {
- /* Deallocate the memory we have allocated: */
- FreeMem( fib_ptr, sizeof( struct FileInfoBlock ) );
-
- exit();
- }
-
-
- /* 3. Try to get some information about the file: */
- if( Examine( lock, fib_ptr ) == NULL )
- {
- /* Deallocate the memory we have allocated: */
- FreeMem( fib_ptr, sizeof( struct FileInfoBlock ) );
-
- /* Unlock the file: */
- UnLock( lock );
-
- exit();
- }
-
-
- /* 4. You may now examine the FileInfoBlock structure! */
-
-
- /* 5. Unlock the file: */
- UnLock( lock );
-
-
- /* 6. Deallocate the memory we have allocated: */
- FreeMem( fib_ptr, sizeof( struct FileInfoBlock ) );
- }
-
-
-
- 2.7.5 EXAMINE FILES/SUBDIRECTORIES IN A DIRECTORY/DEVICE
-
- A directory/device can contain several files plus several
- (sub)directories. If you want to examine not only a file/
- directory, but all files/directories in a directory/device the
- Examine() function is not enough. You need to use the function
- ExNext(), which works together with the Examine function.
-
- To examine a directory/device you first need to call the
- function Examine() as normal. If it was a directory/device you
- start calling the function ExNext(), and continue calling it
- until you receive an error message. The error message is
- normally an "end of directory" message, which means that you
- have examined everything in the directory/device. It can also
- be some other error message which indicates that something
- went wrong while reading.
-
-
-
- 2.7.5.1 EXNEXT()
-
- The ExNext() function is very similar to Examine(). It is
- called like this:
-
- Synopsis: ok = ExNext( lock, fib_ptr );
-
- ok: (long) Actually a Boolean. It is TRUE if AmigaDOS
- could get information about a file/directory in the
- directory/device, else FALSE which means something
- went wrong.
-
- lock: (BPTR) Actually a pointer to a FileLock structure.
-
- fib_ptr: (struct FileInfoBlock *) Pointer to a FileInfoBlock
- structure which will be initialized with some
- information about the file/directory. IMPORTANT! the
- structure must be on a 4 byte boundary. (See above
- for more information.)
-
- Remember that you first need to call the function Examine(),
- and if it was a directory/device (fib_DirEntryType > 0), you
- may call the function ExNext() until you receive an error
- message.
-
-
-
- 2.7.5.2 ERROR MESSAGES
-
- When you have used an AmigaDOS function, and you have received
- an error message, you can call the function IoErr() to find out
- what went wrong. You do not send IoErr() any parameters, it
- only returns a flag (value) which tells your program what went
- wrong.
-
- Here is the complete (V1.3) error list: (The header file
- "libraries/dos.h" contains the definitions.) I do not think I
- need to explain what they mean.
-
- ERROR_NO_FREE_STORE
- ERROR_TASK_TABLE_FULL
- ERROR_LINE_TOO_LONG
- ERROR_FILE_NOT_OBJECT
- ERROR_INVALID_RESIDENT_LIBRARY
- ERROR_NO_DEFAULT_DIR
- ERROR_OBJECT_IN_USE
- ERROR_OBJECT_EXISTS
- ERROR_DIR_NOT_FOUND
- ERROR_OBJECT_NOT_FOUND
- ERROR_BAD_STREAM_NAME
- ERROR_OBJECT_TOO_LARGE
- ERROR_ACTION_NOT_KNOWN
- ERROR_INVALID_COMPONENT_NAME
- ERROR_INVALID_LOCK
- ERROR_OBJECT_WRONG_TYPE
- ERROR_DISK_NOT_VALIDATED
- ERROR_DISK_WRITE_PROTECTED
- ERROR_RENAME_ACROSS_DEVICES
- ERROR_DIRECTORY_NOT_EMPTY
- ERROR_TOO_MANY_LEVELS
- ERROR_DEVICE_NOT_MOUNTED
- ERROR_SEEK_ERROR
- ERROR_COMMENT_TOO_BIG
- ERROR_DISK_FULL
- ERROR_DELETE_PROTECTED
- ERROR_WRITE_PROTECTED
- ERROR_READ_PROTECTED
- ERROR_NOT_A_DOS_DISK
- ERROR_NO_DISK
- ERROR_NO_MORE_ENTRIES
-
-
- The IoErr() function is called like this:
-
- Synopsis: error = IoErr();
-
- error: (long) This field contains one of the above
- mentioned flags.
-
-
- So when you use the function ExNext(), and you receive and
- error message, you should call the function IoErr to check
- what went wrong. If it was not ERROR_NO_MORE_ENTRIES (you
- have checked everything in the directory), something terrible
- went wrong (error while reading).
-
-
-
- 2.7.5.3 EXAMPLE
-
- Here is parts of a program that examines everything inside a
- directory/device, and prints out the filenames:
-
- if( Examine( lock, fib_ptr ) )
- {
- if( fib_ptr->fib_DirEntryType > 0 )
- {
- printf("Directory name: %s\n", fib_ptr->fib_FileName );
-
- while( ExNext( lock, fib_ptr ) )
- {
- printf("name: %s\n", fib_ptr->fib_FileName );
- }
-
- if( IoErr() == ERROR_NO_MORE_ENTRIES )
- printf("End of directory!\n");
- else
- printf("ERROR WHILE READING!!!\n");
- }
- else
- printf("This is a file!\n");
- }
- else
- printf("Could not examine the directory/device!\n");
-
-
-
- 2.8 FUNCTIONS
-
- Here is a list of commonly used functions:
-
- Open()
-
- This function opens a file. Remember, before you can read/
- write files you have to open them.
-
- Synopsis: file_handle = Open( file_name, mode );
-
- file_handle: (BPTR) Actually a pointer to a FileHandle
- structure. If the system could not open the file
- with our requirements Open() returns NULL.
-
- file_name: (char *) Pointer to a text string which contains
- the file name including any necessary devices/
- directories.
-
- mode: (long) When you open a file you need to tell the
- system what you are going to do with it. This
- field should therefore contain one of the
- following flags:
-
- MODE_OLDFILE: Opens an existing file for
- reading and writing.
-
- MODE_NEWFILE: Opens a new file for writing.
- (If the file already exist it
- is deleted.)
-
- MODE_READWRITE: Opens an old file with an
- exclusive lock. (The file is
- automatically locked with an
- EXCLUSIVE_LOCK.)
-
- MODE_READONLY: Same as MODE_OLDFILE.
-
-
- Close()
-
- This function closes an already opened file. Remember to
- close ALL files you have opened!
-
- Synopsis: Close( file_handle );
-
- file_handle: (BPTR) Actually a pointer to a FileHandle
- structure which has been initialized by a
- previous Open() call.
-
-
- Read()
-
- This function reads a specified number of bytes from a file.
-
- Synopsis: bytes_read = Read( file_handle, buffer, size );
-
- bytes_read: (long) Number of bytes actually read. Even if
- you tell AmigaDOS that you want to read x
- number of bytes, it is not certain that you
- actually can do it. The file is maybe corrupted,
- not as big as you thought etc.
-
- file_handle: (BPTR) Actually a pointer to a FileHandle
- structure which has been initialized by a
- previous Open() call.
-
- buffer: (char *) Pointer to the data buffer you want to
- read the data into.
-
- size: (long) Number of bytes you want to read.
-
-
- Write()
-
- This function writes a specified number of bytes to a file.
-
- Synopsis: bytes_wr = Write( file_handle, buffer, size );
-
- bytes_wr: (long) Number of bytes actually written. Even if
- you tell AmigaDOS that you want to write x number
- of bytes, it is not certain that you actually
- can do it. Maybe the disk was full, write-
- protected etc.
-
- file_handle: (BPTR) Actually a pointer to a FileHandle
- structure which has been initialized by a
- previous Open() call.
-
- buffer: (char *) Pointer to the data buffer which you
- want to write.
-
- size: (long) Number of bytes you want to write.
-
-
- Seek()
-
- This function moves the "file cursor" inside a file:
-
- Synopsis: old_pos = Seek( file_handle, new_pos, mode );
-
- old_pos: (long) Previous position in the file, or -1 if
- an error occurred.
-
- file_handle: (BPTR) Actually a pointer to a FileHandle
- structure which has been initialized by a
- previous Open() call.
-
- new_pos: (long) New position relative to the "mode".
-
- mode: (long) The new_pos can be relative to:
- OFFSET_BEGINNING: Beginning of the file.
- OFFSET_CURRENT: Current position.
- OFFSET_END: The end of the file.
-
-
- Lock()
-
- This function "locks" a file so no other processes may alter
- the contents (SHARED_LOCK). You can even prevent other
- processes to read the file (EXCLUSIVE_LOCK).
-
- Synopsis: lock = Lock( name, mode );
-
- lock: (BPTR) Actually a pointer to a FileLock structure.
-
- name: (char *) Pointer to a text string which contains
- the file/directory name.
-
- mode: (long) Accessmode:
- SHARED_LOCK: Other tasks may read the file.
- ACCESS_READ: - " -
- EXCLUSIVE_LOCK: No other tasks may use this f.
- ACCESS_WRITE: - " -
-
-
- UnLock()
-
- This function unlocks a previously locked file: (Remember to
- unlock ALL files you have locked!)
-
- Synopsis: Unlock( lock );
-
- lock: (BPTR) Actually a pointer to FileLock structure
- which has been initialized by a previous Lock()
- call.
-
-
- Rename()
-
- This function renames a file or directory. You can even
- move a file between directories by renaming it. (For example,
- Rename( "df0:Documents/Sale.doc", "df0:Letters/Sale.doc" );
- will move the file Sale.doc from the directory "Documents"
- to directory "Letters". Note! You can not rename a file from
- one volume to another.)
-
- Synopsis: ok = Rename( old_name, new_name );
-
- ok: (long) Actually a Boolean. It is TRUE if AmigaDOS
- could rename the file/directory, else FALSE which
- means something went wrong. (Eg. disk write
- -protected.)
-
- old_name: (char *) Pointer to a string containing the old
- file/directory name.
-
- new_name: (char *) Pointer to a string containing the new
- file/directory name.
-
-
- SetComment
-
- This function attach a comment to a file or directory.
-
- Synopsis: ok = SetComment( name, comment );
-
- ok: (long) Actually a Boolean. It is TRUE if AmigaDOS
- could attach the new comment, else FALSE which
- means something went wrong. (Eg. disk write-
- protected.)
-
- name: (char *) Pointer to a string containing the name
- of the file/directory you want to attach the
- comment to.
-
- comment: (char *) Pointer to a string containing the
- comment. (A comment may be up to 80 characters
- long.)
-
-
- SetProtection()
-
- This function alters the protection bits of a file.
- You can set following flags:
-
- FIBF_DELETE : the file/directory can not be deleted.
- FIBF_EXECUTE : the file can not be executed.
- FIBF_WRITE : you can not write to the file.
- FIBF_READ : you can not read the file.
- FIBF_ARCHIVE : Archive bit.
- FIBF_PURE : Pure bit.
- FIBF_SCRIPT : Script bit.
-
- (Note! All of the flags are for the moment not working!)
-
- Synopsis: ok = SetProtection( name, mask );
-
- ok: (long) Actually a Boolean. It is TRUE if AmigaDOS
- could alter the protection bits, else FALSE which
- means something went wrong. (Eg. disk write-
- protected.)
-
- name: (char *) Pointer to a string containing the name
- of the file/directory you want to change the
- protection bits.
-
- mask: (long) The protection bits. (For example, if you
- want to make the file/directory not deletable,
- and that it can not be executed you should set the
- protection bits: FIBF_DELETE | FIBF_EXECUTE.)
-
-
- DeleteFile()
-
- This function deletes a file or directory. Remember that
- a directory must be empty before it can be deleted.
-
- Synopsis: ok = DeleteFile( name );
-
- ok: (long) Actually a Boolean. It is TRUE if AmigaDOS
- could delete the file/directory, else FALSE which
- means something went wrong. (Eg. disk write-
- protected, directory not empty etc.)
-
- name: (char *) Pointer to a string containing the name
- of the file/directory you want to delete.
-
-
- CreateDir()
-
- This function creates a new directory, AND "locks" is
- automatically. (Remember to unlock the directory later on.)
-
- Synopsis: lock = CreateDir( name );
-
- lock: (BPTR) Actually a pointer to a FileLock structure.
- If lock is equal to NULL, AmigaDOS have not been
- able to create the new directory.
-
- name: (char *) Pointer to a string containing the name
- of the new directory.
-
-
- CurrentDir()
-
- This function makes a specified directory "current
- directory". You need to lock the new directory (new_lock)
- before you can make it the current directory. The function
- returns the old current directories lock so you can unlock
- it if necessary.
-
- Synopsis: old_lock = CurrentDir( new_lock );
-
- old_lock: (BPTR) Actually a pointer to a FileLock structure.
- It is the old current directory lock.
-
- new_lock: (BPTR) Actually a pointer to a FileLock structure.
- The new current directory lock.
-
-
- Info()
-
- This function returns information about a specified disk. You
- specify which disk by either lock that disk, or a file/
- directory on that disk.
-
- Synopsis: ok = Info( lock, info_data );
-
- ok: (long) Actually a Boolean. It is TRUE if AmigaDOS
- could get information about the disk, else FALSE
- which means something went wrong.
-
- lock: (BPTR) Actually a pointer to a FileLock structure.
-
- info_data: (struct InfoData *) Pointer to an InfoData
- structure which will be initialized by the Info()
- function. The problem with this structure is that
- it must be on a four byte boundary, so you need
- to use the function AllocMem() to get the right
- type of memory for the structure. (See Example.)
-
-
- IoErr()
-
- This function can be used to get more information about an
- error message. Whenever you have used an AmigaDOS function
- which did not work properly (you have received an error
- message), you call this function and it will return an
- explanation.
-
- Synopsis: error = IoErr();
-
- error: (long) This field contains a flag returned by
- IoErr() which can be: (I do not think I need
- to explain what they mean.)
-
- ERROR_NO_FREE_STORE
- ERROR_TASK_TABLE_FULL
- ERROR_LINE_TOO_LONG
- ERROR_FILE_NOT_OBJECT
- ERROR_INVALID_RESIDENT_LIBRARY
- ERROR_NO_DEFAULT_DIR
- ERROR_OBJECT_IN_USE
- ERROR_OBJECT_EXISTS
- ERROR_DIR_NOT_FOUND
- ERROR_OBJECT_NOT_FOUND
- ERROR_BAD_STREAM_NAME
- ERROR_OBJECT_TOO_LARGE
- ERROR_ACTION_NOT_KNOWN
- ERROR_INVALID_COMPONENT_NAME
- ERROR_INVALID_LOCK
- ERROR_OBJECT_WRONG_TYPE
- ERROR_DISK_NOT_VALIDATED
- ERROR_DISK_WRITE_PROTECTED
- ERROR_RENAME_ACROSS_DEVICES
- ERROR_DIRECTORY_NOT_EMPTY
- ERROR_TOO_MANY_LEVELS
- ERROR_DEVICE_NOT_MOUNTED
- ERROR_SEEK_ERROR
- ERROR_COMMENT_TOO_BIG
- ERROR_DISK_FULL
- ERROR_DELETE_PROTECTED
- ERROR_WRITE_PROTECTED
- ERROR_READ_PROTECTED
- ERROR_NOT_A_DOS_DISK
- ERROR_NO_DISK
- ERROR_NO_MORE_ENTRIES
-
-
- Examine()
-
- This function can be used to get information about a file,
- directory or device.
-
- Synopsis: ok = Examine( lock, fib_ptr );
-
- ok: (long) Actually a Boolean. It is TRUE if AmigaDOS
- could get information about the file/directory,
- else FALSE which means something went wrong.
-
- lock: (BPTR) Actually a pointer to a FileLock structure.
-
- fib_ptr: (struct FileInfoBlock *) Pointer to a FileInfoBlock
- structure which will be initialized with some
- information about the file/directory. IMPORTANT!
- the structure must be on a 4 byte boundary.
-
-
- ExNext()
-
- This function should be used when you want to examine a
- directory. You should first use the function Examine() to
- see if it is a directory/device or if it simply is a file.
- If it is a directory/device (fib_DirEntryType > 0), you may
- call the ExNext() function until you receive an error
- message.
-
- Synopsis: ok = ExNext( lock, fib_ptr );
-
- ok: (long) Actually a Boolean. It is TRUE if AmigaDOS
- could get information about a file/directory in the
- directory/device, else FALSE which means something
- went wrong.
-
- lock: (BPTR) Actually a pointer to a FileLock structure.
-
- fib_ptr: (struct FileInfoBlock *) Pointer to a FileInfoBlock
- structure which will be initialized with some
- information about the file/directory. IMPORTANT!
- the structure must be on a 4 byte boundary.
-
-
-
- Delay()
-
- This function will put your program to sleep for a specified
- time period. Note that this function should be used instead
- of a "dummy" loop when you want to pause a program. The
- problem with wait loops is that the time it takes to execute
- it depends on how fast the computer is. If you want to wait
- for a while you should use this function since the delay time
- will then always be the same no matter how fast or slow
- the computer is. A dummy loop will also waist a lot of
- processor time while the nice Delay() function will put your
- task to sleep so the processor can work with other things.
-
- Synopsis: Delay( time );
-
- time: (ULONG) How long time you want to wait. The value
- is specified in "timer units" were 50 units is
- equal to 1 second. If you want to wait two minutes
- you should set this field to 2 * 60 * 50 = 6000.
-
-
-
- 2.9 EXAMPLES
-
- Example1
- This program collects ten integer values from the user, and
- saves them in a file ("HighScore.dat") on the RAM disk. The
- memory is then cleared, and the file cursor is moved to the
- beginning of the file. The file is then loaded into the
- memory again, and printed out.
-
- Example2
- This example demonstrates how to create a directory called
- "MyDirectory" on the RAM disk.
-
- Example3
- This example demonstrates how to rename files and directories.
- It will rename the file Example 1 created (called
- "HighScore.dat") to "Numbers.dat". It will also rename the
- directory Example 2 created ("MyDirectory") to "NewDirectory".
-
- Example4
- This example demonstrates how to delete files and directories.
- It will delete the file Example 1 and directory Example 2
- created. (The file and directory are supposed to have been
- renamed by Example 3.)
-
- Example5
- This example demonstrates how to attach a short comment to a
- file. A short file called "Letter.doc" will be created, and a
- short comment will be attached. To see the comment use the
- CLI command "List".
-
- Example6
- This example demonstrates how to protect and unprotect files.
- The file Example 5 created ("Letter.doc") will be protected,
- and we will then try to delete it (unsuccessfully). We will
- then unprotect the file and then try to delete it
- (successfully).
-
- Example7
- This program takes a file/directory/device name as
- parameter, and prints out some interesting information about
- it.
-
- Example8
- This program takes a directory/device name as parameter,
- and prints out all the file/directory-names inside it. This
- example describes how to use Examine() and ExNext().
-