File Information

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

2 6 EXERCISE

Modify the example stat program so that its output is as close as possible to the ls -l output on your system when passed a file or directory name on the command line. Note, the stat call will not return the user's name (only the UID ). The UID can be passed to the getpwuid library call. The getpwuid call will return the user's name (along with additional password entry information). A description of the getpwuid library call is found in Section 3 of the manual. If needed, a second library call, getgrgid , can be used to map the GID value to the actual group name.

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 EXERCISE

The 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.

EXERCISE

Predict what will happen when a process fork s a child process and the child process issues a chdir system callwill the current directory for the parent be changed as well? Write a program that substantiates your answer.

   

2 9 Process Resource Limits

Категории