[ Next ] [ Previous ] | Chapter 4 - I |
File I/O is one of the most important aspects of any operating system. OS/2 makes the file system programming very easy to understand and master, yet it still provides the programmer with many flexible and powerful features. OS/2 has introduced to DOS developers the new concept of Installable File Systems. which allows various file systems to be installed like device drivers. OS/2 introduces the new High Performance File System (HPFS), which allows greater throughput and security features for servers, workstations. and local area network (LAN) administrators. The File Allocation Table (FAT) compatibility is preserved, so DOS users can manipulate their flies without any constraints.
The following examples demonstrate some straightforward file manipulation, yet provide the user with some useful concepts. It is also necessary to introduce the concept of Extended Attributes (EAs), which is the lesser-known 0S/2 file system feature. One of the examples shows a way to gain access to the various types of EAs. EAs appeased in 0S/2 1.2 and have remained there through the 16- to 32-bit migration; they are nothing more than additional data that is associated with the file, The user does not see this extra data. It is there only for the use of the application and operating system. The designers had to be creative it order to implement EA support under FAT due to the fact that DOS, which is the grandfather of FAT never had support for EAs. The HPFS does not require the same creativity in implementation, thus the FAT implementation, is the one that deserves a short explanation.
|
The FAT directory entries take up 32 bytes (20 hex) and are represented
by Table 4.1.
|
A more thorough discussion of EA API and a detailed discussion of the API structures for the FAT and HPFS can be found in the OS/2 Programming Guide and various other IBM technical publications. The short description offered here is merely for the benefit of the programming examples and to help the programmer understand the API syntax used to attain the EA information. Extended attributes will appear foreign to DOS users and programmers, and their usefulness generally is questioned almost immediately. Only upon closer inspection does it become evident that EAs are quite important and really constitute a must-have feature , especially in high-end operating systems such as OS/2. Basically the Extended Attributes are nothing more than a storage area of information no more than 64K in sire that are available for applications to use as they please. OS/2 defines several standard types of EAs that are available for general use. Also, the programmer can define application-specific extended attributes. The only restriction is that the total EA size s cannot exceed 64K. Standard EAs are called SEAs, and by convention starts with a period [.]. They include:
.ASSOCTABLE
.CODEPAGE
.COMMENTS
.HISTORY
.ICON
.KEYPHRASES
.LONGNAME
.SUBJECT
.TYPE
.VERSION
It is a good idea to not use the preceding [.] character in your own applications.
The operating system reserves the right to use [.] as the first character
of the EA name types. Nothing prevents users from implementing the same
convention, but if OS/2 designers decide to add another standard type that
happens to use your EA name, some unpredictable behavior may result. The
type of data that is stored within an SEA is representative of the SEA
name. For example, the .ICON SEA will contain the icon data, while the
.TYPE SEA will contain the file object's type. This type can represent
an executable, data, metafile, C code, bitmap, icon, resource file, object
code, DOS binary, and so on. As you might have guessed, the .TYPE SEA is
one of the more frequently used attributes of a file object. Note that
extended attributes are associated not only with files but also with subdirectories.
In fact, the subdirectory containing the Workplace Shell desktop information
contains subdirectories that have many, many EAs.
A programmer must take certain steps while using EAs. First, if the file
objects are being moved or copied to a system that does not support EAs
(such as a DOS-FAT combination), the programmer must take care not to lose
the EAs that may be associated with the particular file object. Consider
the case of uploading a file with EAs to a UNIX machine and then downloading
the same file back. Doing so may result in EAs being lost or misplaced
because most UNIX machines do not support EAs. Another good example is
trying to copy a file that has a long name from an HPFS partition to a
FAT partition. Since FAT supports the 8.3 naming convention only, the file
name may be truncated, but that is not a problem since the correct HPFS
name may be stored in the .LONGNAME EA. An application that manipulates
files must be EA- and HPFS-aware in order to perform proper file management
in an OS/2 environment.
The first example we discuss attempts to find out the value of the LIBPATH environment variable. In OS/2 Warp, an extended LIBPATH variable was created. This special variable can be set or queried from the command line or from an API, DosSetExtLIBPATH and DosQueryExtLIBPATH. This variable can be changed dynamically and either pretended or appended to the system LIBPATH variable. The system LIBPATH itself cannot be returned from the regular environment SET command or a DosQuery... API. Occasionally the system LIBPATH variable is a handy thing to know. So, a not-so-clean solution is to find the value of the boot drive, find the CONFIG.SYS file, and attempt to extract the LIBPATH string from that file. This will work only when there have been no previous changes to the CONFIG.SYS file since the system has been booted and specifically no direct manipulations of the system LIBPATH value. Although this example is a crude kluge, the method actually can be useful on a number of occasions.
LIBPATH.C
LIBPATH.MAK
LIBPATH.DEF
The first step is to find the system boot drive. In order to do this, use DosQuerySysInfo and specify the arguments corresponding to the boot drive information. DosQuerySysInfo takes three input parameters and one output parameter, and returns the values of the system's static variables:
APIRET DosQuerySysInfo (
ULONG uStartIndex;
/* Ordinal of the first system variable to return. */
ULONG uLastIndex;
/* Ordinal of the last system variable to return. */
PVOID pDataBuf;
/* Address of the data buffer where the system returns the
variable values. */
ULONG ulDataBufLen);/*
Length, in bytes, of the data buffer. */
/* APIRET Return
Code. */
This call can return a single value or a range of values, depending on the ulSrartIndex, ulLastIndex. As is evident by the example, in order to obtain a single value, the ulStartIndex and ulLastIndex are set to the same input value:
arReturn = DosQuerySysInfo(
QSV_BOOT_DRIVE,
QSV_BOOT_DRIVE,
&ulDrive,
sizeof( ulDrive) );
The QSV_BOOT_DRIVE constant is defined by the BSEDOS.H header file, which
is part of the set standard header files provided by she Programmer's Toolkit.
Table 4.1 defines the additional values. The third parameter is the data
buffer that DosQuerySysInfo uses to place the returned values into. The
parameter is the size of the data buffer.
Description | Value | Meaning |
QSV_MAX_PATH_LENGTH | 1 | Maximum path name length in bytes |
Q_MAX_PATH_LENGTH | 1 | = QSV_MAX_PATH_LENGTH |
QSV_MAX_TEXT_SESSIONS | 2 | Maximum number or text sessions |
QSV_MAX_PM_SESSIONS | 3 | Maximum number of PM sessions |
QSV_MAX_VDM_SESSIONS | 4 | Maximum number of virtual DOS machine (VDM) sessions |
QSV_BOOT_DRIVE | 5 | Boot drive value ( 1=A:, 2=B:, etc. ) |
QSV_DYN_PRI_VARIATION | 6 | Dynamic/Absolute priority (0=Absolute, 1=Dynamic ) |
QSV_MAX_WAIT | 7 | Maximum wait time in seconds |
QSV_MIN_SLICE | 8 | Minimum time slice allowed in milliseconds |
QSV_MAX_SLICE | 9 | Maximum time slice allowed in milliseconds |
QSV_PAGE_SIZE | 10 | Default page size (4K) |
QSV_VERSION_MAJOR | 11 | Major version number (20 for OS/2 2.0, 2.1, 2.11, 3.0, 4.0) |
QSV_VERSION_MINOR | 12 | Minor version number (00, 10, 11, 30,40 for OS/2 2.0, 2.1, 2.11, 3.0, 4.0 respectively) |
QSV_VERSION_REVISION | 13 | Revision version letter |
QSV_MS_COUNT | 14 | Free running millisecond 32-bit counter (value=0 at boot time) |
QSV_TIME_LOW | 15 | Lower 32 bits of time since 01-01-1970 in seconds |
QSV_TIME_HIGH | 16 | Upper 32 bits of times since 01-01-1970 in seconds |
QSV_TOTPHYSMEM | 17 | Total number of bytes of physical memory |
QSV_TOTRESMEM | 18 | Total number of system-resident memory |
QSV_TOTAVAILMEM | 19 | (Available memory for all processes)
Maximum number of bytes of memory that can be allocated by all processes in the system. This number is advisory and is not guaranteed, since system conditions change constantly. |
QSV_MAXPRMEM | 20 | (Avail private mem for calling proc)
Maximum number of bytes of memory that this process can allocate in its private arena. This number is advisory and is not guaranteed, since system conditions change constantly. |
QSV_MAXSHMEM | 21 | ( Avail shared mem for calling proc )
Maximum number of bytes of memory that a process can allocate in the shared arena. This number is advisory and is not guaranteed, since system conditions change constantly. |
QSV_TIMER_INTERVAL | 22 | Timer interval in tenths of millisecond |
QSV_MAX_COMP_LENGTH | 23 | Maximum length, in bytes, of one component in a path name. |
QSV_FOREGROUND_FS_SESSION | 24 | Session ID of current fgnd FS session
Session ID of the current foreground full-screen session. Note that this only applies to full-screen sessions. The Presentation Manager session (which displays Vio-windowed, PM, and windowed DOS Sessions) is full-screen session ID 1. |
QSV_FOREGROUND_PROCESS | 25 | Process ID of the current foreground process. |
QSV_NUMPROCESSORS | 26 | Number of processors in the machine |
QSV_MAXHPRMEM | 27 | Maximum amount of free space in process's high private arena |
QSV_MAXHSHMEM | 28 | Maximum amount of free space in process's high shared arena |
QSV_MAXPROCESSES | 29 | Maximum number of concurrent processes supported |
QSV_VIRTUALADDRESSLIMIT | 30 | Size of the user's address space in megabytes |
QSV_INT10ENABLED | 31 | INT10ENABLED |
QSV_MAX | = QSV_INT10ENABLED |
![]() |
Gotcha!
An application that is intended to be used in the HPFS/FAT environment should make the DosQuerySysInfo call and determine the maximum value of the legal file name length: QSV_MAX_COMP_LENGTH. For HPFS, this value is much greater than FAT (255). The application should issue this call in its initialization section and remember the pertinent values for future DosFindFirst, DosFindNext buffer sire allocation values. |
arReturn = DosQueryPathInfo(
pchFile,
FIL_STANDARD,
&fsStatus,
sizeof( fsStatus) );
pchBuffer = malloc (fsStatus.cbFile +1);
DosQueryPathInfo is used to determine the size
of CONFIG.SYS. The function is designed to get file information for a file
or subdirectory. The first parameter, pchFile, is the fully qualified path
for the file. The second parameter is the level of information required.
All we need for this example is standard file information, FIL_STANDARD.
The information level determines the third parameter. If FIL_STANDARD is
specified, a pointer to a FILESTATUS3 structure is used. The structure
looks like this:
typedef struct _FILESTATUS3 {
FDATE
fdateCreation; /* Date of file creation. */
FTIME
ftimeCreation; /* Time of file creation. */
FDATE
fdateLastAccess; /* Date of last access. */
FTIME
ftimeLastAccess; /* Time of last access. */
FDATE
fdateLastWrite; /* Date of last write. */
FTIME
ftimeLastWrite; /* Time of last write. */
ULONG
cbFile; /*
File size (end of data). */
ULONG
cbFileAlloc; /* File allocated size.
*/
ULONG
attrFile; /* Attributes
of the file. */
} FILESTATUS3;
The FILESTATUS3 structure contains two fields of interest: cbFile and cbFileAlloc. The cbFiIe element contains the actual size of the file, start to finish, in bytes. The cbFileAlloc, on the other hand, contains the file size, based on system allocation unit (AU) size, whose value can be a multiple of 512, 2K, 4K, 8K, l6K,32K. and so on, depending on the type of magnetic media used. HPFS and diskettes use 512-byte AUs, while the FAT AU size depends on the volume size. cbFileAlloc is of minimal value in applications, and the cbFile value should be used to allocate the required storage. Thus, cbFile size value is used in the next call to allocate the memory buffer needed to read the whole CONFIG.SYS at once, plus an extra byte for a NULL character.
This memory allocation does not have to be performed. It is possible
to read one character at a time and parse the output using a 1-byte storage
area. The method used in CHKEA was used for ease of implementation as well
as performance reasons. Reading the whole file is much quicker. (Since
the CONFIG.SYS is generally smaller than 4K in size, it should easily fit
into a single page of memory, which is the smallest allocation allowed
in 32-bit OS/2.) The parsing can be achieved more rapidly as well. Memory
operations are much quicker than storage disk I/O.
Having found the file size, the next step is to attempt to open the CONFIG.SYS
file. The DosOpen API call is a good example of the
flexibility and power of the OS/2 file system interface. Several flags
are available to the programmer, and almost any combination of them can
be defined in order to provide for maximum systemwide cooperation. In this
case, the file is opened in read-only mode and with full sharing enabled
This means that if another application decided to open and read CONFIG.SYS
at the same time, it would be able to do so. Allowing other applications
full sharing rights also presents a problem of the file data being changed
while we are attempting to read if. Although this is a remote possibility,
the risk is still there; using the OPEN_SHARE_DENYWRITE flag instead of
OPEN_SHARE_DENYNONE easily prevents it. The OPEN_FLAGS_SEQUENTIAL flag
is used to define how we will be reading the file. Last. we examine the
file in read-only mode by specifying the flag OPEN_ACCESS_READONLY. DosOpen
is
a fairly involved API. We'll go into some more details in just a moment.
arReturn = DosOpen (
pchFile,
&hfFile,
&ulAction,
0,
FILE_NORMAL,
FILE_OPEN,
OPEN_FLAGS_FAIL_ON_ERROR |
OPEN_FLAGS_SEQUENTIAL |
OPEN_SHARE_DENYNONE |
OPEN_ACCESS_READONLY,
NULL);
arReturn = DosRead(
hfFile,
pchBuffer,
fsStatus.cbFile,
&ulBytesRead);
DosRead is the function to read not only flies but any devices. The first parameter, hfFile, is the file handle returned from DosOpen . The buffer, pchBuffer, is the second parameter. The third parameter is the number of bytes to read. In our case, the entire file size is used. The last parameter is a pointer to a ULONG. The number of bytes actually placed into the buffer is returned in a variable, ulBytesRead.
Note: In DOS and OS/2 it is possible to get a good return code (arReturn = 0) and not have the DosRead/DosWrite API complete as expected. It is a good idea to check for the return code first, then check for the BytesRead value and compare it with the expected number.
Once in memory, the last character of the CONFIG.SYS file is set to NULL. This is done so that string operations can be performed more easily. The last step is parsing the file in order to find the LIBPATH information. Once the LIBPATH is found, it is displayed with a straightforward printf. The cleanup is accomplished by freeing the memory and using DosClose to close the file.
arReturn = DosClose( hfFile );
printf( "\n%s\n", pchLibpath);
free(pchBuffer);
[ Next ] [ Previous ] | Chapter 4 - I |