You have already seen that all the files and devices in a Linux system have an inode associated with them, through which they are accessed. The mode itself contains quite a lot of information related to the file, including:
With the exception of the last item, the values of all these attributes are readily available to a process if it knows the pathname to the file or if it has a file descriptor to an open file description associated with it.
In order to access them, the status attributes that are available to a process are copied into a struct stat, which is defined via <sys/stat.h>. The main fields in this structure are:
dev_t st_dev; /* device number */ ino_t st_ino; /* mode number */ umode_t st_mode; /* file type and permissions */ nlink_t st_nlink; /* link count */ uidt st_uid; /* owner ID of file */ gid_t st_gid; /* group ID of file */ dev_t st_rdev /* device numbers for device file */ off_t st_size; /* file size, in bytes */ time_t st_atime; /* time of last access */ time_t st_mtime /* time of last modification */ time_t st_ctime; /* time of last status change */
Symbolic constants giving values for the st_mode field in this structure are defined via <sys/stat.h>.
The information in this structure can be recovered using one of the three system calls fstat(), stat() or lstat():
#include <sys/stat h> #include <unistd h> int fstat(int fd, struct stat *sbuf); int stat(char *patbname, struct stat *sbuf); int lstat(char *pathname, struct stat *sbuf);
For fstat(), the fd parameter is a file descriptor to an open file description and sbuf is a pointer to a struct stat which will be filled with the appropriate status details by the call.
The stat() call is the same as fstat() except that the first parameter is the pathname to the file and not a file descriptor.
The lstat() call is the same as stat() except that if the file is a symbolic link lstat() will give the status details about the link file itself, whereas stat() will follow the link and give details about the file to which the link points.
All three system calls return 0 on successful completion, or -1 on error, with errno set to an appropriate value.
The following code is a simple program which will display human readable versions of the information in the struct stat associated with any given file pathnames:
#include <stdio.h> #include <sys/stat.h> #define MAJOR(a) (int)((unsigned short) (a) » 8) #define MINOR(a) (int)((unsigned short) (a) & OxFF) main(int argc, char **argv) { struct stat sbuf; int dev_flag; for (; argc>1; --argc) { printf("\nFile name: Xs\n", argv[argc-1]); if (stat(argv[argc-1], &sbuf)==-1) fatal("obtaining status details"); dev_flag = file_type(&sbuf); printf("Permission bits: %o\n", sbuf.st_mode & 07777); printf("File numbers: "); printf("major %d, ", MAJOR(sbuf.st_dev)); printf("minor %d, ", MINOR(sbuf.st_dev)); printf("inode %d\n", sbuf.st_ino); printf("Link count: %\n", sbuf.st_nlink); if (dev_flag) { printf("Device numbers: "); printf ("major %d, ", MAJOR(sbuf.st_rdev)); printf ("minor %d\n", MINOR(sbuf.st_rdev)); } else printf("File size: %ld\n", sbuf.st_size); printf("File owner ID: %d\n", sbuf.st_uid); printf("File group ID: %d\n", sbuf.st_gid); } } file_type(struct stat *sbufp) { printf("File type: "); switch (sbufp->st~mode & S_IFMT) { case S_IFREG: printf("Ordinary file\n"); return 0; case S_IFDIR: printf ("Dlrectory\n"); return 0; case S_IFIF0: printf("Named pipe (FIFO)\n"); return 0; case S_IFBLK: printf("Block device special file\n"); return 1; case S_IFCHR: printf("Character device special file\n"); return 1; default: printf("Unknown... \n"); exit(1) } } fatal(char *mess) { fprintf(stderr, "Error: %s\n", mess); exit(i); }
Notice that the program is capable of dealing with multiple file names on the command line. Typical output from the program appears as follows:
$ file_status /etc ./book.ps /dev/modem File name: /dev/modem File type: Character device special file Permission bits: 660 File numbers: major 3, minor 65, mode 47638 Link count: 1 Device numbers: major 5, minor 64 File owner ID: 0 File group ID: 14 File name: ./book.ps File type: Ordinary file Permission bits: 644 File numbers: major 3, minor 66, mode 34876 Link count: 1 File size: 1049173 File owner ID: 500 File group ID: 500 File name: /etc File type: Directory Permission bits: 755 File numbers: major 3, minor 65, mode 45701 Link count: 8 File size: 2048 File owner ID: 0 File group ID: 0