When you open a file using the File folio OpenDiskFile()
function, the item that is returned serves as a handle to the file. The Item
is of type Device. This enables communication to the filesystem that controls this file using the standard Portfolio I/O model.
When you send a command to a file device, the file system responsible for the file wakes up and executes the command. Therefore, the file device is only a pseudo-device, serving as a gateway to the underlying filesystem.
The File folio provides many high-level functions to control file systems. For example, you can create files using the CreateFile()
function, or you can delete files using the DeleteFile()
function. These File folio functions are merely wrappers for file system commands. The functions internally create file devices and send commands to the device to perform work.
This section explains the various commands you can send to a file device. It is often much easier to use the higher-level File folio functions to interact with the file system. However, there are some operations that can only be performed by interfacing to the file device directly.
FILECMD_FSSTAT
command.
Once the command returns successfully, you can look at the fields in the fsStat structure for the status information. The
IOInfo ioInfo;
FileSystemStat fsStat;
memset(&ioInfo,0,sizeof(ioInfo));
ioInfo.ioi_Command = FILECMD_FSSTAT;
ioInfo.ioi_Recv.iob_Buffer = &fsStat;
ioInfo.ioi_Recv.iob_Len = sizeof(FileSystemStat);
fst_BitMap
field of the FileSystemStat structure indicates which fields in the rest of the structure are valid and can be examined. Different file systems cannot always provide all the information in a FileSystemStat structure. For example, if the FSSTAT_SIZE
bit is set in fst_BitMap
, it means the fst_Size
field of the FileSystemStat structure is valid.
The fields in the FileSystemStat structure are:
CMD_STATUS
command.
Once the command completes successfully, you can look at the fields in the fStat structure for the status information. Fields of interest are:
IOInfo ioInfo;
FileStatus fStat;
memset(&ioInfo,0,sizeof(ioInfo));
ioInfo.ioi_Command = CMD_STATUS;
ioInfo.ioi_Recv.iob_Buffer = &fStat;
ioInfo.ioi_Recv.iob_Len = sizeof(FileStatus);
CreateFile()
function. You supply the path name of the file to create, and the function does the necessary work to create a new file entry on the filesystem.
To delete an existing file, use the File folio's DeleteFile()
function. You supply it the path name of the file to delete, and the function does the necessary work to remove the file's entry from the filesystem.
FILECMD_ALLOCBLOCKS
command.
The
IOInfo ioInfo;
memset(&ioInfo,0,sizeof(ioInfo));
ioInfo.ioi_Command = FILECMD_ALLOCBLOCKS;
ioInfo.ioi_Offset = numBlocks;
numBlocks
variable contains the number of blocks by which to extend the file. If this value is negative, the size of the file is reduced by the specified number of blocks.
CMD_WRITE
command to write data to a file. All write operations must be performed in full blocks. The size of the blocks can be obtained by sending a CMD_STATUS
command to the file device. The write operation must also be aligned on a block boundary within the file.
The
IOInfo ioInfo;
memset(&ioInfo,0,sizeof(ioInfo));
ioInfo.ioi_Command = CMD_WRITE;
ioInfo.ioi_Offset = blockOffset;
ioInfo.ioi_Send.iob_Buffer = dataAddress;
ioInfo.ioi_Send.iob_Len = numBytes;
blockOffset
field indicates the offset in blocks from the beginning of the file where the data is to be written. The dataAddress
value points to the data that is to be written. Finally, the numBytes
value indicates the number of bytes to write out. This value must be an even multiple of the block size for the file.
FILECMD_SETEOF
command. This command tells the filesystem how many useful bytes of data are in the file. Because you can only transfer data in terms of blocks, sending this command tells the filesystem how many bytes of the last written block are useful bytes.
IOInfo ioInfo;
memset(&ioInfo,0,sizeof(ioInfo));
ioInfo.ioi_Command = FILECMD_SETEOF;
ioInfo.ioi_Offset = numBytesInFile;
The
IOInfo ioInfo;
memset(&ioInfo,0,sizeof(ioInfo));
ioInfo.ioi_Command = CMD_READ;
ioInfo.ioi_Offset = blockOffset;
ioInfo.ioi_Recv.iob_Buffer = dataAddress;
ioInfo.ioi_Recv.iob_Len = numBytes;
blockOffset
value indicates the offset in blocks from the beginning of the file from which data is read. dataAddress
indicates an address in memory where the data will be copied once read from the filesystem. Finally, numBytes
contains the number of bytes to read. This number must be an even multiple of the block size of the file.
OpenDiskFile()
function
opens a directories. You can then use the FILECMD_READDIR
command to scan the directory and obtain information about files in the directory.
The
IOInfo ioInfo;
DirectoryEntry dirEntry;
memset(&ioInfo,0,sizeof(ioInfo));
ioInfo.ioi_Command = FILECMD_READDIR;
ioInfo.ioi_Offset = fileNum;
ioInfo.ioi_Recv.iob_Buffer = &dirEntry;
ioInfo.ioi_Recv.iob_Len = sizeof(DirectoryEntry);
fileNum
value indicates the number of the file within the directory to read. You start with file 0, and keep going until the I/O cannot be completed because there are no more files. The dirEntry structure will be filled out with information about the specified file.
FILECMD_GETPATH
command determines the exact path to an open file.
Once the command completes successfully, the path variable contains a complete unambiguous path to reach the file. You can then use this path to issue another
IOInfo ioInfo;
char path[FILESYSTEM_MAX_PATH_LEN];
memset(&ioInfo,0,sizeof(ioInfo));
ioInfo.ioi_Command = FILECMD_GETPATH;
ioInfo.ioi_Recv.iob_Buffer = path;
ioInfo.ioi_Recv.iob_Len = sizeof(path);
OpenDiskFile()
command or a DeleteFile()
command.