VxWorks Reference Manual : Libraries
dosFsLib - MS-DOS media-compatible file system library
dosFsConfigGet( ) - obtain dosFs volume configuration values
dosFsConfigInit( ) - initialize dosFs volume configuration structure
dosFsConfigShow( ) - display dosFs volume configuration data
dosFsDateSet( ) - set the dosFs file system date
dosFsDateTimeInstall( ) - install a user-supplied date/time function
dosFsDevInit( ) - associate a block device with dosFs file system functions
dosFsDevInitOptionsSet( ) - specify volume options for dosFsDevInit( )
dosFsInit( ) - prepare to use the dosFs library
dosFsMkfs( ) - initialize a device and create a dosFs file system
dosFsMkfsOptionsSet( ) - specify volume options for dosFsMkfs( )
dosFsModeChange( ) - modify the mode of a dosFs volume
dosFsReadyChange( ) - notify dosFs of a change in ready status
dosFsTimeSet( ) - set the dosFs file system time
dosFsVolOptionsGet( ) - get current dosFs volume options
dosFsVolOptionsSet( ) - set dosFs volume options
dosFsVolUnmount( ) - unmount a dosFs volume
This library provides services for file-oriented device drivers to use the MS-DOS® file standard. This module takes care of all necessary buffering, directory maintenance, and file system details.
The various routines provided by the VxWorks DOS file system (dosFs) may be separated into three broad groups: general initialization, device initialization, and file system operation.
The dosFsInit( ) routine is the principal initialization function; it need only be called once, regardless of how many dosFs devices are to be used. In addition, dosFsDateTimeInstall( ) (if used) will typically be called only once, prior to performing any actual file operations, to install a user-supplied routine which provides the current date and time.
Other dosFs functions are used for device initialization. For each dosFs device, either dosFsDevInit( ) or dosFsMkfs( ) must be called to install the device and define its configuration. The dosFsConfigInit( ) routine is provided to easily initialize the data structure used during device initialization; however, its use is optional.
Several routines are provided to inform the file system of changes in the system environment. The dosFsDateSet( ) and dosFsTimeSet( ) routines are used to set the current date and time; these are normally used only if no user routine has been installed via dosFsDateTimeInstall( ). The dosFsModeChange( ) call may be used to modify the readability or writability of a particular device. The dosFsReadyChange( ) routine is used to inform the file system that a disk may have been swapped, and that the next disk operation should first remount the disk. Finally, dosFsVolUnmount( ) informs the file system that a particular device should be synchronized and unmounted, generally in preparation for a disk change.
More detailed information on all of these routines is discussed in the following sections.
Before any other routines in dosFsLib can be used, the routine dosFsInit( ) must be called to initialize this library. This call specifies the maximum number of dosFs files that can be open simultaneously. Attempts to open more dosFs files than the specified maximum will result in errors from open( ) and creat( ).
This initialization is enabled when the configuration macro INCLUDE_DOSFS is defined; dosFsInit( ) is then called from the root task, usrRoot( ), in usrConfig.c.
To use this library for a particular device, the device descriptor structure used by the device driver must contain, as the very first item, a block device description structure (BLK_DEV). This must be initialized before calling dosFsDevInit( ). In the BLK_DEV structure, the driver includes the addresses of five routines which it must supply: one that reads one or more sectors, one that writes one or more sectors, one that performs I/O control on the device (using ioctl( )), one that checks the status of the device, and one that resets the device. These routines are described below. The BLK_DEV structure also contains fields which describe the physical configuration of the device. For more information about defining block devices, see the VxWorks Programmer's Guide: I/O System.
The dosFsDevInit( ) routine associates a device with the dosFsLib functions. It expects three parameters:
- (1)
- A pointer to a name string, to be used to identify the device. This will be part of the pathname for I/O operations which operate on the device. This name will appear in the I/O system device table, which may be displayed using the iosDevShow( ) routine.
- (2)
- A pointer to the BLK_DEV structure which describes the device and contains the addresses of the five required functions. The fields in this structure must have been initialized before the call to dosFsDevInit( ).
- (3)
- A pointer to a volume configuration structure (DOS_VOL_CONFIG). This structure contains configuration data for the volume which are specific to the dosFs file system. (See "Changes in Volume Configuration", below, for more information.) The fields in this structure must have been initialized before the call to dosFsDevInit( ). The DOS_VOL_CONFIG structure may be initialized by using the dosFsConfigInit( ) routine.
As an example:
dosFsDevInit ( char *volName, /* name to be used for volume */ BLK_DEV *pBlkDev, /* pointer to device descriptor */ DOS_VOL_CONFIG *pVolConfig /* pointer to vol config data */ )Once dosFsDevInit( ) has been called, when dosFsLib receives a request from the I/O system, it calls the device driver routines (whose addresses were passed in the BLK_DEV structure) to access the device.The dosFsMkfs( ) routine is an alternative to using dosFsDevInit( ). The dosFsMkfs( ) routine always initializes a new dosFs file system on the disk; thus, it is unsuitable for disks containing data that should be preserved. Default configuration parameters are supplied by dosFsMkfs( ), since no DOS_VOL_CONFIG structure is used.
See "Network File System (NFS) Support", below, for additional NFS-related parameters you can set before calling dosFsDevInit( ).
The sector number passed to the driver's sector read and write routines is an absolute number, starting from sector 0 at the beginning of the device. If desired, the driver may add an offset from the beginning of the physical device before the start of the logical device. This can be done by keeping an offset parameter in the driver device structure, and adding the offset to the sector number passed by the file system's read and write routines.
As a special case in open( ) and creat( ) calls, the dosFs file system recognizes a null filename as indicating access to the entire "raw" disk rather than to an individual file on the disk. (To open a device in raw mode, specify only the device name -- no filename -- during the open( ) or creat( ) call.)
Raw mode is the only means of accessing a disk that has no file system. For example, to initialize a new file system on the disk, first the raw disk is opened and the returned file descriptor is used for an ioctl( ) call with FIODISKINIT. Opening the disk in raw mode is also a common operation when doing other ioctl( ) functions which do not involve a particular file (e.g., FIONFREE, FIOLABELGET).
To read the root directory of a disk on which no file names are known, specify the device name when calling opendir( ). Subsequent readdir( ) calls will return the names of files and subdirectories in the root directory.
Data written to the disk in raw mode uses the same area on the disk as normal dosFs files and subdirectories. Raw I/O does not use the disk sectors used for the boot sector, root directory, or File Allocation Table (FAT). For more information about raw disk I/O using the entire disk, see the manual entry for rawFsLib.
On true MS-DOS machines, disk device names are typically of the form "A:", that is, a single letter designator followed by a colon. Such names may be used with the VxWorks dosFs file system. However, it is possible (and desirable) to use longer, more mnemonic device names, such as "DOS1:", or "/floppy0/". The name is specified during the dosFsDevInit( ) or dosFsMkfs( ) call.
The pathnames used to specify dosFs files and directories may use either forward slashes ("/") or backslashes ("o effect on the directory data written to the disk. (Note, however, that forward slashes are not allowed within VxWorks dosFs filenames, although they are normally legal for pure MS-DOS implementations.)
When using the VxWorks shell to make calls specifying dosFs pathnames, you must allow for the C-style interpretation which is performed. In cases where the file name is enclosed in quote marks, any backslashes must be "escaped" by a second, preceding backslash. For example:
-> copy ("DOS1:\\subdir\\file1", "file2")However, shell commands which use pathnames without enclosing quotes do not require the second backslash. For example:-> copy < DOS1:\subdir\file1Forward slashes do not present these inconsistencies, and may therefore be preferable for use within the shell.The leading slash of a dosFs pathname following the device name is optional. For example, both "DOS1:newfile.new" and "DOS1:/newfile.new" refer to the same file.
The MS-DOS standard only allows for file names which fit the restrictions of eight upper-case characters optionally followed by a three-character extension. This may not be convenient if you are transferring files to or from a remote system, or if your application requires particular file naming conventions.
To provide additional flexibility, the dosFs file system provides an option to use longer, less restricted file names. When this option is enabled, file names may consist of any sequence of up to 40 ASCII characters. No case conversion is performed and no characters have any special significance.
Because special directory entries are used on the disk, disks which use the extended names are not compatible with true MS-DOS systems and cannot be read on MS-DOS machines. Disks which use the extended name option must be initialized by the VxWorks dosFs file system (using FIODISKINIT); disks which have been initialized (software-formatted) on MS-DOS systems cannot be used.
To enable the extended file names, set the DOS_OPT_LONGNAMES bit in the dosvc_options field in the DOS_VOL_CONFIG structure when calling dosFsDevInit( ). (The dosFsMkfs( ) routine may also be used to enable extended file names; however, the DOS_OPT_LONGNAMES option must already have been specified in a previous call to dosFsMkfsOptionsSet( ).)
To enable the export of a file system, the DOS_OPT_EXPORT option must be set when initializing the device via dosFsDevInit( ) or dosFsMkfs( ). This option may also be made the default for use with disks when no explicit configuration is given. See the manual entry for dosFsDevInitOptionsSet( ).
If the remote client that will be mounting the dosFs volume is a PC-based client, you may also need to specify the DOS_OPT_LOWERCASE option. This option causes filenames to be mapped to lowercase (when not using the DOS_OPT_LONGNAMES option). This lowercase mapping is expected by many PC-based NFS implementations.
When the DOS_OPT_EXPORT option is enabled, the VxWorks NFS file system uses the reserved fields of a dosFs directory entry to store information needed to uniquely identify a dosFs file.
Every time a file is created in a directory, the directory timestamp is incremented. This is necessary to avoid cache inconsistencies in clients, because some UNIX clients use the directory timestamp to determine if their local cache needs to be updated.
You can also specify integers for a user ID, group ID, and file access permissions byte when you initialize a dosFs file system for NFS export. The values you specify will apply to all files in the file system.
Set dosFsUserId to specify the numeric user ID. The default is 65534.
Set dosFsGroupId to specify the numeric group ID. The default is 65534.
Set dosFsFileMode to specify the numeric file access mode. The default is 777.
Directories on VxWorks dosFs volumes may be searched using the opendir( ), readdir( ), rewinddir( ), and closedir( ) routines. These calls allow the names of files and subdirectories to be determined.
To obtain more detailed information about a specific file, use the fstat( ) or stat( ) routine. Along with standard file information, the structure used by these routines also returns the file attribute byte from a dosFs directory entry.
For more information, see the manual entry for dirLib.
Directory entries on dosFs volumes contain a time and date for each file or subdirectory. This time is set when the file is created, and it is updated when a file is closed, if it has been modified. Directory time and date fields are set only when the directory is created, not when it is modified.
The dosFs file system library maintains the date and time in an internal structure. While there is currently no mechanism for automatically advancing the date or time, two different methods for setting the date and time are provided.
The first method involves using two routines, dosFsDateSet( ) and dosFsTimeSet( ), which are provided to set the current date and time.
Examples of setting the date and time would be:
dosFsDateSet (1990, 12, 25); /* set date to Dec-25-1990 */ dosFsTimeSet (14, 30, 22); /* set time to 14:30:22 */The second method requires a user-provided hook routine. If a time and date hook routine is installed using dosFsDateTimeInstall( ), the routine will be called whenever dosFsLib requires the current date. This facility is provided to take advantage of hardware time-of-day clocks which may be read to obtain the current time.The date/time hook routine should be defined as follows:
void dateTimeHook ( DOS_DATE_TIME *pDateTime /* ptr to dosFs date/time struct */ )On entry to the hook routine, the DOS_DATE_TIME structure will contain the last time and date which was set in dosFsLib. The structure should then be filled by the hook routine with the correct values for the current time and date. Unchanged fields in the structure will retain their previous values.The MS-DOS specification only provides for 2-second granularity for file time stamps. If the number of seconds in the time specified during dosFsTimeSet( ) or the date/time hook routine is odd, it will be rounded down to the next even number.
The date and time used by dosFsLib is initially Jan-01-1980, 00:00:00.
Directory entries on dosFs volumes contain an attribute byte consisting of bit-flags which specify various characteristics of the entry. The attributes which are identified are: read-only file, hidden file, system file, volume label, directory, and archive. The VxWorks symbols for these attribute bit-flags are:
DOS_ATTR_RDONLY
DOS_ATTR_HIDDEN
DOS_ATTR_SYSTEM
DOS_ATTR_VOL_LABEL
DOS_ATTR_DIRECTORY
DOS_ATTR_ARCHIVEAll the flags in the attribute byte, except the directory and volume label flags, may be set or cleared using the ioctl( ) FIOATTRIBSET function. This function is called after opening the specific file whose attributes are to be changed. The attribute byte value specified in the FIOATTRIBSET call is copied directly. To preserve existing flag settings, the current attributes should first be determined via fstat( ), and the appropriate flag(s) changed using bitwise AND or OR operations. For example, to make a file read-only, while leaving other attributes intact:
struct stat fileStat; fd = open ("file", O_RDONLY, 0); /* open file */ fstat (fd, &fileStat); /* get file status */ ioctl (fd, FIOATTRIBSET, (fileStat.st_attrib | DOS_ATTR_RDONLY)); /* set read-only flag */ close (fd); /* close file */
The VxWorks dosFs file system provides efficient handling of contiguous files, meaning files which are made up of a consecutive series of disk sectors. This support includes both the ability to allocate contiguous space to a file (or directory) and optimized access to such a file when it is used.
To allocate a contiguous area to a file, the file is first created in the normal fashion, using open( ) or creat( ). The file descriptor returned during the creation of the file is then used to make an ioctl( ) call, specifying the FIOCONTIG function. The other parameter to the FIOCONTIG function is the size of the requested contiguous area in bytes. It is also possible to request that the largest contiguous free area on the disk be obtained. In this case, the special value CONTIG_MAX (-1) is used instead of an actual size.
The FAT is searched for a suitable section of the disk, and if found, it is assigned to the file. (If there is no contiguous area on the volume large enough to satisfy the request, an S_dosFsLib_NO_CONTIG_SPACE error is returned.) The file may then be closed or used for further I/O operations. For example, the following will create a file and allocate 0x10000 contiguous bytes:
fd = creat ("file", O_RDWR, 0); /* open file */ status = ioctl (fd, FIOCONTIG, 0x10000); /* get contiguous area */ if (status != OK) ... /* do error handling */ close (fd); /* close file */In contrast, the following example will create a file and allocate the largest contiguous area on the disk to it:
fd = creat ("file", O_RDWR, 0); /* open file */ status = ioctl (fd, FIOCONTIG, CONTIG_MAX); /* get contiguous area */ if (status != OK) ... /* do error handling */ close (fd); /* close file */It is important that the file descriptor used for the ioctl( ) call be the only descriptor open to the file. Furthermore, since a file may be assigned a different area of the disk than was originally allocated, the FIOCONTIG operation should take place before any data is written to the file.To determine the actual amount of contiguous space obtained when CONTIG_MAX is specified as the size, use fstat( ) to examine the file size. For more information, see dirLib.
Space which has been allocated to a file may later be freed by using ioctl( ) with the FIOTRUNC function.
Directories may also be allocated a contiguous disk area. A file descriptor to the directory is used to call FIOCONTIG, just as for a regular file. A directory should be empty (except for the "." and ".." entries) before it has contiguous space allocated to it. The root directory allocation may not be changed. Space allocated to a directory is not reclaimed until the directory is deleted; directories may not be truncated using the FIOTRUNC function.
When any file is opened, it is checked for contiguity. If a file is recognized as contiguous, more efficient techniques for locating specific sections of the file are used, rather than following cluster chains in the FAT as must be done for fragmented files. This enhanced handling of contiguous files takes place regardless of whether the space was actually allocated using FIOCONTIG.
Copies of directory entries and the FAT for each volume are kept in memory. This greatly speeds up access to files, but it requires that dosFsLib be notified when disks are changed (i.e., floppies are swapped). Two different notification mechanisms are provided.
The first, and preferred, method of announcing a disk change is for dosFsVolUnmount( ) to be called prior to removal of the disk. This call flushes all modified data structures to disk, if possible (see the description of disk synchronization below), and also marks any open file descriptors as obsolete. During the next I/O operation, the disk is remounted. The ioctl( ) call may also be used to initiate dosFsVolUnmount( ), by specifying the FIOUNMOUNT function code. (Any open file descriptor to the device may be used in the ioctl( ) call.)There may be open files or directories on a dosFs volume when it is unmounted. If this is the case, those file descriptors will be marked as obsolete. Any attempts to use them for further I/O operations will return an S_dosFsLib_FD_OBSOLETE error. To free such file descriptors, use the close( ) call, as usual. This will successfully free the descriptor, but will still return S_dosFsLib_FD_OBSOLETE. File descriptors acquired when opening the entire volume (raw mode) will not be marked as obsolete during dosFsVolUnmount( ) and may still be used.
Interrupt handlers must not call dosFsVolUnmount( ) directly, because it is possible for the dosFsVolUnmount( ) call to block while the device becomes available. The interrupt handler may instead give a semaphore which readies a task to unmount the volume. (Note that dosFsReadyChange( ) may be called directly from interrupt handlers.)
When dosFsVolUnmount( ) is called, it attempts to write buffered data out to the disk. It is therefore inappropriate for situations where the disk change notification does not occur until a new disk has been inserted. (The old buffered data would be written to the new disk.) In these circumstances, dosFsReadyChange( ) should be used.
If dosFsVolUnmount( ) is called after the disk is physically removed (i.e., there is no disk in the drive), the data-flushing portion of its operation will fail. However, the file descriptors will still be marked as obsolete, and the disk will be marked as requiring remounting. An error will not be returned by dosFsVolUnmount( ) in this situation. To avoid lost data in such a situation, the disk should be explicitly synchronized before it is removed.
Do not attempt to use dosFsVolUnmount( ) with volumes mounted using usrFdConfig( ). This routine does not return the DOS_VOL_CONFIG structure required by dosFsVolUnmount( ). Instead use ioctl( ) with FIOUNMOUNT, which accesses the volume information via the file descriptor.
The second method of informing dosFsLib that a disk change is taking place is via the "ready-change" mechanism. A change in the disk's ready status is interpreted by dosFsLib to indicate that the disk should be remounted during the next I/O operation.There are three ways to announce a ready-change. First, the dosFsReadyChange( ) routine may be called directly. Second, the ioctl( ) call may be used, with the FIODISKCHANGE function code. Finally, the device driver may set the "bd_readyChanged" field in the BLK_DEV structure to TRUE. This has the same effect as notifying dosFsLib directly.
The ready-change mechanism does not provide the ability to flush data structures to the disk. It merely marks the volume as needing remounting. As a result, buffered data (data written to files, directory entries, or FAT changes) may be lost. This may be avoided by synchronizing the disk before asserting ready-change. (The combination of synchronizing and asserting ready-change provides all the functionality of dosFsVolUnmount( ), except for marking file descriptors as obsolete.)
Since it does not attempt to flush data or to perform other operations that could cause a delay, ready-change may be used in interrupt handlers.
If it is not possible for dosFsVolUnmount( ) or dosFsReadyChange( ) to be called each time the disk is changed, the device must be specially identified when it is initialized with the file system. One of the parameters of dosFsDevInit( ) is the address of a DOS_VOL_CONFIG structure, which specifies various configuration parameters. DOS_OPT_CHANGENOWARN must be set in the dosvc_options field of the DOS_VOL_CONFIG structure, if the driver and/or application is unable to issue a dosFsVolUnmount( ) call or assert a ready-change when a disk is changed.This configuration option results in a significant performance disadvantage, because the disk configuration data must be regularly read in from the physical disk, in case the disk has been changed. In addition, setting DOS_OPT_CHANGENOWARN also enables auto-sync mode (see below).
Note that for disk change notification, all that is required is that dosFsVolUnmount( ) or dosFsReadyChange( ) be called each time the disk is changed. It is not necessary that either routine be called from the device driver or an interrupt handler. For example, if your application provided a user interface through which an operator could enter a command which would result in a dosFsVolUnmount( ) call before removing the disk, that would be sufficient, and DOS_OPT_CHANGENOWARN should not be set. It is important, however, that such a procedure be followed strictly.
A disk should be "synchronized" before is is unmounted. To synchronize a disk means to write out all buffered data (files, directories, and the FAT table) that have been modified, so that the disk is "up-to-date." It may or may not be necessary to explicitly synchronize a disk, depending on when (or if) the dosFsVolUnmount( ) call is issued.When dosFsVolUnmount( ) is called, an attempt will be made to synchronize the device before unmounting. If the disk is still present and writable at the time dosFsVolUnmount( ) is called, the synchronization will take place; there is no need to independently synchronize the disk.
However, if dosFsVolUnmount( ) is called after a disk has been removed, it is obviously too late to synchronize. (In this situation, dosFsVolUnmount( ) discards the buffered data.) Therefore, a separate ioctl( ) call with the FIOFLUSH or FIOSYNC function should be made before the disk is removed. (This could be done in response to an operator command.)
The dosFs file system provides a modified mode of behavior called "auto-sync." This mode is enabled by setting DOS_OPT_AUTOSYNC in the dosvc_options field of the DOS_VOL_CONFIG structure when calling dosFsDevInit( ). When this option is enabled, modified directory and FAT data is written to the physical device as soon as these structures are altered. (Normally, such changes may not be written out until the involved file is closed.) This results in a performance penalty, but it provides the highest level of data security, since it minimizes the amount of time when directory and FAT data on the disk are not up-to-date.Auto-sync mode is automatically enabled if the volume does not have disk change notification, i.e., if DOS_OPT_CHANGENOWARN is set in the dosvc_options field of the DOS_VOL_CONFIG structure when dosFsDevInit( ) is called. It may also be desirable for applications where data integrity-- in case of a system crash--is a larger concern than simple disk I/O performance.
Various disk configuration parameters are specified when the dosFs device is first initialized using dosFsDevInit( ). This data is kept in the volume descriptor (DOS_VOL_DESC) for the device. However, it is possible for a disk with different parameters than those defined to be placed in a drive after the device has already been initialized. For such a disk to be usable, the configuration data in the volume descriptor must be modified when a new disk is present.
When a disk is mounted, the boot sector information is read from the disk. This data is used to update the configuration data in the volume descriptor. Note that this will happen the first time the disk is accessed after the volume has been unmounted (using dosFsVolUnmount( )).
This automatic re-initialization of the configuration data has two important implications:
- (1)
- Since the values in the volume descriptor are reset when a new volume is mounted, it is possible to omit the dosFs configuration data (by specifying a NULL pointer instead of the address of a DOS_VOL_CONFIG structure during dosFsDevInit( )). The first use of the volume must be with a properly formatted and initialized disk. (Attempting to initialize a disk, using FIODISKINIT, before a valid disk has been mounted is fruitless.)
- (2)
- The volume descriptor data is used when initializing a disk (with FIODISKINIT). The FIODISKINIT function initializes a disk with the configuration of the most recently mounted disk, regardless of the original specification during dosFsDevInit( ). Therefore, it is recommended that FIODISKINIT be used immediately after dosFsDevInit( ), before any disk has been mounted. (The device should be opened in raw mode; the FIODISKINIT function is then performed; and the device is then closed.)
The dosFs file system supports the following ioctl( ) functions. The functions listed are defined in the header ioLib.h. Unless stated otherwise, the file descriptor used for these functions may be any file descriptor which is opened to a file or directory on the volume or to the volume itself.
- FIODISKFORMAT
- Formats the entire disk with appropriate hardware track and sector marks. No file system is initialized on the disk by this request. Note that this is a driver-provided function:
fd = open ("DEV1:", O_WRONLY); status = ioctl (fd, FIODISKFORMAT, 0);- FIODISKINIT
- Initializes a DOS file system on the disk volume. This routine does not format the disk; formatting must be done by the driver. The file descriptor should be obtained by opening the entire volume in raw mode:
fd = open ("DEV1:", O_WRONLY); status = ioctl (fd, FIODISKINIT, 0);- FIODISKCHANGE
- Announces a media change. It performs the same function as dosFsReadyChange( ). This function may be called from interrupt level:
status = ioctl (fd, FIODISKCHANGE, 0);- FIOUNMOUNT
- Unmounts a disk volume. It performs the same function as dosFsVolUnmount( ). This function must not be called from interrupt level:
status = ioctl (fd, FIOUNMOUNT, 0);- FIOGETNAME
- Gets the file name of the file descriptor and copies it to the buffer nameBuf:
status = ioctl (fd, FIOGETNAME, &nameBuf );- FIORENAME
- Renames the file or directory to the string newname:
status = ioctl (fd, FIORENAME, "newname");- FIOSEEK
- Sets the current byte offset in the file to the position specified by newOffset:
status = ioctl (fd, FIOSEEK, newOffset);- FIOWHERE
- Returns the current byte position in the file. This is the byte offset of the next byte to be read or written. It takes no additional argument:
position = ioctl (fd, FIOWHERE, 0);- FIOFLUSH
- Flushes the file output buffer. It guarantees that any output that has been requested is actually written to the device. If the specified file descriptor was obtained by opening the entire volume (raw mode), this function will flush all buffered file buffers, directories, and the FAT table to the physical device:
status = ioctl (fd, FIOFLUSH, 0);- FIOSYNC
- Performs the same function as FIOFLUSH, and additionally re-reads buffered file data from the disk. This allows file changes made via a different file descriptor to be seen.
- FIOTRUNC
- Truncates the specified file's length to newLength bytes. Any disk clusters which had been allocated to the file but are now unused are returned, and the directory entry for the file is updated to reflect the new length. Only regular files may be truncated; attempts to use FIOTRUNC on directories or the entire volume will return an error. FIOTRUNC may only be used to make files shorter; attempting to specify a newLength larger than the current size of the file produces an error (setting errno to S_dosFsLib_INVALID_NUMBER_OF_BYTES).
status = ioctl (fd, FIOTRUNC, newLength);- FIONREAD
- Copies to unreadCount the number of unread bytes in the file:
status = ioctl (fd, FIONREAD, &unreadCount);- FIONFREE
- Copies to freeCount the amount of free space, in bytes, on the volume:
status = ioctl (fd, FIONFREE, &freeCount);- FIOMKDIR
- Creates a new directory with the name specified as dirName:
status = ioctl (fd, FIOMKDIR, "dirName");- FIORMDIR
- Removes the directory whose name is specified as dirName:
status = ioctl (fd, FIORMDIR, "dirName");- FIOLABELGET
- Gets the volume label (located in root directory) and copies the string to labelBuffer:
status = ioctl (fd, FIOLABELGET, &labelBuffer);- FIOLABELSET
- Sets the volume label to the string specified as newLabel. The string may consist of up to eleven ASCII characters:
status = ioctl (fd, FIOLABELSET, "newLabel");- FIOATTRIBSET
- Sets the file attribute byte in the DOS directory entry to the new value newAttrib. The file descriptor refers to the file whose entry is to be modified:
status = ioctl (fd, FIOATTRIBSET, newAttrib);- FIOCONTIG
- Allocates contiguous disk space for a file or directory. The number of bytes of requested space is specified in bytesRequested. In general, contiguous space should be allocated immediately after the file is created:
status = ioctl (fd, FIOCONTIG, bytesRequested);- FIONCONTIG
- Copies to maxContigBytes the size of the largest contiguous free space, in bytes, on the volume:
status = ioctl (fd, FIONCONTIG, &maxContigBytes);- FIOREADDIR
- Reads the next directory entry. The argument dirStruct is a DIR directory descriptor. Normally, the readdir( ) routine is used to read a directory, rather than using the FIOREADDIR function directly. See dirLib.
DIR dirStruct; fd = open ("directory", O_RDONLY); status = ioctl (fd, FIOREADDIR, &dirStruct);- FIOFSTATGET
- Gets file status information (directory entry data). The argument statStruct is a pointer to a stat structure that is filled with data describing the specified file. Normally, the stat( ) or fstat( ) routine is used to obtain file information, rather than using the FIOFSTATGET function directly. See dirLib.
struct stat statStruct; fd = open ("file", O_RDONLY); status = ioctl (fd, FIOFSTATGET, &statStruct);Any other ioctl( ) function codes are passed to the block device driver for handling.
In order to minimize memory fragmentation in the system memory pool, all memory consumed by dosFsLib will be contained within a dedicated memory partition. This partition is accessible via the dosFsMemPartId global variable.
To display the current amount of memory used by dosFsLib, call show(dosFsMemPartId). Please see the manual page for memPartShow( ) for more details.
The following varibles may be set before dosFsLib is initialized to change the behavior of the memory management.
If the dosFsLib memory partition is not provided, one will be allocated from the system memory pool. It's size defaults to 8 K, which may be changed via the dosFsMemPartInitSize global. To provide a memory pool, set dosFsMemPartId to a valid PART_ID returned from memPartCreate( ).
The global variable dosFsMemPartIdOptions may be modified to change the behavior of error handling for errors in malloc( ) and free( ). The options default to MEM_BLOCK_ERROR_LOG_FLAG, which will log information about errors detected by free( ). These options only affect operations on the dosFs memory partition.
The private partition will dynamically grow as much as needed, allocating additional memory from the system memory pool, in units no smaller than 1 Kilobyte. This minumum unit size may be adjusted via the dosFsMemPartGrowSize global variable.
The maximum size for the dosFs memory partition may be limited via the global variable dosFsMemPartCap. Once the cap limit has been reached or surpassed, dosFs will not attempt to allocate more memory from the system memory partition. The default value is -1, which allows uninterupted use of the system memory partition.
Additional debugging may be enabled via the global boolean dosFsDebug. Setting this to 1 will enable verbose debug messages from the dosFs memory manager.
dosFsLib.h
dosFsLib, ioLib, iosLib, dirLib, ramDrv, Microsoft MS-DOS Programmer's Reference (Microsoft Press), Advanced MS-DOS Programming (Ray Duncan, Microsoft Press), VxWorks Programmer's Guide: I/O System, Local File Systems
dosFsConfigGet( ) - obtain dosFs volume configuration values
STATUS dosFsConfigGet ( DOS_VOL_DESC * vdptr, /* ptr to volume descriptor */ DOS_VOL_CONFIG * pConfig /* ptr to config structure to fill */ )
This routine obtains the current configuration values for a dosFs disk volume. The data is obtained from the dosFs volume descriptor specified by vdptr. No physical I/O to the device takes place.
The configuration data is placed into a DOS_VOL_CONFIG structure, whose address is pConfig. This structure must be allocated before calling dosFsConfigGet( ).
One use for this routine is to obtain the configuration data from a known good disk, to be used to initialize a new disk (using dosFsDevInit( )).
The volume is not locked while the data is being read from the volume descriptor, so it is conceivable that another task may modify the configuration information while this routine is executing.
OK or ERROR.
dosFsConfigInit( ) - initialize dosFs volume configuration structure
STATUS dosFsConfigInit ( DOS_VOL_CONFIG * pConfig, /* pointer to volume config structure */ char mediaByte, /* media descriptor byte */ UINT8 secPerClust, /* sectors per cluster */ short nResrvd, /* number of reserved sectors */ char nFats, /* number of FAT copies */ UINT16 secPerFat, /* number of sectors per FAT copy */ short maxRootEnts, /* max number of entries in root dir */ UINT nHidden, /* number of hidden sectors */ UINT options /* volume options */ )
This routine initializes a dosFs volume configuration structure (DOS_VOL_CONFIG). This structure is used by the dosFsDevInit( ) routine to specify the file system configuration for the disk.
The DOS_VOL_CONFIG structure must have been allocated prior to calling this routine. Its address is specified by pConfig. The specified configuration variables are placed into their respective fields in the structure.
This routine is provided only to allow convenient initialization of the DOS_VOL_CONFIG structure (particularly from the VxWorks shell). A structure which is properly initialized by other means may be used equally well by dosFsDevInit( ).
OK, or ERROR if there is an invalid parameter or pConfig is NULL.
dosFsLib, dosFsDevInit( )
dosFsConfigShow( ) - display dosFs volume configuration data
STATUS dosFsConfigShow ( char * devName /* name of device */ )
This routine obtains the dosFs volume configuration for the named device, formats the data, and displays it on the standard output. The information which is displayed is that which is contained in a DOS_VOL_CONFIG structure, along with other configuration values (for example, from the BLK_DEV structure which describes the device).
If no device name is specified, the current default device is described.
OK or ERROR.
dosFsDateSet( ) - set the dosFs file system date
STATUS dosFsDateSet ( int year, /* year (1980...2099) */ int month, /* month (1...12) */ int day /* day (1...31) */ )
This routine sets the date for the dosFs file system, which remains in effect until changed. All files created or modified are assigned this date in their directory entries.
No automatic incrementing of the date is performed; each new date must be set with a call to this routine.
OK, or ERROR if the date is invalid.
dosFsLib, dosFsTimeSet( ), dosFsDateTimeInstall( ).
dosFsDateTimeInstall( ) - install a user-supplied date/time function
void dosFsDateTimeInstall ( FUNCPTR pDateTimeFunc /* pointer to user-supplied function */ )
This routine installs a user-supplied function to provide the current date and time. Once such a function is installed, dosFsLib will call it when necessary to obtain the date and time. Otherwise, the date and time most recently set by dosFsDateSet( ) and dosFsTimeSet( ) are used.
The user-supplied routine must take exactly one input parameter, the address of a DOS_DATE_TIME structure (defined in dosFsLib.h). The user routine should update the necessary fields in this structure and then return. Any fields which are not changed by the user routine will retain their previous value.
N/A
dosFsDevInit( ) - associate a block device with dosFs file system functions
DOS_VOL_DESC *dosFsDevInit ( char * devName, /* device name */ BLK_DEV * pBlkDev, /* pointer to block device struct */ DOS_VOL_CONFIG * pConfig /* pointer to volume config data */ )
This routine takes a block device structure (BLK_DEV) created by a device driver and defines it as a dosFs volume. As a result, when high-level I/O operations (e.g., open( ), write( )) are performed on the device, the calls will be routed through dosFsLib. The pBlkDev parameter is the address of the BLK_DEV structure which describes this device.
This routine associates the name devName with the device and installs it in the VxWorks I/O system's device table. The driver number used when the device is added to the table is that which was assigned to the dosFs library during dosFsInit( ). (The driver number is placed in the global variable dosFsDrvNum.)
The BLK_DEV structure contains configuration data describing the device and the addresses of five routines which will be called to read sectors, write sectors, reset the device, check device status, and perform other control functions (ioctl( )). These routines will not be called until they are required by subsequent I/O operations.
The pConfig parameter is the address of a DOS_VOL_CONFIG structure. This structure must have been previously initialized with the specific dosFs configuration data to be used for this volume. This structure may be easily initialized using dosFsConfigInit( ).
If the device being initialized already has a valid dosFs (MS-DOS) file system on it, the pConfig parameter may be NULL. In this case, the volume will be mounted and the configuration data will be read from the boot sector of the disk. (If pConfig is NULL, both change-no-warn and auto-sync options are initially disabled. These can be enabled using the dosFsVolOptionsSet( ) routine.)
This routine allocates and initializes a volume descriptor (DOS_VOL_DESC) for the device. It returns a pointer to DOS_VOL_DESC.
A pointer to the volume descriptor DOS_VOL_DESC, or NULL if there is an error.
dosFsDevInitOptionsSet( ) - specify volume options for dosFsDevInit( )
STATUS dosFsDevInitOptionsSet ( UINT options /* options for future dosFsDevInit() calls */ )
This routine allows volume options to be set that will be enabled by subsequent calls to dosFsDevInit( ) that do not explicitly supply configuration information in a DOS_VOL_CONFIG structure. This is normally done when mounting a disk which has already been initialized with file system data. The value of options will be used for all volumes that are initialized by dosFsDevInit( ), unless a specific configuration is given.
The only volume options which may be specified in this call are those which are not tied to the actual data on the disk. Specifically, you may not specify the long file name option in this call; if a disk using that option is mounted, that will be automatically detected. If you specify such an unsettable option during this call it will be ignored; all valid option bits will still be accepted and applied during subsequent dosFsDevInit( ) calls.
For example, to use dosFsDevInit( ) to initialize a volume with the auto-sync and filesystem export options, do the following:
status = dosFsDevInitOptionsSet (DOS_OPT_AUTOSYNC | DOS_OPT_EXPORT); if (status != OK) return (ERROR); vdptr = dosFsDevInit ("DEV1:", pBlkDev, NULL); /* note NULL pointer for DOS_VOL_CONFIG */
OK, or ERROR if options is invalid.
dosFsLib, dosFsDevInit( ), dosFsVolOptionsSet( )
dosFsInit( ) - prepare to use the dosFs library
STATUS dosFsInit ( int maxFiles /* max no. of simultaneously open files */ )
This routine initializes the dosFs library. It must be called exactly once, before any other routine in the library. The argument specifies the number of dosFs files that may be open at once. This routine installs dosFsLib as a driver in the I/O system driver table, allocates and sets up the necessary memory structures, and initializes semaphores. The driver number assigned to dosFsLib is placed in the global variable dosFsDrvNum.
This initialization is enabled when the configuration macro INCLUDE_DOSFS is defined; dosFsInit( ) is then called from the root task, usrRoot( ), in usrConfig.c.
OK or ERROR.
dosFsMkfs( ) - initialize a device and create a dosFs file system
DOS_VOL_DESC *dosFsMkfs ( char * volName, /* volume name to use */ BLK_DEV * pBlkDev /* pointer to block device struct */ )
This routine provides a quick method of creating a dosFs file system on a device. It is used instead of the two-step procedure of calling dosFsDevInit( ) followed by an ioctl( ) call with an FIODISKINIT function code.
This call uses default values for various dosFs configuration parameters (i.e., those found in the volume configuration structure, DOS_VOL_CONFIG). The values used are:
- 2
- sectors per cluster (see below)
- 1
- reserved sector
- 2
- FAT copies
- 112
- root directory entries
- 0xF0
- media byte value
- 0
- hidden sectors
The volume options (auto-sync mode, change-no-warn mode, and long filenames) that are enabled by this routine can be set in advance using dosFsMkfsOptionsSet( ). By default, none of these options is enabled for disks initialized by dosFsMkfs( ).
If initializing a large disk, it is quite possible that the entire disk area cannot be described by the maximum 64K clusters if only two sectors are contained in each cluster. In such a situation, dosFsMkfs( ) will automatically increase the number of sectors per cluster to a number which will allow the entire disk area to be described in 64K clusters.
The number of sectors per FAT copy is set to the minimum number of sectors which will contain sufficient FAT entries for the entire block device.
A pointer to a dosFs volume descriptor, or NULL if there is an error.
S_dosFsLib_INVALID_PARAMETER
dosFsLib, dosFsDevInit( )
dosFsMkfsOptionsSet( ) - specify volume options for dosFsMkfs( )
STATUS dosFsMkfsOptionsSet ( UINT options /* options for future dosFsMkfs() calls */ )
This routine allows volume options to be set that will be enabled by subsequent calls to dosFsMkfs( ). The value of options will be used for all volumes that are initialized by dosFsMkfs( ).
For example, to use dosFsMkfs( ) to initialize a volume with the auto-sync and long filename options, do the following:
status = dosFsMkfsOptionsSet (DOS_OPT_AUTOSYNC | DOS_OPT_LONGNAMES); if (status != OK) return (ERROR); vdptr = dosFsMkfs ("DEV1:", pBlkDev);
OK, or ERROR if options is invalid.
dosFsLib, dosFsMkfs( ), dosFsVolOptionsSet( )
dosFsModeChange( ) - modify the mode of a dosFs volume
void dosFsModeChange ( DOS_VOL_DESC * vdptr, /* pointer to volume descriptor */ int newMode /* O_RDONLY/O_WRONLY/O_RDWR (both) */ )
This routine sets the volume's mode to newMode. The mode is actually kept in "bd_mode" fields of the the BLK_DEV structure, so that it may also be used by the device driver. Changing that field directly has the same result as calling this routine. The mode field should be updated whenever the read and write capabilities are determined, usually after a ready change. See the manual entry for dosFsReadyChange( ).
The driver's device initialization routine should initially set the mode field to O_RDWR (i.e., both O_RDONLY and O_WRONLY).
N/A
dosFsReadyChange( ) - notify dosFs of a change in ready status
void dosFsReadyChange ( DOS_VOL_DESC * vdptr /* pointer to volume descriptor */ )
This routine sets the volume descriptor's state to DOS_VD_READY_CHANGED. It should be called whenever a driver senses that a device has come on-line or gone off-line (e.g., a disk has been inserted or removed).
After this routine has been called, the next attempt to use the volume will result in an attempted remount.
This routine may also be invoked by calling ioctl( ) with a function code of FIODISKCHANGE.
Setting the "bd_readyChanged" field to TRUE in the BLK_DEV structure that describes this device will have the same result as calling this routine.
N/A
dosFsTimeSet( ) - set the dosFs file system time
STATUS dosFsTimeSet ( int hour, /* 0 to 23 */ int minute, /* 0 to 59 */ int second /* 0 to 59 */ )
This routine sets the time for the dosFs file system, which remains in effect until changed. All files created or modified are assigned this time in their directory entries.
No automatic incrementing of the time is performed; each new time must be set with a call to this routine.
OK, or ERROR if the time is invalid.
dosFsLib, dosFsDateSet( ), dosFsDateTimeInstall( )
dosFsVolOptionsGet( ) - get current dosFs volume options
STATUS dosFsVolOptionsGet ( DOS_VOL_DESC * vdptr, /* ptr to volume descriptor */ UINT * pOptions /* where to put current options value */ )
This routine obtains the current options for a specified dosFs volume and stores them in the field pointed to by pOptions.
OK, always.
dosFsLib, dosFsVolOptionsSet( )
dosFsVolOptionsSet( ) - set dosFs volume options
STATUS dosFsVolOptionsSet ( DOS_VOL_DESC * vdptr, /* ptr to volume descriptor */ UINT options /* new options for volume */ )
This routine sets the volume options for an already-initialized dosFs device. Only the following options can be changed (enabled or disabled) dynamically:
DOS_OPT_CHANGENOWARN (0x1)
DOS_OPT_AUTOSYNC (0x2)The DOS_OPT_CHANGENOWARN option may be enabled only for removable volumes (i.e., the bd_removable field in the BLK_DEV structure for the device must be set to TRUE). If specified for a non-removable volume, it is ignored. When successfully set, the DOS_OPT_CHANGENOWARN option also enables the DOS_OPT_AUTOSYNC option.
It is recommended that the current volume options be obtained by calling dosFsVolOptionsGet( ), the desired option bits modified, and then the options set using dosFsVolOptionsSet( ).
OK, or ERROR if options is invalid or an attempt is made to change an option that is not dynamically changeable.
dosFsLib, dosFsDevInitOptionsSet( ), dosFsMkfsOptionsSet( ), dosFsVolOptionsGet( )
dosFsVolUnmount( ) - unmount a dosFs volume
STATUS dosFsVolUnmount ( DOS_VOL_DESC * vdptr /* pointer to volume descriptor */ )
This routine is called when I/O operations on a volume are to be discontinued. This is the preferred action prior to changing a removable disk.
All buffered data for the volume is written to the device (if possible, with no error returned if data cannot be written), any open file descriptors are marked as obsolete, and the volume is marked as not currently mounted. When a subsequent I/O operation is initiated on the disk (e.g., during the next open( )), the volume will be remounted automatically.
Once file descriptors have been marked as obsolete, any attempt to use them for file operations will return an error. (An obsolete file descriptor may be freed by using close( ). The call to close( ) will return an error, but the descriptor will in fact be freed.) File descriptors obtained by opening the entire volume (in raw mode) are not marked as obsolete.
This routine may also be invoked by calling ioctl( ) with the FIOUNMOUNT function code.
This routine must not be called from interrupt level.
OK, or ERROR if the volume was not mounted.