Tuesday, December 15, 2009

File Attributes and Directory Processing









File Attributes and Directory Processing


It is possible to search a directory for files and other directories that satisfy a specified name pattern and, at the same time, obtain file attributes. Searches require a search handle obtained by the FindFirstFile function. Obtain specific files with FindNextFile, and terminate the search with FindClose.



HANDLE FindFirstFile (
LPCTSTR lpFileName,
LPWIN32_FIND_DATA lpffd)

Return: A search handle. INVALID_HANDLE_VALUE indicates failure.

FindFirstFile examines both subdirectory and file names, looking for a name match. The returned HANDLE is used in subsequent searches.


Parameters


lpFileName points to a directory or pathname that can contain wildcard characters (? and *). Search for a single specific file by omitting wildcard characters.


lpffd points to a WIN32_FIND_DATA structure that contains information about the first file or directory to satisfy the search criteria, if any are found.


The WIN32_FIND_DATA structure is defined as follows:



typedef struct_WIN32_FIND_DATA {
DWORD dwFileAttributes;
FILETIME ftCreationTime;
FILETIME ftLastAccessTime;
FILETIME ftLastWriteTime;
DWORD nFileSizeHigh;
DWORD nFileSizeLow;
DWORD dwReserved0;
DWORD dwReserved1;
TCHAR cFileName [MAX_PATH];
TCHAR cAlternateFileName [14];
} WIN32_FIND_DATA;


dwFileAttributes can be tested for the values described with CreateFile along with some additional values, such as FILE_ATTRIBUTE_SPARSE_FILE and FILE_ATTRIBUTE_ENCRYTPED, which are not set by CreateFile. The three file times (creation, last access, and last write) are described in an upcoming section. The file size fields, giving the current file length, are self-explanatory. cFileName is not the pathname; it is the file name by itself. cAlternateFileName is the DOS 8.3 (including the period) version of the file name; this information is rarely used and is appropriate only to determine how a file would be named on a FAT16 file system.


Frequently, the requirement is to scan a directory for files that satisfy a name pattern containing ? and * wildcard characters. To do this, use the search handle obtained from FindFirstFile, which retains information about the search name, and call FindNextFile.



BOOL FindNextFile (
HANDLE hFindFile,
LPWIN32_FIND_DATA lpffd)


FindNextFile will return FALSE in case of invalid arguments or if no more matching files can be found, in which case GetLastError will return ERROR_NO_MORE_FILES.


When the search is complete, close the search handle. Do not use CloseHandle. This is a rare exception to the rule that CloseHandle is for all handlesclosing a search handle will cause an exception. Instead, use the following:



BOOL FindClose (HANDLE hFindFile)


The function GetFileInformationByHandle obtains the same information for a specific file, specified by an open handle. It also returns a field, nNumberOfLinks, which indicates the number of hard links set by CreateHardLink.


This method of wildcard expansion is necessary even in programs executed from the MS-DOS prompt because the DOS shell does not expand wildcards.


Pathnames


You can obtain a file's full pathname using GetFullPathName. GetShortPathName returns the name in DOS 8.3 format, assuming that the volume supports short names.


NT 5.1 introduced SetFileShortName, which allows you to change the existing short name of a file or directory. This can be convenient because the existing short names are often difficult to interpret.


Other Methods of Obtaining File and Directory Attributes


The FindFirstFile and FindNextFile functions can obtain the following file attribute information: attribute flags, three time stamps, and file size. There are several other related functions, including one to set attributes, and they can deal directly with the open file handle rather than scan a directory or use a file name. Three such functions, GetFileSize, GetFileSizeEx, and SetEndOfFile, were described previously in this chapter.


Distinct functions are used to obtain the other attributes. For example, to obtain the time stamps of an open file, use the GetFileTime function.



BOOL GetFileTime (
HANDLE hFile,
LPFILETIME lpftCreation,
LPFILETIME lpftLastAccess,
LPFILETIME lpftLastWrite)


The file times here and in the WIN32_FIND_DATA structure are 64-bit unsigned integers giving elapsed 100-nanosecond units (107 units per second) from a base time (January 1, 1601), expressed as Universal Coordinated Time (UTC).[3] There are several convenient functions for dealing with times.

[3] Do not, however, expect to get 100-nanosecond precision; precision will vary depending on hardware characteristics.


  • FileTimeToSystemTime (not described here; see the Windows references or Program 3-2) breaks the file time into individual units ranging from years down to seconds and milliseconds. These units are suitable, for example, when displaying or printing times.

  • SystemTimeToFileTime reverses the process, converting time expressed in these individual units to a file time.

  • CompareFileTime determines whether one file time is less than (1), equal to (0), or greater than (+1) another.

  • Change the time stamps with SetFileTime; times that are not to be changed are set to 0 in the function call. NTFS supports all three file times, but the FAT gives an accurate result only for the last access time.

  • FileTimeToLocalFileTime and LocalFileTimeToFileTime convert between UTC and the local time.


GetFileType, not described in detail here, distinguishes among disk files, character files (actually, devices such as printers and consoles), and pipes (see Chapter 11). The file, again, is specified with a handle.


The function GetFileAttributes uses the file or directory name, and it returns just the dwFileAttributes information.



DWORD GetFileAttributes (LPCTSTR lpFileName)

Return: The file attributes, or 0xFFFFFFFF in case of failure.

The attributes can be tested for appropriate combinations of several mask values. Some attributes, such as the temporary file attribute, are originally set with CreateFile. The attribute values include the following:


  • FILE_ATTRIBUTE_DIRECTORY

  • FILE_ATTRIBUTE_NORMAL

  • FILE_ATTRIBUTE_READONLY

  • FILE_ATTRIBUTE_TEMPORARY


The function SetFileAttributes changes these attributes in a named file.



opendir, readdir, and closedir in UNIX correspond to the three Find functions. The function stat obtains file size and times, in addition to owning user and group information that relates to UNIX security. fstat and lstat are variations. These functions can also obtain type information. utime sets file times in UNIX. There is no UNIX equivalent to the temporary file attribute.



Temporary File Names


The next function creates names for temporary files. The name can be in any specified directory and must be unique.


GetTempFileName gives a unique file name, with the .tmp suffix, in a specified directory and optionally creates the file. This function is used extensively in later examples (Program 6-1, Program 7-1, and elsewhere).



UINT GetTempFileName (
LPCTSTR lpPathName,
LPCTSTR lpPrefixString,
UINT uUnique,
LPTSTR lpTempFileName)

Return: A unique numeric value used to create the file name. This will be uUnique if uUnique is nonzero. On failure, the return value is zero.

Parameters

lpPathName is the directory for the temporary file. "." is a typical value specifying the current directory. Alternatively, use GetTempPath, a Windows function not described here, to give the name of a directory dedicated to temporary files.


lpPrefixString is the prefix of the temporary name. Only 8-bit ASCII characters are allowed. uUnique is normally zero so that the function will generate a unique four-digit suffix and will create the file. If this value is nonzero, the file is not created; do that with CreateFile, possibly using FILE_FLAG_DELETE_ON_CLOSE.


lpTempFileName points to the buffer that receives the temporary file name. The buffer's byte length should be at least the same value as MAX_PATH. The resulting pathname is a concatenation of the path, the prefix, the four-digit hex number, and the .tmp suffix.









    No comments: