870 likes | 1.1k Views
Input/Output With File and Directory Processing. OBJECTIVES. Describe the Windows file systems (compared to UNIX/Linux) Perform sequential file processing Perform console I/O and direct access file I/O Report and analyze system call errors
E N D
OBJECTIVES • Describe the Windows file systems (compared to UNIX/Linux) • Perform sequential file processing • Perform console I/O and direct access file I/O • Report and analyze system call errors • Describe and use Unicode characters and strings and write generic applications (both Unicode and ASCII characters) • Use Windows file locking to protect files from concurrent modification by several processes • Perform file and directory management
BASIC Windows I/O • Basic Windows API file processing functions: • CreateFile • ReadFile • WriteFile • CloseHandle • Windows files are: • binary • text (lines are CR-LF terminated)
BASIC UNIX I/O • Basic UNIX file processing functions are eqiovalent: • open • read • write • close • UNIX files are: • Plain byte streams • text lines are LF terminated
C library I/O • Basic C file processing functions are equivalent: • fopen • fread • fwrite • fclose
THE FILE SYSTEMS • Windows File Systems • (Virtual) File Allocation Table File System (FAT, VFAT) • The only disk file system for floppies and Windows 9x • NTFS File System (NTFS) • Very large (“huge”) files, secure, robust • Supported on Windows NT (all versions) • CD-ROM File System (CDFS) • Custom file systems • Developed by software vendors
Windows FILE NAMING (1/2) • Hierarchical • Full pathname can start with a drive name • A:, C:, … • Or with a “share” name • \\servername\sharename • Pathname separator is a backslash — \ • You can also use / in C • Directory and file names cannot use ASCII 1–31 • Or any of < > : " | • But you can have blanks in file names • Case insensitive but case retaining
Windows FILE NAMING (2/2) • File, directory names up to 255 characters long • 250 in Windows 9x • More with UNICODE • A period . separates a file’s name from its extension • The period is in the name; there can be more than one • . and .. indicate the current directory and its parent • No file link (as in UNIX) • Alternate data stream • Different logical files for the same phisical file • A problem for security !!!
UNIX file systems • Ext2 and Ext3 (Linux) • JFS (AIX) • XFS (IRIX) • Names are case-sensitive • Max. name length implementation dependent • Links used (hard and symbolic)
CREATING AND OPENING FILES Windows • HANDLE CreateFile (LPCTSTR lpName, • DWORD dwAccess, DWORD dwShareMode, • LPSECURITY_ATTRIBUTES lpsa, DWORD dwCreate, • DWORD dwAttrsAndFlags, HANDLE hTemplateFile) • Return: A HANDLE to an open file object • INVALID_HANDLE_VALUE in case of failure • LPCTSTR will be described in Part II
CREATING AND OPENING (2/6) • Parameters • lpName • Pointer to the string naming the file • Length normally limited to 260 • \\?\ is an escape prefix allowing long NT path names • dwAccess • Access using GENERIC_READ or GENERIC_WRITE • Note: Flags can be combined with |
CREATING AND OPENING (3/6) • dwShareMode • 0 — Cannot be shared; not even this process can open another handle • FILE_SHARE_READ — Other processes can read concurrently • FILE_SHARE_WRITE — Other processes can write concurrently • lpsa points to a SECURITY_ATTRIBUTES structure • NULL for now
CREATING AND OPENING (4/6) • dwCreate — Create a file, overwrite one, etc. • CREATE_NEW — Fails if the file exists • CREATE_ALWAYS — An existing file will be overwritten • OPEN_EXISTING — Fail if the file does not exist • OPEN_ALWAYS — Open the file or create it if it doesn’t exist • TRUNCATE_EXISTING — File length will be set to zero • Note: There is no “open to append” mode • You will need to position to the end of file
CREATING AND OPENING (5/6) • dwAttrsAndFlags — 16 flags and attributes including: • FILE_ATTRIBUTE_NORMAL — No other attributes are set • FILE_ATTRIBUTE_READONLY — Cannot write or delete • FILE_FLAG_OVERLAPPED • FILE_FLAG_SEQUENTIAL_SCAN and FILE_FLAG_RANDOM_ACCESS provide performance hints • Attributes are properties of the files themselves • Flags are associated with a specific HANDLE • Different HANDLEs to the same file can have different flags • Example: One HANDLE is “overlapped,” another not • Or, one has FILE_FLAG_SEQUENTIAL_SCAN and another FILE_FLAG_RANDOM_ACCESS
CREATING AND OPENING (6/6) • File processing flags include: • FILE_FLAG_WRITE_THROUGH • FILE_FLAG_NO_BUFFERING • FILE_FLAG_DELETE_ON_CLOSE • hTemplateFile — Handle of an open GENERIC_READ file • Use the same attributes for the new file
READING FILES (1/2) • BOOL ReadFile (HANDLE hFile, LPVOID lpBuffer, • DWORD nNumberOfBytesToRead, • LPDWORD lpNumberOfBytesRead, • LPOVERLAPPED lpOverlapped) • Return: TRUE if the read succeeds • Even if no bytes were read due to an attempt to read past the end of file • FALSE indicates an invalid handle, a handle without GENERIC_READ access, etc.
READING FILES (2/2) • Parameters • hFile — File handle with GENERIC_READ access • lpBuffer — Memory buffer to receive the input data • nNumberOfBytesToRead • Number of bytes you expect to read • *lpNumberOfBytesRead • Actual number of bytes transferred • Zero indicates end of file • lpOverlapped • Points to OVERLAPPED structure (NULL for now)
WRITING FILES • BOOL WriteFile ( • HANDLE hFile, CONST VOID *lpBuffer, • DWORD nNumberOfBytesToWrite, • LPDWORD lpNumberOfBytesWritten, • LPOVERLAPPED lpOverlapped) • Return: TRUE if the function succeeds; FALSE otherwise
CLOSING FILES • BOOL CloseHandle (HANDLE hObject) • Return: TRUE if the function succeeds; FALSE otherwise • This function is general purpose and will be used to close handles to many different object types
COPYING FILES • BOOL CopyFile (LPCTSTR lpExistingFile, • LPCTSTR lpNewFile, BOOL fFailIfExists) • If a file with the new name already exists, it will be replaced only if fFailIfExists is FALSE • This is a “convenience function” and also provides performance
UNICODE & GENERIC CHARACTERS • Windows NT supports 16-bit characters • WCHAR or wchar_t • To assure maximum flexibility and source portability, define all characters and strings using “generic” type TCHAR • Calculate lengths using sizeof(TCHAR) • Include #define UNICODE (to get WCHAR) in all source modules (or #undef UNICODE to get CHAR) • Be consistent • Define UNICODE before #include <windows.h> • Also define _UNICODE consistently for the generic C library
GENERIC CHARACTERS (2/3) • Use the “generic” C library for all string functions • _tprintf in place of printf • _stprintf in place of sprintf • _tcslen in place of strlen • _itot in place of itoa • And MANY more • See the on line help and the lab programs • Generic versions of some functions are not provided • e.g. memchr - Replacements are in the lab solutions
GENERIC CHARACTERS (3/3) • Constant strings in one of three forms (first 2 are ANSI C) • The last is a macro "This string uses 8-bit characters" L"This string uses 16-bit characters" _T ("This string uses generic characters") • Expands to “T…” if UNICODE is not defined; L”T…” if it is TEXT macro is the same as _T LPTSTR expands to either char * or wchar_t *
THE GENERIC C LIBRARY • Define _UNICODE consistently with UNICODE • This makes available a wide class of string processing and I/O functions _fgettc, _itot, _ttoi, _totupper, _totlower • And many more — nearly the complete library • Also, locale-specific functions (seven in all): lstrlen, lstrcmp, lstrcpy, lstrcat, … • Be sure to #include <tchar.h> after <windows.h> • Note: Any _ keyword or function is specific to Microsoft Visual C++ and the Microsoft compiler
GENERIC CHARACTERS AND THE MAIN PROGRAM • Windows main is for ASCII; wmain is for Unicode • In place of int main (argc, char * argv[]) • or int main (argc, w_char * argv[]) • Use #include <tchar.h> • /* this is after <windows.h> */ • ... int _tmain (int argc, LPTSTR argv[]) • The _tmain macro then expands to main or wmain • Depending on definition of _UNICODE • This assures correct operation in all circumstances and combinations
STANDARD DEVICESAND CONSOLE I/O (1/7) • Both UNIX and Win32 have3 “standard” devices for input, output and error. • Unix usesfirst 3 file descriptors (0, 1, 2) • Win32 requires handle andprovidesa functionto get standard device handlers from integer constants • HANDLE GetStdHandle(DWORD nStdHandle);
STANDARD DEVICESAND CONSOLE I/O (1/7) • HANDLE GetStdHandle (DWORD dwDevice) • Return: A valid handle or INVALID_HANDLE_VALUE for failure • BOOL SetStdHandle (DWORD IDStdHandle, • HANDLE hHandle) • Return: TRUE or FALSE indicating success or failure
STANDARD DEVICESAND CONSOLE I/O (2/7) • dwDevice and IDStdHandle • Must have one of these values: • STD_INPUT_HANDLE • STD_OUTPUT_HANDLE • STD_ERROR_HANDLE
STANDARD DEVICESAND CONSOLE I/O (3/7) • hHandle • Specifies an open file that is to be the standard device • Two reserved pathnames for console input (the keyboard): • "CONIN$" • and output (the display): • "CONOUT$"
STANDARD DEVICESAND CONSOLE I/O (4/7) • BOOL SetConsoleMode (HANDLE hConsole, • DWORD fdevMode) • Return: TRUE if and only if the function succeeds • hConsole • Must have GENERIC_WRITE access
STANDARD DEVICESAND CONSOLE I/O (5/7) • fDevMode — How characters are processed • ENABLE_WINDOW_INPUT • ENABLE_LINE_INPUT • ENABLE_ECHO_INPUT • ENABLE_PROCESSED_INPUT • ENABLE_PROCESSED_OUTPUT • ENABLE_WRAP_AT_EOL_OUTPUT
STANDARD DEVICESAND CONSOLE I/O (6/7) • BOOL ReadConsole (HANDLE hConsoleInput, • LPVOID lpvBuffer, DWORD cchToRead, • LPDWORD lpcchRead, LPVOID lpvReserved) • Return: TRUE if and only if the read succeeds
STANDARD DEVICESAND CONSOLE I/O (7/7) • BOOL WriteConsole • Same as ReadConsole • BOOL FreeConsole (VOID) • BOOL AllocConsole (VOID)
EXAMPLE: PrintStrings (1/3) • #include "envirmnt.h" /* UNICODE is defined here */ • #include <windows.h> • BOOL PrintStrings (HANDLE hOut, ...) • /* Write the messages to the output handle (hOut) • Use WriteConsole (to handle Unicode & console • processing) first, as the output will normally • be the console. If that fails, use WriteFile. • hOut: Handle for output file. • ... : Variable argument list containing TCHAR • strings. The list must be terminated with NULL. */
PrintStrings (2/3) • { • DWORD MsgLen, Count; • BOOL Success = TRUE; • LPCTSTR pMsg; • va_list pMsgList; /* Current message string */ • va_start (pMsgList, hOut); • /* Start processing msgs */ • while (((pMsg = va_arg (pMsgList, LPCTSTR)) != NULL) • && Success) • { • MsgLen = _tcslen (pMsg); • (CONTINUED)
PrintStrings (3/3) • /* WriteConsole fails if the handle is associated • with a file rather than with a console */ • if (!WriteConsole (hOut, pMsg, • MsgLen, &Count, NULL) && • !WriteFile (hOut, pMsg, • MsgLen * sizeof (TCHAR), &Count, NULL)) • return FALSE; • } /* End of while loop - process next message */ • va_end (pMsgList); • return TRUE; • }
EXAMPLE: ReportError (1/4) • OBJECTIVE: • Turn system call errors into meaningful text strings • And print the text • Terminate the program if the error is fatal • Similar to perror(), but it works in the multithreaded Windows environment.
EXAMPLE: ReportError (2 of 4) • #include "envirmnt.h" • #include <windows.h> • #include "support.h" • VOID ReportError (LPCTSTR UserMessage, • DWORD ExitCode, BOOL PrintErrorMsg) • /* General-purpose function to report system errors. • Obtain the error number and turn it into the • system error message. Display this information • and the user specified message to the standard • error device. • UserMessage: Message to be displayed to • standard error device. */
ReportError (3/4) • ExitCode: 0 - Return • > 0 - ExitProcess with this code • PrintErrorMessage: Display the last system error • message if this flag is set. */ • { • DWORD eMsgLen, ErrNum = GetLastError (); • LPVOID lpvSysMsg; • HANDLE hStdErr = GetStdHandle (STD_ERROR_HANDLE); • PrintMsg (hStdErr, UserMessage); • if (PrintErrorMsg) {
ReportError (4/4) • eMsgLen = FormatMessage ( • FORMAT_MESSAGE_ALLOCATE_BUFFER | • FORMAT_MESSAGE_FROM_SYSTEM, • NULL, ErrNum, • MAKELANGID (LANG_DFLT, SUBLANG_DFLT), • &lpvSysMsg, 0, NULL); • PrintStrings (hStdErr, TEXT ("\n"), • lpvSysMsg, TEXT ("\n"), NULL); • HeapFree (GetProcessHeap (), 0, lpvSysMsg); • } • if (ExitCode > 0) • ExitProcess (ExitCode); • else • return; • }
FILE POINTERS (1/4) • DWORD SetFilePointer (HANDLE hFile, • LONG lDistanceToMove, • PLONG lpDistanceToMoveHigh, • DWORD dwMoveMethod) • Return: The low-order DWORD (unsigned) of the new file pointer. The high-order portion of the new file pointer goes to the DWORD indicated by lpDistanceToMoveHigh (if non-NULL). In case of error, the return value is OxFFFFFFFF. • Note: The file pointer is associated with the HANDLE, not the file. The pointer advances with each read and write.
FILE POINTERS (2/4) • Note: NTFS is a 64-bit file system, so file pointers are 64 bits long. The file pointer is specified with two 32-bit parts. • Large files are increasingly important in many applications • But many users will only require “short” (< 4GB) files • SetFilePointer Parameters • hFile — Handle of an open file with read and/or write access • lDistanceToMove — LONG signed distance to move or unsigned file position
FILE POINTERS (3/4) • *lpDistanceToMoveHigh • High-order portion of the move distance • Can be NULL for “small” files • dwMoveMethod — Specifies one of these modes: • FILE_BEGIN — Position from the start of file • FILE_CURRENT — Move pointer forward or backward • FILE_END — Position backward from end of file • SetEndOfFile () function resizes the file based on the current file pointer
FILE POINTERS (4/4) • Use the LARGE_INTEGER data type (union) for 64-bit file positions • Example coming up • Members: • LONGLONG Quadpart Do the 64-bit arithmetic here • DWORD LowPart • LONG HighPart
Alternative Direct File Access Using the Overlapped Structure (1/2) • Example: Use the Offset fields in the overlapped structure • Offset Low order 32 bits • OffsetHigh High order 32 bits • hEvent Must be NULL. This field is used with asynchronous I/O • Two reserved fields Do not use!! • The example shows how to update a record in a file
Alternative Direct File Access Using the Overlapped Structure (2/2) • OVERLAPPED ov = { 0, 0, 0, 0, NULL }; • RECORD r; /* Includes “reference count” field */ • LONGLONG n; • LARGE_INTEGER FilePos; • DWORD nRd, nWrt; • . . . • /* Update reference count in the n’th record. */ • FilePos.QuadPart = n * sizeof (RECORD); • ov.Offset = FilePos.LowPart; • ov.OffsetHigh = FilePos.HighPart; • ReadFile (hFile, &r, sizeof(RECORD), &nRd, &ov); • r.RefCount++; /* Update the record. */ • WriteFile(hFile, &r, sizeof(RECORD), &nWrt, &ov);