GEOS SDK TechDocs
|
|
5.5 FileEnum()
There are several routines designed for working with files as a string of bytes. These routines may be used to work with DOS files or with GEOS byte files. You can open any file (including an executable file or a VM file) for byte-level access. This may be useful for such things as file-compression routines; however, be aware that if you make any changes to such files, you could invalidate them. For this reason, if you open a VM or executable file for byte-level access, you should open it for read-only use.
FileOpen(), FileCreate(), FileCreateTempFile(), FileClose(), FileAccessFlags
The GEOS file system provides several routines for opening files for byte-level access. If you are working with GEOS Virtual Memory files, you should use the appropriate VM routines to open and close the files (see the VM chapter). You should use the byte-level routines only if you are working with DOS files or with GEOS byte files. You may occasionally want to read a VM file or an executable file as a string of bytes. In this rare case, you must use the routines in this section. Note, however, that you should not change the VM file with these routines; it is safe only to open it for read-only access.
To open a file, call
FileOpen()
. This routine takes two arguments: a set of
FileAccessFlags
and a pointer to a null-terminated string. The string should specify the name of the file (either the virtual name or the native name may be used). It may simply be a file name, or it may be a relative or absolute path. The
FileAccessFlags
record specifies two things: what kind of access the caller wants, and what type of access is permitted to other geodes.
A set of
FileAccessFlags
is thus a bit-wise OR of two different values. The first specifies what kind of access the calling geode wants and has the following values:
The second part specifies what kind of access other geodes may have. Note that if you try to deny a permission which has already been given to another geode (e.g. you open a file with FILE_DENY_W when another geode has the file open for write-access), the call will fail. The following permissions can be used:
Two flags, one from each of these sets of values, are combined to make up a proper
FileAccessFlags
value. For example, to open the file for read-only access while prohibiting other geodes from writing to the file, you would pass the flags FILE_ACCESS_R and FILE_DENY_W as follows:
myHandle = FileOpen("MyFile",
(FILE_ACCESS_R | FILE_DENY_W));
If successful,
FileOpen()
returns the file's handle. If it is unsuccessful, it returns a null handle and sets the thread's error value. The following error values are commonly returned:
FileOpen()
will fail until a file is closed.
Note that if you use the document control objects, they automatically make all appropriate calls to
FileOpen()
when the user requests it; you will automatically be passed the file's handle.
FileOpen()
can only be called if the file already exists.
In order to create a byte file, you must call
FileCreate()
.
FileCreate()
takes four arguments: a set of
FileCreateFlags
, a set of
FileAccessFlags
, a set of
FileAttrs
, and a pointer to a string containing a name for the file.
As with
FileOpen()
, the name may be a name alone or a relative or absolute path. The
FileCreateFlags
specifies whether the file should be created if it already exists. The following flags are available:
FileCreate()
will fail with error condition ERROR_FILE_FORMAT_MISMATCH.
The first three flags (FILE_CREATE_...) are mutually exclusive; exactly one of them must be passed to
FileCreate()
. That flag may or may not be combined with FCF_NATIVE.
The
FileAccessFlags
are the same as described in
FileOpen()
. Note, however, that you must request either write access or read/write access when you use
FileCreate()
.
Every file has a set of attributes. These record certain information about the file. If you create a file, you will need to specify values for these attributes. The attributes are described above in the section on FEA_FILE_ATTR .
If
FileCreate()
is successful, it will open the file and return its handle. If it fails, it will return a null handle and set the thread's error value. It may return any of the
FileOpen()
errors. It may also return the following errors:
FileCreate()
was called with FILE_CREATE_ONLY and a file with the specified name already exists.
FileCreate()
was called with FILE_CREATE_TRUNCATE or FILE_CREATE_NO_TRUNCATE and a file exists in a different format than desired; i.e. you passed FCF_NATIVE and the file already exists in the GEOS format, or vice versa.
It is often useful to create temporary files which are not seen by the user. In these cases, you generally don't care about the file's name since you will most likely be deleting the file on exit. For these situations GEOS provides the routine
FileCreateTempFile()
.
FileCreateTempFile()
is passed a directory; it chooses a unique name for the file. This routine takes two arguments:
FileAttrs
, as described above.
FileCreateTempFile()
will write the name of the temporary file at the end of the string. Temporary files are typically created in SP_WASTE_BASKET.
If successful,
FileCreateTempFile()
will open the temporary file and return its handle. It will also write the file's name to the end of the string passed. You will need to know the name to delete the file. The name is also useful if GEOS shuts down while a temporary file is open; the geode will need to know the temporary file's name in order to reopen it.
When you are done with a file, you should close it by calling
FileClose()
. This releases any restrictions you may have placed on the file and allows the file to be moved or deleted. It is passed two arguments: the file handle and a Boolean value which should be set to
true
(i.e. non-zero) if the geode cannot handle error messages; it will cause
FileClose()
to fatal-error if it cannot successfully close the file. (This should only be used during development; the flag should never be passed in a finished program.) The routine returns zero if successful; otherwise, it returns a
FileError
value.
FileRead(), FileWrite(), FilePos(), FileCommit()
There are a few specific operations you are allowed to perform on data in a byte-file. You can copy data from the file into memory; you can copy data from memory into the file, overwriting the file's contents; you can write data to the end of a file; and you can cut data from the end of the file. If you want to perform more elaborate manipulations on a byte-file, you may wish to create a temporary VM file and copy the data there (see the VM chapter).
Every file handle has a file position associated with it. All read and write operations begin at that position; they may also change the position. The first byte in a file is considered to be at position zero. If the file is a GEOS byte file, position zero is immediately after the GEOS header; thus, the header cannot be accessed or altered via the read and write operations.
To read data from a file, call
FileRead()
. This routine takes four arguments. The first is the file's handle. The second is the address of a buffer.
FileRead()
will copy the requested number of bytes from the file to the buffer. The third is the number of bytes to read. The fourth is a Boolean indicating whether the caller can handle errors. (This is
true
if the geode cannot handle error messages; it will cause
FileRead()
to fatal-error if it cannot successfully read the data. This should only be used during development; the flag should never be passed in a finished program.)
FileRead()
returns the number of bytes actually read. This may be less than the number requested, if the end of file is reached; in this case, the thread's error value will be set to ERROR_SHORT_READ_WRITE. If
FileRead()
was unable to gain access to the file, it will return -1 and set the thread's error value to ERROR_ACCESS_DENIED. In any event, the file position will be incremented by the number of bytes read; thus, it will point to the first byte after the data read.
To write data to a file, call
FileWrite()
. This routine takes four arguments. The first is the file's handle. The second is the address of a buffer in memory. The third is the number of bytes to write. The fourth is a Boolean indicating whether the caller can handle errors.
FileWrite()
will copy the specified number of bytes from the buffer to the file, starting at the current position and expanding the file as necessary. It will also increment the current position by the number of bytes written. If the current position is not at the end of the file,
FileWrite()
will overwrite the file's existing data.
FileWrite()
returns the number of bytes written. This may be less than the number requested, if the disk ran out of space; in this case, the thread's error value will be set to ERROR_SHORT_READ_WRITE. If
FileWrite()
could not get access to the file (as, for example, if the geode had read-only access to the file), it will return -1 and set the thread's error value to ERROR_ACCESS_DENIED.
If a file is on a removable disk, the kernel will make sure that the disk is in the appropriate drive before reading from or writing to it. If the disk is not in the drive, the kernel will prompt the user to insert it. The user will have the option of aborting the operation; this will result in the file-access routine failing with error condition ERROR_DISK_UNAVAILABLE.
When you write changes to a file, either the GEOS file system or the underlying DOS may choose to cache those changes to save time. All cached changes will be written to the disk when the file is closed. However, you can force the cached changes to be written immediately by calling
FileCommit()
. This routine takes two arguments. The first is the file's handle. The second is a Boolean indicating whether the caller can handle errors. The routine returns zero if the operation was successful; otherwise it returns an error code.
To change the current file position, call
FilePos()
. This routine takes three arguments. The first is the file handle.
The second is a member of the
FilePosMode
enumerated type; this value indicates how the new position is specified. The third argument is a number of bytes; it specifies how far the file position will be moved.
FilePosMode
has the following possible values:
FilePos()
returns a 32-bit integer. This integer specifies the file position after the move (relative to the start of the file). To find out the current file position without changing it, call
FilePos()
with mode FILE_POS_RELATIVE and offset zero.
FileGetDateAndTime(), FileSetDateAndTime(), FileGetAttributes(), FileSetAttributes()
GEOS provides several routines to get information about files. To get information about a GEOS file, you would ordinarily use one of the extended attributes routines (see GEOS Extended Attributes ). These routines are ordinarily used for non-GEOS files. Nevertheless, all of the following routines can be used on GEOS files.
FileGetDateAndTime()
and
FileSetDateAndTime()
are used to get and set the file's modification time. To access a GEOS file's modification time, you would ordinarily call an extended attribute routine, passing FEA_MODIFICATION. However, special-purpose routines are provided specifically for changing a file's modification time. Note that these routines may be used for GEOS or non-GEOS files. Similarly, you can change the FEA_MODIFICATION attribute even for non-GEOS files. To find out the modification time, call
FileGetDateAndTime()
. This routine is passed the file's handle and returns a
FileDateAndTime
value (as described above on FEA_MODIFICATION
). To change the modification time, call
FileSetDateAndTime()
. This routine is passed the file's handle and a
FileDateAndTime
value. If successful, it returns zero; otherwise, it returns an error code. You must have write permission to change the modification time; otherwise,
FileSetDateAndTime()
will fail with condition ERROR_ACCESS_DENIED.
The
TimerGetFileDateTime()
routine returns the current date and time in a
FileDateAndTime
structure.
To find out a DOS file's attributes, call
FileGetAttributes()
. This routine is passed a file's path.
It returns the file's
FileAttrs
record (as described on FEA_FILE_ATTR
). To change the file's attributes, call
FileSetAttributes()
. This routine takes two arguments: the address of a null-terminated path string and a
FileAttrs
record. It returns zero if it was successful; otherwise, it returns an error condition. Note that a file's attributes cannot be changed if the file is open.
FileLockRecord(), FileUnlockRecord()
GEOS provides routines to help threads synchronize file access. This functionality is very elaborate for VM files. For byte files it is less so. Several threads can synchronize their access to a single handle by using
HandleP()
and
HandleV()
, described in the Memory Management chapter. If they want to use the file at the same time, they should use FileLockRecord()
and
FileUnlockRecord()
.
FileLockRecord()
takes three arguments: the file handle, a dword specifying the start of the region to be locked, and a dword specifying the length (in bytes) of the region to be locked. If there are no locks on any part of that region,
FileLockRecord()
returns zero; otherwise, it returns the error code ERROR_ALREADY_LOCKED. Note that there is nothing to stop another thread or geode from reading or writing to that region. The lock simply prevents anyone from
locking
that region with
FileLockRecord()
. The file's users have to remember to lock any part of the file before accessing it.
To release a lock on a part of a file, call
FileUnlockRecord()
. This routine takes the same arguments as
FileLockRecord()
.
GEOS SDK TechDocs
|
|
5.5 FileEnum()