There are a number of system calls that a process can use to obtain file information. Of these, the stat system calls (shown in Table 2.8) provide the process with a comprehensive set of file- related information somewhat analogous to the information that can be obtained by using the system-level stat command found in Linux. For example, the command
linux$ stat a.out File: "a.out" Size: 14932 Blocks: 32 Regular File Access: (0755/-rwxr-xr-x) Uid: ( 500/ gray) Gid: (1000/ faculty) Device: 815 Inode: 97541 Links: 1 Access: Tue Jan 1 16:05:58 2002 Modify: Tue Jan 1 16:05:57 2002 Change: Tue Jan 1 16:05:57 2002
displays information about the file a.out found in the current directory.
Table 2.8. Summary of the stat System Calls.
Include File(s) |
|
Manual Section |
2 |
||
Summary |
[View full width] int stat(const char *file_name, struct stat *buf); int lstat(const char *file_name, struct stat *buf); int fstat(int filedes, struct stat *buf); |
||||
Return |
Success |
Failure |
Sets errno |
||
1 |
Yes |
As its first argument, the stat system call takes a character pointer to a string containing the path for a file. The lstat system call is similar to stat except when the file referenced is a symbolic link. In the case of a symbolic link, lstat returns information about the link entry, while stat returns information about the actual file. The fstat system call takes an integer file descriptor value of an open file as its first argument.
All three stat system calls return, via their second argument, a pointer to a stat structure. The stat structure is defined in its entirety in the header file and the >. The file is automatically included by and should not be directly included by the programmer. The stat structure normally contains members for
dev_t st_dev; /* device file resides on */ ino_t st_ino; /* this file's number */ u_short st_mode; /* protection */ short st_nlink; /* number of hard links to the file */ short st_uid; /* user ID of owner */ short st_gid; /* group ID of owner */ dev_t st_rdev; /* the device identifier(special files only)*/ off_t st_size; /* total size of file, in bytes */ time_t st_atime; /* file data last access time */ time_t st_mtime; /* file data last modify time */ time_t st_ctime; /* file data last status change time */ long st_blksize; /* preferred blocksize for file system I/O*/ long st_blocks; /* actual number of blocks allocated */
The special data types (e.g., dev _ t , ino _ t ) of individual structure members are mapped to standard data types in the header file . If the stat system calls are successful, they return a value of 0. Otherwise, they return a value of -1 and set errno . As these system calls reference file information, there are numerous error situations that may be encountered . The value that errno may be assigned and an explanation of the associated perror message are shown in Table 2.9.
Table 2.9. stat Error Messages.
# |
Constant |
perror Message |
Explanation |
---|---|---|---|
2 |
ENOENT |
No such file or directory |
File does not exist (or is NULL). |
4 |
EINTR |
Interrupted system call |
Signal was caught during the system call. |
9 |
EBADF |
Bad file number |
The value in fildes is not a valid open file descriptor. |
12 |
ENOMEM |
Cannot allocate memory |
Out of memory (i.e., kernel memory). |
13 |
EACCES |
Permission denied |
Search permission denied on part of file path. |
14 |
EFAULT |
Bad address |
Path references an illegal address. |
20 |
ENOTDIR |
Not a directory |
Part of the specified path is not a directory. |
36 |
ENAMETOOLONG |
File name too long |
The path value exceeds system path/file name length. |
40 |
ELOOP |
Too many levels of symbolic links |
The perror message says it all. |
67 |
ENOLINK |
The link has been severed |
The path value references a remote system that is no longer active. |
72 |
EMULTIHOP |
Multihop attempted |
The path value requires multiple hops to remote systems, but file system does not allow it. |
75 |
EOVERFLOW |
Value too large for defined data type |
A value for a member of the structure referenced by buf is too large. |
A program showing the use of the stat system call is shown in Program 2.2.
Program 2.2 Using the stat system call.
/* Using the stat system call */ #include + #include #include #include #include using namespace std; 10 const int N_BITS = 3; int main(int argc, char *argv[ ]){ unsigned int mask = 0700; struct stat buff; + static char *perm[] = {"---", "--x", "-w-", "-wx", "r--", "r-x", "rw-", "rwx"}; if (argc > 1) { if ((stat(argv[1], &buff) != -1)) { cout << "Permissions for " << argv[1] << " "; 20 for (int i=3; i;-i) { cout << perm[(buff.st_mode & mask) >> (i-1)*N_BITS]; mask >>= N_BITS; } cout << endl; + } else { perror(argv[1]); return 1; } } else { 30 cerr << "Usage: " << argv[0] << "file_name "; return 2; } return 0; }
When this program is run and passed its own name on the command line, the output is as shown in Figure 2.11.
Figure 2.11 Output of Program 2.2.
linux$ p2.2 a.out Permissions for a.out rwxr-xr-x
The system command sequence ls -l for the same file produces the same set of permissions as shown in Figure 2.12.
Figure 2.12 Verifying Program 2.2 output with the ls command.
linux$ ls -l a.out -rwxr-xr-x 1 gray faculty 15290 Jan 2 07:26 a.out
In a programming environment, the access permissions of a file can be modified with the chmod / fchmod system calls (Table 2.10).
Table 2.10. Summary of the chmod/fchmod System Calls.
Include File(s) |
|
Manual Section |
2 |
|
Summary |
int chmod( const char *path, mode_t mode ); int fchmod( int fildes, mode_t mode ); |
|||
Return |
Success |
Failure |
Sets errno |
|
1 |
Yes |
Both system calls accomplish the same action and differ only in the format of their first argument. The chmod system call takes a character pointer reference to a file path as its first argument, while fchmod takes an integer file descriptor value of an open file. The second argument for both system calls is the mode. The mode can be specified literally as an octal number (e.g., 0755) or by bitwise OR ing together combinations of defined permission constants found in the header file . Unless the effective user ID of the process is that of the superuser, the effective user ID and the owner of the file whose permissions are to be changed must be the same. If either system call is successful, it returns a 0. Otherwise, the call returns a -1 and sets the value in errno . As with the stat system calls, the number of error conditions is quite extensive (see Table 2.11).
Table 2.11. chmod/fchmod Error Messages.
# |
Constant |
perror Message |
Explanation |
---|---|---|---|
1 |
EPERM |
Operation not permitted |
Not owner or file or superuser. |
2 |
ENOENT |
No such file or directory |
File does not exist (or is NULL). |
4 |
EINTR |
Interrupted system call |
Signal was caught during the system call. |
5 |
EIO |
I/O error |
I/O error while attempting read or write to file system. |
9 |
EBADF |
Bad file number |
The value in fildes is not a valid open file descriptor. |
12 |
ENOMEM |
Cannot allocate memory |
Out of memory (i.e., kernel memory). |
13 |
EACCES |
Permission denied |
Search permission denied on part of file path. |
14 |
EFAULT |
Bad address |
path references an illegal address. |
20 |
ENOTDIR |
Not a directory |
Part of the specified path is not a directory. |
30 |
EROFS |
Read-only file system |
File referenced by path is on read-only file system. |
36 |
ENAMETOOLONG |
File name too long |
The path value exceeds system path/file name length. |
40 |
ELOOP |
Too many levels of symbolic links |
The perror message says it all. |
67 |
ENOLINK |
The link has been severed |
The path value references a remote system that is no longer active. |
72 |
EMULTIHOP |
Multihop attempted |
The path value requires multiple hops to remote systems but file system does not allow it. |
The umask value, which is inherited from the parent process, may be modified by a process with the umask system call (Table 2.12).
Table 2.12. Summary of the umask System Call.
Include File(s) |
|
Manual Section |
2 |
|
Summary |
mode_t umask(mode_t mask); |
|||
Return |
Success |
Failure |
Sets errno |
|
The previous umask |
When invoked, umask both changes the umask value to the octal integer value passed and returns the old (previous) umask value. [6] If you use the umask system call to determine the current umask setting, you should call umask a second time, passing it the value returned from the first call, to restore the settings to their initial state. For example,
[6] This system call appears to have been written before such techniques were frowned upon (i.e., both changing the state of the umask and returning its current value).
mode_t cur_mask; cur_mask = umask(0); cout << "Current mask: " << setfill('0') << setw(4) << oct << cur_mask << endl; umask(cur_mask);
2 7 EXERCISEThe umask system call will never generate an error or set the value in errno . What happens if you attempt to assign a mask value of 011? |
The library function getcwd is used to copy the absolute path of the current working directory of a process to an allocated location. The function is defined as shown in Table 2.13. It returns a pointer to the directory pathname. The function expects two arguments. The first is a pointer to the location where the pathname should be stored. If this argument is set to NULL, getcwd uses malloc to automatically allocate storage space. The second argument is the length of the pathname to be returned (plus 1 for the to terminate the string). The include file contains the defined constant MAXPATHLEN that can be used to assure a buffer of sufficient size (i.e., MAXPATHLEN +1). In the following code snippet the space allocated to hold the path information will be just what is needed to store the absolute path (most likely less than MAXPATHLEN +1).
Table 2.13. Summary of the getcwd Library Function.
Include File(s) |
Manual Section |
3 |
||
Summary |
char *getcwd(char *buf, size_t size); |
|||
Return |
Success |
Failure |
Sets errno |
|
A pointer to the current directory name |
NULL |
Yes |
char *path; path = getcwd(NULL, MAXPATHLEN+1); cout << path << endl; cout << "Path length: " << strlen(path) << endl; // sufficient to hold path
If getcwd fails, it returns a NULL and sets errno (Table 2.14). If malloc is used to dynamically allocate storage, the space should be returned with free when it is no longer needed.
Table 2.14. getcwd Error Messages.
# |
Constant |
perror Message |
Explanation |
---|---|---|---|
13 |
EACCES |
Permission denied |
Search permission denied on part of file path. |
22 |
EINVAL |
Invalid argument |
The value for size is less than or equal to 0. |
34 |
ERANGE |
Numerical resultout of range |
The value for size is greater than 0 but less than the length of the path plus 1. |
The system call chdir is used to change the current working directory (as is the cd [7] command at system level). See Table 2.15.
[7] The cd command, unlike many other system-level commands, is not run as a child process, so its change will take effect for the current process.
The chdir system call takes a character pointer reference to a valid pathname (the process must have search permission for all directories referenced) as its argument. The fchdir system call takes an open file descriptor of a directory as its argument. If successful, the system call returns a 0, and the new working directory for the process will be the one specified. If the call fails, a -1 is returned and errno is set (Table 2.16).
Table 2.15. Summary of the chdir/fchdir System Calls.
Include File(s) |
Manual Section |
2 |
||
Summary |
int chdir( const char *path ); int fchdir( int fildes ); |
|||
Return |
Success |
Failure |
Sets errno |
|
1 |
Yes |
Table 2.16. chdir/fchdir Error Messages.
# |
Constant |
perror Message |
Explanation |
---|---|---|---|
2 |
ENOENT |
No such file or directory |
File does not exist (or is NULL). |
4 |
EINTR |
Interrupted system call |
Signal was caught during the system call. |
5 |
EIO |
I/O error |
I/O error while attempting read or write to file system. |
9 |
EBADF |
Bad file number |
The value in fildes is not a valid open file descriptor. |
12 |
ENOMEM |
Cannot allocate memory |
Out of memory (i.e., kernel memory). |
13 |
EACCES |
Permission denied |
Search permission denied on part of file path. |
14 |
EFAULT |
Bad address |
path references an illegal address. |
20 |
ENOTDIR |
Not a directory |
Part of the specified path is not a directory. |
36 |
ENAMETOOLONG |
File name too long |
The path value exceeds system path/file name length. |
40 |
ELOOP |
Too many levels of symbolic links |
The perror message says it all. |
67 |
ENOLINK |
The link has been severed |
The path value references a remote system that is no longer active. |
72 |
EMULTIHOP |
Multihop attempted |
The path value requires multiple hops to remote systems, but file system does not allow it. |
Programs and Processes
Processing Environment
Using Processes
Primitive Communications
Pipes
Message Queues
Semaphores
Shared Memory
Remote Procedure Calls
Sockets
Threads
Appendix A. Using Linux Manual Pages
Appendix B. UNIX Error Messages
Appendix C. RPC Syntax Diagrams
Appendix D. Profiling Programs