|< C Run-Time 2 | Main | C Run-Time 4 >| Site Index | Download |
MODULE B
IMPLEMENTATION SPECIFIC
MICROSOFT C Run-Time 3
|
|
My Training Period: hours
Note: This Module is a continuation from the previous one. Program examples, compiled using Visual C++ .Net (Visual studio .Net 2003). It is low-level programming and the .Net used is Unmanaged (/clr is not set: Project menu → your_project_name Properties… sub menu → Configuration Properties folder → General subfolder → Used Managed Extension setting set to No). All programs are in debug mode, run on Windows 2000 and Xp Pro.
Abilities
▪ Able to recognize the standard and implementation specific C. ▪ Able to find and collect the required and related information in order to use functions to accomplish your tasks. ▪ Able to understand and use functions that available in the libraries in your own programs.
File-Handling Functions (Open File)
- The following functions used to open files.
- The following Table is an example of the needed information for fopen() and wfopen() functions.
|
||||||||||||||||||||||||||||||||||||||||
- The fopen() function opens the file specified by filename. _wfopen() is a wide-character version of fopen() and the arguments to _wfopen() are wide-character strings.
- _wfopen() and fopen() behave identically otherwise.
- The character string mode specifies the type of access requested for the file, as follows:
|
mode |
|
|
"r" |
Opens for reading. If the file does not exist or cannot be found, the fopen() call fails. |
|
"w" |
Opens an empty file for writing. If the given file exists, its contents are destroyed. |
|
"a" |
Opens for writing at the end of the file (appending) without removing the EOF marker before writing new data to the file; creates the file first if it doesn't exist. |
|
"r+" |
Opens for both reading and writing, the file must exist. |
|
"w+" |
Opens an empty file for both reading and writing. If the given file exists, its contents are destroyed. |
|
"a+" |
Opens for reading and appending; the appending operation includes the removal of the EOF marker before new data is written to the file and the EOF marker is restored after writing is complete; creates the file first if it doesn't exist. |
|
The following characters can be included in mode to specify the translation mode for newline characters: |
|
|
t |
Open in text (translated) mode. In this mode, CTRL+Z is interpreted as an end-of-file character on input. In files opened for reading/writing with "a+", fopen() checks for a CTRL+Z at the end of the file and removes it, if possible. This is done because using fseek() and ftell() to move within a file that ends with a CTRL+Z, may cause fseek() to behave improperly near the end of the file. |
|
b |
Open in binary (un-translated) mode; translations involving carriage-return and linefeed characters are suppressed. |
|
c |
Enable the commit flag for the associated filename so that the contents of the file buffer are written directly to disk if either fflush() or _flushall() is called. |
|
n |
Reset the commit flag for the associated filename to "no-commit". This is the default. It also overrides the global commit flag if you link your program with commode.obj. The global commit flag default is "no-commit" unless you explicitly link your program with commode.obj. |
|
S |
Specifies that caching is optimized for, but not restricted to, sequential access from disk. |
|
R |
Specifies that caching is optimized for, but not restricted to, random access from disk. |
|
T |
Specifies a file as temporary. If possible, it is not flushed to disk. |
|
D |
Specifies a file as temporary. It is deleted when the last file pointer is closed. |
|
Table 3: File type of access, mode. |
|
- To learn more about standard C for file I/O goes C File I/O and for C++ goes C++ File I/O. Get the big picture of the standard and implementation specific for the file I/O and other topics in C and C++ as well.
- The following Table is an example of the needed information for _sopen() and _wsopen() functions.
|
Information |
Description |
|
The function |
_sopen(), _wsopen(). |
|
The use |
Open a file for sharing. |
|
The prototype |
int _sopen(
const char *filename, int oflag, int shflag [, int pmode ]); /*For wide character*/
int _wsopen( const wchar_t *filename, int oflag, int shflag [,
int pmode ]); |
|
Example |
char fname[50] = C:\\testfile.txt; int _sopen(fname, _O_CREAT, _SH_DENYNO, _S_IWRITE); |
|
The parameters |
filename – The filename. oflag - Type of operations allowed. shflag - Type of sharing allowed. pmode - Permission setting. |
|
The return value |
Each of these functions returns a file descriptor for the opened file. A return value of –1 indicates an error, in which case errno is set to one of the following values: EACCES - Given path is a directory, or file is read-only, but an open-for-writing operation was attempted. EEXIST - _O_CREAT and _O_EXCL flags were specified, but filename already exists. EINVAL - Invalid oflag or shflag argument. EMFILE - No more file descriptors available. ENOENT - File or path not found. |
|
The header file |
<io.h> or <wchar.h> (for _wsopen()) |
|
Table 4: _sopen() and _wsopen() functions information. |
|
- oflag is an integer expression formed from one or more of the following manifest constants or constant combinations that defined in fcntl.h.
|
oflag |
Description |
|
_O_APPEND |
Moves file pointer to end of file before every write operation. |
|
_O_BINARY |
Opens file in binary (untranslated) mode. |
|
_O_CREAT |
Creates and opens new file for writing. Has no effect if file specified by filename exists. pmode argument is required when _O_CREAT is specified. |
|
_O_CREAT | _O_SHORT_LIVED |
Create file as temporary and if possible do not flush to disk. pmode argument is required when _O_CREAT is specified. |
|
_O_CREAT | _O_TEMPORARY |
Create file as temporary; file is deleted when last file handle is closed. pmode argument is required when _O_CREAT is specified. |
|
_O_CREAT | _O_EXCL |
Returns error value if file specified by filename exists. Applies only when used with _O_CREAT. |
|
_O_RANDOM |
Specifies that caching is optimized for, but not restricted to, random access from disk. |
|
_O_RDONLY |
Opens file for reading only; cannot be specified with _O_RDWR or _O_WRONLY. |
|
_O_RDWR |
Opens file for both reading and writing; you cannot specify this flag with _O_RDONLY or _O_WRONLY. |
|
_O_SEQUENTIAL |
Specifies that caching is optimized for, but not restricted to, sequential access from disk. |
|
_O_TEXT |
Opens file in text (translated) mode. |
|
_O_TRUNC |
Opens file and truncates it to zero length; file must have write permission. You cannot specify this flag with _O_RDONLY. _O_TRUNC used with _O_CREAT opens an existing file or creates a new file. The _O_TRUNC flag destroys the contents of the specified file. |
|
_O_WRONLY |
Opens file for writing only; cannot be specified with _O_RDONLY or _O_RDWR. |
|
Table 5: oflag constants. |
|
- To specify the file access mode, you must specify either _O_RDONLY, _O_RDWR, or _O_WRONLY. There is no default value for the access mode.
- The argument shflag is a constant expression consisting of one of the following manifest constants, defined in share.h.
|
shflag |
Description |
|
_SH_DENYRW |
Denies read and write access to file. |
|
_SH_DENYWR |
Denies write access to file. |
|
_SH_DENYRD |
Denies read access to file. |
|
_SH_DENYNO |
Permits read and write access. |
|
Table 6: shflag. |
|
- The pmode argument is required only when you specify _O_CREAT. If the file does not exist, pmode specifies the file's permission settings, which are set when the new file is closed the first time. Otherwise pmode is ignored.
- pmode is an integer expression that contains one or both of the manifest constants _S_IWRITE and _S_IREAD, defined in sys\stat.h.
- When both constants are given, they are combined with the bitwise-OR operator. The meaning of pmode is as follows:
|
pmode |
Description |
|
_S_IREAD |
Reading only permitted. |
|
_S_IWRITE |
Writing permitted (effectively permits reading and writing). |
|
_S_IREAD | _S_IWRITE |
Reading and writing permitted. |
|
Table 7: pmode. |
|
- If write permission is not given, the file is read-only. Under Windows 98/Me and Windows NT/2000/XP, all files are readable; it is not possible to give write-only permission. Thus the modes _S_IWRITE and _S_IREAD | _S_IWRITE are equivalent.
- _sopen() applies the current file-permission mask to pmode before setting the permissions.
- The following Table is an example of the needed information in order to use the _open() function.
|
Information |
Description |
|
The function |
_open(). |
|
The use |
Open a file. |
|
The prototype |
int _open(const char *filename, int oflag [, int pmode]); [ ... ] – denotes optional. |
|
Example |
char fname[50] = C:\\testfile.txt; int _sopen(fname, _O_CREAT, _SH_DENYNO, _S_IWRITE); |
|
The parameters |
filename – The filename. oflag - Type of operations allowed. pmode - Permission mode. |
|
The return value |
Each of these functions returns a file handle for the opened file. A return value of –1 indicates an error, in which case errno is set to one of the following values:
EACCES - Tried to open read-only file for writing, or file's sharing mode does not allow specified operations, or given path is directory. EEXIST - _O_CREAT and _O_EXCL flags specified, but filename already exists. EINVAL - Invalid oflag or pmode argument. EMFILE - No more file handles available (too many open files). ENOENT - File or path not found. |
|
The header file |
<io.h> |
|
Table 8: _open() function information. |
|
- Finally, a program example that uses the functions. Originally the robots.txt file has write permission.
/*Playing with some of the file handling functions*/
#include <io.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
/*You can try other files and directories*/
char obj[50] = "d:\\test\\testsubtwo\\testsubthree\\robots.txt";
char newobj[50] = "d:\\test\\testsubtwo\\testsubthree\\human.txt";
int main()
{
/*Check for existence*/
if((_access(obj, 0)) != -1)
printf("%s file exists\n", obj);
else
printf("%s file does not exist lol!\n", obj);
/*Check for read/write permission*/
if((_access(obj, 2)) != -1)
printf("%s file has write permission\n", obj);
if((_access(obj, 4)) != -1)
printf("%s file has read permission\n", obj);
if((_access(obj, 6)) != -1)
printf("%s file has write and read permission\n\n", obj);
/* Make file read-only: */
if(_chmod(obj, _S_IREAD) == -1)
perror("File not found lol!\n");
else
{
printf("The file mode is changed to read-only\n");
_chmod(obj, _S_IREAD);
}
if((_access(obj, 4)) != -1)
printf("%s file has read permission\n", obj);
/*Change back to read/write*/
if(_chmod(obj, _S_IWRITE) == -1)
perror("file not found lol!\n");
else
{
printf("\nThe file\'s mode is changed to read/write\n");
_chmod(obj, _S_IWRITE);
}
if((_access(obj, 2)) != -1)
printf("%s file has write permission\n", obj);
/*Attempt to rename file*/
int result = rename(obj, newobj);
if(result != 0)
printf("\nCould not rename %s\n", obj);
else
printf("\n%s file has been renamed to\n %s\n", obj, newobj);
/*remove the file*/
if(remove(newobj) == -1)
printf("\nCould not delete %s lol!\n", newobj);
else
printf("\nOoops! %s file has been deleted lol!\n", newobj);
return 0;
}
The output:
d:\test\testsubtwo\testsubthree\robots.txt file exists
d:\test\testsubtwo\testsubthree\robots.txt file has write permission
d:\test\testsubtwo\testsubthree\robots.txt file has read permission
d:\test\testsubtwo\testsubthree\robots.txt file has write and read permission
The file mode is changed to read-only
d:\test\testsubtwo\testsubthree\robots.txt file has read permission
The file's mode is changed to read/write
d:\test\testsubtwo\testsubthree\robots.txt file has write permission
d:\test\testsubtwo\testsubthree\robots.txt file has been renamed to
d:\test\testsubtwo\testsubthree\human.txt
Ooops! d:\test\testsubtwo\testsubthree\human.txt file has been deleted lol!
Press any key to continue
The File Permission mask
- The following Table is the needed information in order to use the _umask() function.
|
Information |
Description |
|
The function |
_umask(). |
|
The use |
Sets the default file-permission mask. |
|
The prototype |
int _umask(int pmode); |
|
Example |
_umask(_S_IWRITE); |
|
The parameters |
pmode - default permission setting - _S_IREAD, _S_IWRITE. |
|
The return value |
Returns the previous value of pmode. There is no error return. |
|
The header files |
<io.h>, <sys/stat.h> and <sys/types.h>. |
|
Table 9: _umask() function information. |
|
- The _umask() function sets the file-permission mask of the current process to the mode specified by pmode.
- The file-permission mask modifies the permission setting of new files created by _creat(), _open(), or _sopen(). If a bit in the mask is 1, the corresponding bit in the file's requested permission value is set to 0 (disallowed).
- If a bit in the mask is 0, the corresponding bit is left unchanged. The permission setting for a new file is not set until the file is closed for the first time.
- The argument pmode is a constant expression containing one or both of the manifest constants _S_IREAD and _S_IWRITE, defined in sys\stat.h.
- When both constants are given, they are joined with the bitwise-OR operator ( | ). If the pmode argument is _S_IREAD, reading is not allowed (the file is write-only). If the pmode argument is _S_IWRITE, writing is not allowed (the file is read-only).
- For example, if the write bit is set in the mask, any new files will be read-only. Note that with MS-DOS and the Windows operating systems, all files are readable. It is not possible to give write-only permission. Therefore, setting the read bit with _umask() has no effect on the file's modes.
- The following is a simple program example.
/*This program uses _umask to set the file-permission mask
so that all future files will be created as read-only files.
Then we create a file for write and test opening the file
for writing*/
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <io.h>
#include <stdio.h>
int main()
{
int fh, oldmask;
/*File in current working directory*/
char test[20] = "test.txt";
/*Create read-only files: */
oldmask = _umask(_S_IWRITE);
printf("Oldmask = 0x%.4x\n", oldmask);
/*create a file with write permission*/
fh = _creat(test, _S_IWRITE);
if(fh == -1)
printf("Couldn't create %s file!\n", test);
else
{
printf("%s file successfully created.\n", test);
_close(fh);
}
/*Try opening file for write*/
fh = _open(test, _O_WRONLY);
if(fh == -1)
printf("%s opening failed!\n", test);
else
{
printf("%s opening succeeded!\n", test);
if(_close(fh) == 0)
printf("%s closed successfully!\n", test);
}
printf("Oldmask = 0x%.4x\n", oldmask);
return 0;
}
The output:
Oldmask = 0x0000
test.txt file successfully created.
test.txt opening failed!
Oldmask = 0x0000
Press any key to continue
The File Statistic
- The _stat(), _stat64(), _stati64(), _wstat(), _wstat64(), _wstati64() functions used for file statistic. The information needed in order to use these functions is listed in the following Table.
|
Information |
Description |
|
The function |
_stat(), _stat64(), _stati64(), _wstat(), _wstat64(), _wstati64() |
|
The use |
Get status information on a file. |
|
The prototype |
int _stat(const char *path, struct _stat *buffer);
int _stat64(const char *path, struct __stat64 *buffer); int _stati64(const char *path, struct _stati64 *buffer); int _wstat(const wchar_t *path, struct _stat *buffer); int _wstat64(const wchar_t *path, struct __stat64 *buffer); int _wstati64(const wchar_t *path, struct _stati64 *buffer); |
|
Example |
struct __stat64 buf; char fname[50] = "c:\\WINNT\\system32\\config\\sam.log"; _stat64(fname, &buf); |
|
The parameters |
path - Pointer to a string containing the path of existing file. buffer - Pointer to structure that stores results. |
|
The return value |
Each of these functions returns 0 if the file-status information is obtained. A return value of –1 indicates an error, in which case errno is set to ENOENT, indicating that the filename or path could not be found. The date stamp on a file can be represented if it is later than midnight, January 1, 1970, and before 19:14:07 January 18, 2038, UTC unless you use _stat64() or _wstat64(), in which case the date can be represented up till 23:59:59, December 31, 3000, UTC. |
|
The header files |
_stat(), _stat64(), _stati64() - <sys/types.h> followed by <sys/stat.h>. _wstat(), _wstat64(), _wstati64() - <sys/types.h> followed by <sys/stat.h> or <wchar.h>. |
|
Table 10: File statistic functions information. |
|
- The _stat() function obtains information about the file or directory specified by path and stores it in the structure pointed to by buffer.
- _stat() automatically handles multibyte-character string arguments as appropriate, recognizing multibyte-character sequences according to the multibyte code page currently in use.
- _wstat() is a wide-character version of _stat(); the path argument to _wstat() is a wide-character string (More information and implementation of the wide character can be found in Locale, Wide Character & Unicode (Story) and Windows Users & Groups tutorial (Implementation)).
- The _stat structure, defined in sys\stat.h, includes the following elements. You should be familiar in using and accessing structure elements.
|
Element |
Description |
|
st_gid |
Numeric identifier of group that owns file (UNIX-specific) This field will always be zero on Windows NT systems. A redirected file is classified as a Windows NT file. |
|
st_atime |
Time of last access of file. Valid on NTFS but not on FAT formatted disk drives. |
|
st_ctime |
Time of creation of file. Valid on NTFS but not on FAT formatted disk drives. |
|
st_dev |
Drive number of the disk containing the file (same as st_rdev). |
|
st_ino |
Number of the information node (the inode) for the file (UNIX-specific). On UNIX file systems, the inode describes the file date and time stamps, permissions, and content. When files are hard-linked to one another, they share the same inode. The inode, and therefore st_ino, has no meaning in the FAT, HPFS, or NTFS file systems. |
|
st_mode |
Bit mask for file-mode information. The _S_IFDIR bit is set if path specifies a directory; the _S_IFREG bit is set if path specifies an ordinary file or a device. User read/write bits are set according to the file's permission mode; user execute bits are set according to the filename extension. |
|
st_mtime |
Time of last modification of file. |
|
st_nlink |
Always 1 on non-NTFS file systems. |
|
st_rdev |
Drive number of the disk containing the file (same as st_dev). |
|
st_size |
Size of the file in bytes; a 64-bit integer for _stati64() and _wstati64(). |
|
st_uid |
Numeric identifier of user who owns file (UNIX-specific). This field will always be zero on Windows NT systems. A redirected file is classified as a Windows NT file. |
|
Table 11: _stat structure members. |
|
- If path refers to a device, the st_size, various time fields, st_dev, and st_rdev fields in the _stat structure are meaningless. Because stat.h uses the _dev_t type that is defined in types.h, you must include types.h before stat.h in your code.
- The following is a program example.
/*Using the _stat64 function reporting a file information*/
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
int main()
{
struct __stat64 buf;
int result;
char fname[50] = "c:\\WINNT\\system32\\config\\sam.log";
/*Get data associated with a file*/
result = _stat64(fname, &buf);
/*Test if statistics are valid*/