My Training Period: xx hours. Before you begin, read someinstruction here. Functions and structure used in the program examples were dumped at Win32 functions & structures.
Abilities that supposed to be acquired:
File-Handling Functions (Open File)
|
The fopen() function opens the file specified byfilename. _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 associatedfilename 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 associatedfilename 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:
|
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 (un-translated) 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:
|
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, change accordingly to yours */
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 following Figure shows another sample output run using VC++ 2005
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, change accordingly to yours */
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;
}
A sample output:
Oldmask = 0x0000
test.txt file successfully created.
test.txt opening failed!
Oldmask = 0x0000
Press any key to continue
The following is a sample program run using VC++ EE 2005.
/* 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>
#include <share.h> // _SH_RDWR
int main()
{
int fh, oldmask;
/* file in root directory, change accordingly to yours */
char test[20] = "C:\\test.txt";
/* create read-only files: */
_umask_s(_S_IWRITE, &oldmask);
/* oldmask = _umask(_S_IWRITE); */
printf("Oldmask = 0x%.4x\n", oldmask);
/* create a file with write permission */
_sopen_s( &fh, test, _O_RDWR, _SH_DENYNO, _S_IREAD | _S_IWRITE );
/* 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); */
_sopen_s( &fh, test, _O_RDWR, _SH_DENYNO, _S_IREAD | _S_IWRITE );
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;
}
A sample output:
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 */
if(result != 0)
printf("Problem getting %s file information.\n", fname);
else
{
/*dump some of the file information*/
/*Notice how the structures' elements were accessed*/
printf("The file : %s\n", fname);
printf("Drive : %c:\n", buf.st_dev + 'A');
printf("File size : %ld bytes\n", buf.st_size);
printf("Time created : %s", _ctime64(&buf.st_ctime));
printf("Last accessed : %s", _ctime64(&buf.st_atime));
printf("Time modified : %s", _ctime64(&buf.st_mtime));
printf("Bit mask : %p\n", &buf. st_mode);
return 0;
}
}
A sample output:
The file : c:\WINNT\system32\config\sam.log
Drive : C:
File size : 1024 bytes
Time created : Sat Jun 05 07:07:16 2004
Last accessed : Wed May 18 20:45:12 2005
Time modified : Wed May 18 20:45:12 2005
Bit mask : 0012FEA6
Press any key to continue
The following example run on VC++ EE 2005.
/* 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;
// change accordingly to other path
char fname[50] = "c:\\Windows\\system32\\config\\sam.log";
char buff[50] = "";
/* get data associated with a file */
result = _stat64(fname, &buf);
/* test if statistics are valid */
if(result != 0)
printf("Problem getting %s file information.\n", fname);
else
{
/*dump some of the file information*/
/*Notice how the structures' elements were accessed*/
printf("The file : %s\n", fname);
printf("Drive : %c:\n", buf.st_dev + 'A');
printf("File size : %ld bytes\n", buf.st_size);
/* ctime_s( char* buffer, size_t sizeInBytes, const time_t *time); */
_ctime64_s(buff, 50, &buf.st_ctime);
printf("Time created : %s", buff);
_ctime64_s(buff, 50, &buf.st_atime);
printf("Last accessed : %s", buff);
_ctime64_s(buff, 50, &buf.st_mtime);
printf("Time modified : %s", buff);
printf("Bit mask : %p\n", &buf. st_mode);
return 0;
}
}
A sample output:
The following is a program example that open files for input and output. cruntime.cpp and robots.txt files are in current working directory and having write permission.
/* opening file for input and output, then close. Running on 32 bits system */
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <io.h>
#include <stdio.h>
int main()
{
int fhand1, fhand2;
char fname1[50] = "cruntime.cpp";
char fname2[50] = "robots.txt";
fhand1 = _open(fname1, _O_RDONLY);
if(fhand1 == -1)
printf("opening %s failed for input\n", fname1);
else
{
printf("%s opening succeeded for input\n", fname1);
if(_close(fhand1) == 0)
printf("%s closed successfully!\n", fname1);
}
fhand2 = _open(fname2, _O_WRONLY | _O_CREAT, _S_IREAD | _S_IWRITE);
if(fhand2 == -1)
printf("%s open failed for output\n", fname2);
else
{
printf("%s open succeeded for output\n", fname2);
if(_close(fhand2) ==0)
printf("%s closed successfully!\n", fname1);
}
return 0;
}
A sample output:
|
Another example run using VC++ EE 2005 with SDK
/* opening file for input and output, then close. Running on 32 bits system */
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <io.h>
#include <stdio.h>
#include <share.h> // _O_RDWR
int main()
{
int fhand1, fhand2;
/* change accordingly to your other path */
char fname1[50] = "testwin32.cpp";
char fname2[50] = "C:\\VBPTask.log";
/* fhand1 = _open(fname1, _O_RDONLY); */
_sopen_s( &fhand1, fname1, _O_RDWR, _SH_DENYNO, _S_IREAD | _S_IWRITE );
if(fhand1 == -1)
printf("opening %s failed for input\n", fname1);
else
{
printf("%s opening succeeded for input\n", fname1);
if(_close(fhand1) == 0)
printf("%s closed successfully!\n", fname1);
}
/* fhand2 = _open(fname2, _O_WRONLY | _O_CREAT, _S_IREAD | _S_IWRITE); */
_sopen_s( &fhand2, fname2, _O_RDWR, _SH_DENYNO, _S_IREAD | _S_IWRITE );
if(fhand2 == -1)
printf("%s open failed for output\n", fname2);
else
{
printf("%s open succeeded for output\n", fname2);
if(_close(fhand2) == 0)
printf("%s closed successfully!\n", fname1);
}
return 0;
}
A sample output:
Another longer program example with more functions :o).
/* playing with directory, file and permission */
#include <stdio.h>
#include <stdlib.h>
#include <direct.h>
#include <io.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
int main(void)
{
int curdrive;
char buffer[_MAX_PATH];
/* file name */
char fname[20] = "content.doc";
/* path */
char dir[50] = "d:\\test\\testsubtwo\\testsubthree";
struct _finddata_t c_file;
/* file handle */
long hFile;
/* ---------------------------------------------- */
printf("Firstly, get the current drive...\n");
curdrive = _getdrive();
printf("Current drive is %c:\n\n", curdrive + 'A'-1);
/* ----------------------------------------------- */
printf("Next, get the current working directory...\n");
printf("Current working directory is: \n");
if(_getcwd(buffer, _MAX_PATH) == NULL)
perror("_getcwd error lol!");
else
printf("%s\n\n", buffer);
/*----------------------------------------------- */
printf("Change the current working directory...\n");
_chdir(dir);
printf("\n");
/*------------------------------------------------ */
printf("Current working directory is: \n");
if(_getcwd(buffer, _MAX_PATH) == NULL)
perror("_getcwd error");
else
printf("%s\n\n", buffer);
/* ------------------------------------------------ */
hFile = _findfirst("*.*", &c_file);
{
printf("Listing of *.* files\n\n");
printf("\nRDO HID SYS ARC TYPE FILE DATE %19c SIZE\n", ' ');
printf("--- --- --- --- ---- ---- ---- %19c ----\n", ' ');
printf((c_file.attrib & _A_RDONLY) ? " Y " : " N ");
printf((c_file.attrib & _A_HIDDEN) ? " Y " : " N ");
printf((c_file.attrib & _A_SYSTEM) ? " Y " : " N ");
printf((c_file.attrib & _A_ARCH) ? " Y " : " N ");
printf((c_file.attrib & _A_NORMAL) ? " Y " : " N ");
printf(" %-15s %.24s %6d\n", c_file.name, ctime(&(c_file.time_write)), c_file.size );
/* find the rest of the files */
while(_findnext(hFile, &c_file) == 0)
{
printf((c_file.attrib & _A_RDONLY) ? " Y " : " N ");
printf((c_file.attrib & _A_HIDDEN) ? " Y " : " N ");
printf((c_file.attrib & _A_SYSTEM) ? " Y " : " N ");
printf((c_file.attrib & _A_ARCH) ? " Y " : " N ");
printf((c_file.attrib & _A_NORMAL) ? " Y " : " N ");
printf(" %-15s %.24s %6d\n", c_file.name, ctime(&(c_file.time_write)), c_file.size);
}
_findclose(hFile);
}
/* check the file exist... */
if((_access(fname, 0)) != -1)
printf("\n%s file exists\n", fname);
else
{
printf("\n%s file not found lor!\n", fname);
/* just exit */
exit(1);
}
/* check the permission */
printf("\nTest the permission for %s file\n", fname);
/* if write, then change to read. Must check the write first
because file that can be write can also be read but not vice versa */
if((_access(fname, 2)) == 0)
{
printf("\n%s file has write permission!\n", fname);
printf("\nChange to read only permission...\n");
_chmod(fname, _S_IREAD);
printf("\nRetest the read only permission...\n");
if((_access(fname, 4)) == 0)
printf("%s file is READ ONLY!\n", fname);
exit(0);
}
/* if not write it should be read permission, then change to write permission*/
else
{
printf("\n%s file is READ ONLY!\n", fname);
printf("\nChange to write permission...\n");
_chmod(fname, _S_IWRITE);
printf("\nRetest for write permission...");
if((_access(fname, 2)) == 0)
printf("\n%s has write permission!\n", fname);
exit(0);
}
return 0;
}
A sample output:
Firstly, get the current drive...
Current drive is D:
Next, get the current working directory...
Current working directory is:
d:\mcruntime
Change the current working directory...
Current working directory is:
d:\test\testsubtwo\testsubthree
Listing of *.* files
RDO HID SYS ARC TYPE FILE DATE SIZE
--- --- --- --- ---- ---- ---- ----
N N N N N . Mon May 16 22:10:30 2005 0
N N N N N .. Mon May 16 22:10:30 2005 0
N N N Y N content.doc Sun Sep 19 12:19:25 2004 264192
Y N N Y N module32.html Tue Jun 01 22:27:12 2004 375168
Y N N N N module32_files Fri May 13 22:53:07 2005 0
N N N Y N paass.xls Fri Oct 29 23:02:26 2004 21504
Y N N Y N preface.txt Thu Aug 12 15:45:38 2004 906
N N N Y N robots.txt Sun Oct 03 20:23:50 2004 3138
content.doc file exists
Test the permission for content.doc file
content.doc file has write permission!
Change to read only permission...
Retest the read only permission...
content.doc file is READ ONLY!
Press any key to continue
Through Windows, let verify through the file Properties.
Figure 1
Then, rerun the same program second time and the expected output is shown below.
Firstly, get the current drive...
Current drive is D:
Next, get the current working directory...
Current working directory is:
d:\mcruntime
Change the current working directory...
Current working directory is:
d:\test\testsubtwo\testsubthree
Listing of *.* files
RDO HID SYS ARC TYPE FILE DATE SIZE
--- --- --- --- ---- ---- ---- ----
N N N N N . Mon May 16 22:10:30 2005 0
N N N N N .. Mon May 16 22:10:30 2005 0
Y N N Y N content.doc Sun Sep 19 12:19:25 2004 264192
Y N N Y N module32.html Tue Jun 01 22:27:12 2004 375168
Y N N N N module32_files Fri May 13 22:53:07 2005 0
N N N Y N paass.xls Fri Oct 29 23:02:26 2004 21504
Y N N Y N preface.txt Thu Aug 12 15:45:38 2004 906
N N N Y N robots.txt Sun Oct 03 20:23:50 2004 3138
content.doc file exists
Test the permission for content.doc file
content.doc file is READ ONLY!
Change to write permission...
Retest for write permission...
content.doc has write permission!
Press any key to continue
Verify through the file Properties.
Figure 2
Well, the Read-only check box is unchecked means the file has write permission. Very nice huh?
Besides the authentication, there are authorizations for all objects in Windows. For authentication example, you have the access permission using the given username and password.
But what about right permission? Can you do anything for any objects in Windows when you have the access permission? Not at all, except for Administrators and System credentials :o).
We will learn more about this in Windows OS Security Programming.
Another example run using VC++ EE 2005 with SDK.
/* playing with directory, file and permission */
#include <stdio.h>
#include <stdlib.h>
#include <direct.h>
#include <io.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <windows.h> /* GetLastError() */
int main(void)
{
int curdrive;
char buffer[_MAX_PATH];
/* file name, change accordingly to other file */
char fname[50] = "test.doc";
char buff[50] = "";
/* path, change accordingly to other path available on your machine */
char dir[50] = "D:\\mycd1\\Ethertest8712";
struct _finddata_t c_file;
/* file handle */
intptr_t hFile;
/* ---------------------------------------------- */
printf("Firstly, get the current drive...\n");
curdrive = _getdrive();
printf("Current drive is %c:\n\n", curdrive + 'A'-1);/* ----------------------------------------------- */
printf("Next, get the current working directory...\n");
printf("Current working directory is: \n");
if(_getcwd(buffer, _MAX_PATH) == NULL)
perror("_getcwd() error lol!");
else
printf("%s\n\n", buffer);
/*----------------------------------------------- */
printf("Change the current working directory...\n");
_chdir(dir);
printf("\n");
/*------------------------------------------------ */
printf("Current working directory is: \n");
if(_getcwd(buffer, _MAX_PATH) == NULL)
perror("_getcwd() error");
else
printf("%s\n\n", buffer);
/* ------------------------------------------------ */
hFile = _findfirst("*.*", &c_file);
{
printf("Listing of *.* files\n\n");
printf("\nRDO HID SYS ARC TYPE FILE DATE %19c SIZE\n", ' ');
printf("--- --- --- --- ---- ---- ---- %19c ----\n", ' ');
printf((c_file.attrib & _A_RDONLY) ? " Y " : " N ");
printf((c_file.attrib & _A_HIDDEN) ? " Y " : " N ");
printf((c_file.attrib & _A_SYSTEM) ? " Y " : " N ");
printf((c_file.attrib & _A_ARCH) ? " Y " : " N ");
printf((c_file.attrib & _A_NORMAL) ? " Y " : " N ");
ctime_s(buff, 50, &(c_file.time_write));
printf(" %-15s %.24s %6d\n", c_file.name, buff, c_file.size );
/* find the rest of the files */
while(_findnext(hFile, &c_file) == 0)
{
printf((c_file.attrib & _A_RDONLY) ? " Y " : " N ");
printf((c_file.attrib & _A_HIDDEN) ? " Y " : " N ");
printf((c_file.attrib & _A_SYSTEM) ? " Y " : " N ");
printf((c_file.attrib & _A_ARCH) ? " Y " : " N ");
printf((c_file.attrib & _A_NORMAL) ? " Y " : " N ");
ctime_s(buff, 50, &(c_file.time_write));
printf(" %-15s %.24s %6d\n", c_file.name, buff, c_file.size);
}
_findclose(hFile);
}
/* check the file existence... 00 - Existence only, 02 - Write-only, 04 - Read-only, 06 - Read and write */
if((_access(fname, 0)) != -1)
printf("\n%s file exists\n", fname);
else
{
printf("\n%s file not found lor! Error: %d\n", fname, GetLastError());
/* just exit */
exit(1);
}
/* check the permission */
printf("\nTest the permission for %s file\n", fname);
/* if write, then change to read. Must check the write first because file that can be write can also be read but not vice versa */
if((_access(fname, 2)) == 0)
{
printf("\n%s file has write permission!\n", fname);
printf("\nChange to read only permission...\n");
_chmod(fname, _S_IREAD);
printf("\nRetest the read only permission...\n");
if((_access(fname, 4)) == 0)
printf("%s file is READ ONLY!\n", fname);
exit(0);
}
/* if not write it should be read permission, then change to write permission*/
else
{
printf("\n%s file is READ ONLY!\n", fname);
printf("\nChange to write permission...\n");
_chmod(fname, _S_IWRITE);
printf("\nRetest for write permission...");
if((_access(fname, 2)) == 0)
printf("\n%s has write permission!\n", fname);
exit(0);
}
return 0;
}
A sample output output: