CS 355 - Systems Programming:
Unix/Linux with C
File Properties
Reference: Molay, Understanding Unix/Linux Programming, Chapter 3.6-3.9
The ls -l command
Our standard approach to studying a Unix system command:
What does ls -l do?
ls -l prints a list of file names located in the current directory in the long format
$ ls -l total 72 -rwxr-xr-x 1 stan staff 8772 Oct 6 10:31 a.out -rw-r--r--@ 1 stan staff 1040 Sep 29 11:55 cp.c drwxr-xr-x 2 stan staff 512 Oct 12 10:37 dir -rw-r--r--@ 1 stan staff 637 Oct 6 10:33 ls1.c -rw-r--r--@ 1 stan staff 1067 Sep 29 10:36 stuff.txt -rw-r--r-- 1 stan staff 1067 Sep 29 10:38 stuff1.txt -rw-r--r--@ 1 stan staff 1246 Sep 22 12:59 who1.c -rw-r--r--@ 1 stan staff 2392 Sep 22 12:46 who2.c
Read the manual:
LS(1) BSD General Commands Manual LS(1) NAME ls -- list directory contents . . . If the -l option is given, the following information is displayed for each file: file mode, number of links, owner name, group name, number of bytes in the file, abbreviated month, day-of-month file was last modi- fied, hour file last modified, minute file last modified, and the path- name. In addition, for each directory whose contents are displayed, the total number of 512-byte blocks used by the files in the directory is displayed on a line by itself, immediately before the information for the files in the directory. If the file or directory has extended attributes, the permissions field printed by the -l option is followed by a '@' character. Otherwise, if the file or directory has extended secu- rity information (such as an access control list), the permissions field printed by the -l option is followed by a '+' character. . . .
Each output line produced by ls -l consists of these seven fields:
How does ls -l do it?
ls -l uses the stat system call:
struct stat { dev_t st_dev; /* ID of device containing file */ ino_t st_ino; /* inode number */ 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 ID (if special file) */ off_t st_size; /* total size, in bytes */ blksize_t st_blksize; /* blocksize for file system I/O */ blkcnt_t st_blocks; /* number of 512B blocks allocated */ 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 */ };
The following mask values are defined for the file type component of the st_mode field:
S_IFMT 0170000 bit mask for the file type bit fields S_IFSOCK 0140000 socket S_IFLNK 0120000 symbolic link S_IFREG 0100000 regular file S_IFBLK 0060000 block device S_IFDIR 0040000 directory S_IFCHR 0020000 character device S_IFIFO 0010000 FIFO
The following mask values are defined for the file permissions component of the st_mode field:
S_ISUID 0004000 set-user-ID bit S_ISGID 0002000 set-group-ID bit S_ISVTX 0001000 sticky bit S_IRWXU 0000700 mask for file owner permissions S_IRUSR 0000400 owner has read permission S_IWUSR 0000200 owner has write permission S_IXUSR 0000100 owner has execute permission S_IRWXG 0000070 mask for group permissions S_IRGRP 0000040 group has read permission S_IWGRP 0000020 group has write permission S_IXGRP 0000010 group has execute permission S_IRWXO 0000007 mask for permissions for others (not in group) S_IROTH 0000004 others have read permission S_IWOTH 0000002 others have write permission S_IXOTH 0000001 others have execute permission
The set-group-ID bit S_ISGID has several special uses. For a directory: files created there inherit their group ID from the directory, not from the effective group ID of the creating process, and directories created there will also get the S_ISGID bit set. For a file that does not have the group execution bit S_IXGRP set, the set-group-ID bit indicates mandatory file/record locking.
The sticky bit S_ISVTX on a directory means that a file in that directory can be renamed or deleted only by the owner of the file, by the owner of the directory, and by a privileged process.
Can I write ls -l?
How to use masking to decode permission bits:
void mode_to_letters( int mode, char str[] ) { strcpy( str, "----------" ); /* default=no perms */ if ( S_ISDIR(mode) ) str[0] = 'd'; /* directory? */ if ( S_ISCHR(mode) ) str[0] = 'c'; /* char devices */ if ( S_ISBLK(mode) ) str[0] = 'b'; /* block device */ if ( mode & S_IRUSR ) str[1] = 'r'; /* 3 bits for user */ if ( mode & S_IWUSR ) str[2] = 'w'; if ( mode & S_IXUSR ) str[3] = 'x'; if ( mode & S_IRGRP ) str[4] = 'r'; /* 3 bits for group */ if ( mode & S_IWGRP ) str[5] = 'w'; if ( mode & S_IXGRP ) str[6] = 'x'; if ( mode & S_IROTH ) str[7] = 'r'; /* 3 bits for other */ if ( mode & S_IWOTH ) str[8] = 'w'; if ( mode & S_IXOTH ) str[9] = 'x'; }
How to produce a line containing file information:
void show_file_info( char *filename, struct stat *info_p ) { char *uid_to_name(), *ctime(), *gid_to_name(); void mode_to_letters(); char modestr[11]; mode_to_letters( info_p->st_mode, modestr ); printf( "%s" , modestr ); printf( "%4d " , (int) info_p->st_nlink); printf( "%-8s " , uid_to_name(info_p->st_uid) ); printf( "%-8s " , gid_to_name(info_p->st_gid) ); printf( "%8ld " , (long)info_p->st_size); printf( "%.12s ", 4+ctime(&info_p->st_mtime)); printf( "%s\n" , filename ); }
Functions uid_to_name() and gid_to_name() are used to obtain printable user and group names; see Molay pp. 88-91 for more detail.
Setting and modifying the properties of a file
Type of the file (whether it's a file or directory) is established when it is created and cannot be changed afterwards.
File type (e.g. "rwxr--r--") is established at the time of its creation:
fd = creat("newfile", 0744);
Useful system calls to modify the properties of a file include: