The UNIX kernel maintains considerable detail about every file system object. This is true whether the object is a file, a directory, a special device node, or a named pipe. Whatever the file system object is, several properties are tracked and maintained for it.
The stat(2) and fstat(2) functions return information about file system objects in a structure named stat. The synopsis for the stat structure is as follows:
struct stat { dev_t st_dev; /* device */ ino_t st_ino; /* inode */ mode_t st_mode; /* protection */ nlink_t st_nlink; /* number of hard links */ uid_t st_uid; /* user ID of owner */ gid_t st_gid; /* group ID of owner */ dev_t st_rdev; /* device type (if inode dev) */ #ifndef _POSIX_SOURCE struct timespec st_atimespec; /* time of last access */ struct timespec st_mtimespec; /* time of last data modification */ struct timespec st_ctimespec; /* time of last file status change */ #else time_t st_atime; /* time of last access */ long st_atimensec; /* nsec of last access */ time_t st_mtime; /* time of last data modification */ long st_mtimensec; /* nsec of last data modification */ time_t st_ctime; /* time of last file status change */ long st_ctimensec; /* nsec of last file status change */ #endif off_t st_size; /* file size, in bytes */ int64_t st_blocks; /* blocks allocated for file */ u_int32_t st_blksize; /* optimal blocksize for I/O */ u_int32_t st_flags; /* user defined flags for file */ u_int32_t st_gen; /* file generation number */ } ; #ifndef _POSIX_SOURCE #define st_atime st_atimespec.tv_sec #define st_mtime st_mtimespec.tv_sec #define st_ctime st_ctimespec.tv_sec #endif struct timespec { time_t tv_sec; /* seconds */ long tv_nsec; /* and nanoseconds */ } ;
The definition shown is the one documented by FreeBSD Release 3.4. This definition shows the difference that exists, depending on whether or not POSIX standards are being used. When POSIX standards are not in use, the members st_atimespec, st_mtimespec, and st_ctimespec are defined in terms of the structure timespec. Then macros are used to equate, for example, the name st_atime to st_atimespec.
When POSIX standards are used, the st_atime member is defined in terms of the C type time_t, as has been the traditional type for this member. If finer-grained time information is required, the member st_atimensec can be consulted when compiling to POSIX standards.
Note
SGI's IRIX 6.5 describes the access, modified, and create date/time structure members in terms of the C data type timespec_t. Many other UNIX systems such as HPUX 10 and 11, Solaris 8, and UnixWare 7 describe the stat members in simple terms of the C data type time_t.
The stat(2) function allows the programmer to supply the pathname of the file system object and retrieve file system properties. The function synopsis for stat(2) is as follows:
#include <sys/types.h> #include <sys/stat.h> #include <unistd.h> int stat(const char *file_name, struct stat *buf);
The stat(2) function returns 0 when it is successful. When the call fails, -1 is returned with an error code placed in the global variable errno.
You can use the following code to obtain information about the executable file bin/a.out:
struct stat sbuf; if ( stat("bin/a.out",&sbuf) == -1 ) { fprintf(stderr,"%s: stat(2) ",strerror(errno)); abort(); }
The code shows how the properties are returned to the structure sbuf for the file a.out. The programmer can then access the members of variable sbuf to work with the file properties.
Warning
stat(2) and fstat(2) under SGI IRIX 6.5 are capable of returning EINTR if a signal is caught.
Table 6.1 reviews the stat structure members in detail, complete with units.
Data Type | Member Name | Description |
---|---|---|
dev_t | st_dev | The device number for this file system. |
ino_t | st_ino | The i-node number for this file system entry. |
mode_t | st_mode | File system object permission bits. |
nlink_t | st_nlink | The number of hard links to this file. |
uid_t | st_uid | The uid number of the owning user for this file system object. |
gid_t | st_gid | The gid number of the group for this file system object. |
dev_t | st_rdev | The device type, if the device is an i-node device. |
time_t | st_atime | The time this file system object was last accessed. |
long | st_atimensec | The last access time in nanoseconds. |
time_t | st_mtime | The time this file system object was last modified. |
long | st_mtimensec | The time of last modification in nanoseconds. |
time_t | st_ctime | The time of creation for this file system object. |
long | st_ctimensec | The time of creation in nanoseconds. |
off_t | st_size | The total size in bytes of this file system object. |
int64_t | st_blocks | The number of blocks allocated to this file system object. |
u_int32_t | st_blksize | The block size for file system I/O. |
u_int32_t | st_flags | User-defined flags for file. This appears to be a FreeBSD extension. |
u_int32_t | st_gen | File generation number. This appears to be a FreeBSD extension. |
The HPUX operating system also includes another useful piece of information:
struct stat { … uint st_acl:1; /* Set if the file has optional */ /* access control list entries */ /* HFS File Systems only */ } ;
When set, the flag bit member st_acl indicates that access control list (ACL) entries exist for that file. Only certain types of file systems, including HP's HFS file system, support access control list entries.
There are situations where it is necessary to obtain properties of the file system object that is open on a file descriptor. In this situation, you may not have the pathname for the object. The fstat(2) function solves this problem by allowing you to retrieve properties for the object open on the file descriptor.
#include <sys/types.h> #include <sys/stat.h> #include <unistd.h> int fstat(int fd, struct stat *sb);
For a file that is open on file descriptor fd, the following example shows how fstat(2) is used:
int fd; /* Open file descriptor */ struct stat sbuf; if ( fstat(fd,&sbuf) == -1 ) { fprintf(stderr,"%s: fstat(2) ",strerror(errno)); abort(); }
In this example, the structure sbuf receives all of the file properties for the object open on file unit fd.
In order to put the stat(2) and fstat(2) functions through their paces, a simple C++ object will be created to allow a few simple tests to be performed. The system call functions will be encapsulated in the object and then tested by calling upon the object methods. Listing 6.1 shows the C++ program.
The program in Listing 6.1 defines the class Stat, beginning at line 14. This class inherits from the stat structure and leaves the stat members exposed for simplicity (note the public keyword in line 14). Two additional private members, path and fd, are declared in lines 17 and 18 for tracking purposes.
Two examine C++ methods are declared in lines 24 and 25 to allow the object to inquire by pathname or by file descriptor. This eventually translates to a call to stat(2) or fstat(2), respectively.
Lines 45–58 declare the implementation of the inquiry by pathname. Line 54 shows the call to stat(2). Note that this method is coded to throw the errno value if an error is returned by stat(2). Lines 64–79 likewise define the implementation of the inquiry by open file descriptor. The fstat(2) call appears in line 75, and again, errno is thrown if an error is returned.
Lines 86–125 define a friend function (see line 28) that allows the class Stat to be sent to cout with the << operator. This provides a simple dump of the stat structure members.
The loop in the main() program in lines 165–183 performs the task of examining every pathname provided on the command line (line 168). Any error is caught in line 169 and reported in lines 171–173. If s.examine(argv[x]) executes successfully, control passes to line 176, where the contents of the object are formatted for output.
The following session shows the program in Listing 6.1 being compiled and tested using the file Makefile:
$ make stat cc -c -D_POSIX_C_SOURCE=199309L -Wall -fhandle-exceptions stat.cc cc stat.o -o stat -lstdc++ $ ./stat Makefile stat(Makefile) { st_dev = 196613; st_ino = 125953; st_mode = 0100644; st_nlink = 1; st_uid = 1001; st_gid = 1001; st_rdev = 525400; st_atime = 956797796; st_mtime = 956723168; st_ctime = 956723168; st_size = 378; st_blocks = 2; st_blksize = 8192; st_flags = 0; st_gen = 0; } ; 'Makefile'is not the same file as ./stat $
Notice that, if we verify a few attributes of the file Makefile, they will agree with the output shown:
$ ls -li Makefile
125953 -rw-r--r-- 1 me mygrp 378 Apr 26 00:26 Makefile
$
The file size of 378 bytes matches the value shown for st_size, and the permissions -rw-r--r-- match the lower 3 octal digits of st_mode for permission bits. The -i option of the ls(1) command causes the i-node number to be displayed. It is shown as 125953 and agrees with the st_ino value shown.
When the device number in st_dev and the i-node in st_ino match for two different pathnames, this indicates that these are links to the same file. The method int operator==(Stat &o) is defined in the class Stat of Listing 6.1 to allow the user of Stat objects to perform such a comparison test. The method is implemented in lines 132–149.
This class method is tested in the main() program by initially obtaining the stat(2) information on the executable file ./stat in line 161. Then the command-line argument is compared against this in line 181 (note the s == t expression before the ? operator).
In the earlier test run, the message
'Makefile'is not the same file as ./stat
was shown. However, if this program is tested again with new_link as the argument that is linked to ./stat, then the following results are obtained:
$ ln ./stat new_link $ ./stat new_link stat(new_link) { st_dev = 196613; st_ino = 125955; st_mode = 0100755; st_nlink = 2; st_uid = 1001; st_gid = 1001; st_rdev = 525312; st_atime = 956797797; st_mtime = 956797797; st_ctime = 956798301; st_size = 12080; st_blocks = 24; st_blksize = 8192; st_flags = 0; st_gen = 0; } ; 'new_link'is same file as ./stat $ ls -li new_link stat 125955 -rwxr-xr-x 2 me mygrp 12080 Apr 26 21:09 new_link 125955 -rwxr-xr-x 2 me mygrp 12080 Apr 26 21:09 stat $
After creating a link new_link to ./stat, the program correctly states that the pathname new_link is the same file as ./stat. This is reported from lines 180–182 of the main() program.
The st_mode member also holds information about the type of file system object. To determine the object type, use one of the following macros, where m is the st_mode value to be tested. The following tests and macros can be used:
symbolic link | S_ISLNK(m) |
regular file | S_ISREG(m) |
directory | S_ISDIR(m) |
character special device | S_ISCHR(m) |
block special device | S_ISBLK(m) |
named pipe (FIFO) | S_ISFIFO(m) |
socket | S_ISSOCK(m) |
These macros test the high order bits in the stat structure member st_mode.
The following code shows how a function could report the type of the file system object path that is provided as an argument:
static void report_type(const char *path) { struct stat sbuf; char *cp = "?"; if ( stat(path,&sbuf) == -1 ) { /* Report stat(2) error */ fprintf(stderr,"%s: stat(%s) ", strerror(errno),path); return; } if ( S_ISDIR(sbuf.st_mode) ) cp = "directory"; else if ( S_ISREG(sbuf.st_mode) ) cp = "regular file"; else if ( S_ISCHR(sbuf.st_mode) ) cp = "character raw device"; else if ( S_ISBLK(sbuf.st_mode) ) cp = "block raw device"; else if ( S_ISFIFO(sbuf.st_mode) ) cp = "named pipe (FIFO)"; else if ( S_ISSOCK(sbuf.st_mode) ) cp = "UNIX socket"; else if ( S_ISLNK(sbuf.st_mode) ) cp = "symbolic link"; printf("Path %s is a %s ",path,cp); }
This example shows how the stat structure member st_mode is used in each of the test macro calls.
The time values st_atime, st_mtime, and st_ctime are sometimes valuable assets to the programmer. Most of the time, the value st_mtime is examined, which represents the last modification for the object. However, the time of last access, st_atime, can be extremely useful if you need to see if the object has been recently accessed. The creation time, st_ctime, indicates when the object was created. The data type time_t is discussed in Chapter 11, "UNIX Date and Time Facilities."
Note
Calling stat(2) or fstat(2) to query a file system object's properties does not alter its date and time accessed.
3.142.174.55