Advanced Unix Programming Chapter 4 Files and Directories





































- Slides: 37

Advanced Unix Programming Chapter 4 – Files and Directories

stat • #include <sys/stat. h> • int stat(const char *restrict pathname, struct stat *restrict buf); • restrict keyword is used to tell the compiler which pointer references can be optimized, by indicating that the object to which the pointer refers is accessed in the function only via that pointer. (From section 2. 2 Unix Standardization)

stat … • Given a pathname stat returns a structure (of type stat) of information about the named file. • struct stat { • mode_t st_mode; /* file type & mode (permissions) */ • ino_t st_ino; /* i-node number (serial number) */ • dev_t st_dev; /* device number (file system) */ • dev_t st_rdev; /* device number for special files */ • nlink_t st_nlink; /* number of links */ • uid_t st_uid; /* user ID of owner */

stat … • • • gid_t st_gid; /* group ID of owner */ off_t st_size; /* size in bytes, for regular files */ time_t st_atime; /* time of last access */ time_t st_mtime; /* time of last modification */ time_t st_ctime; /* time of last file status change */ • blksize_t st_blksize; /* best I/O block size */ • blkcnt_t st_blocks; /* number of disk blocks allocated */ • };

File type • mode_t st_mode; /* file type & mode (permissions) */ • Use following macros to find out type of file: • S_ISREG(st_mode) regular file • S_ISDIR(st_mode) directory file • S_ISLNK(st_mode) symbolic link • S_ISCHR(st_mode) character special file • … • See Fig 4. 3 program

User ids • real user ID who we really are • effective user ID used for file access permission checks • When we execute a program file, the effective user ID of the process is usually the real user ID • Special flag in the file's mode word (st_mode) that says "when this file is executed, set the effective user ID of the process to be the owner of the file (st_uid)”. • Why do we need this? …

passwd program • passwd changes user password • That updates /etc/passwd or /etc/shadow typically • But /etc/passwd is writable only by root!! • Solution is to have root as owner of passwd program file and have its set-user-id bit on. • whereis, ll

S_ISUID • set-user-ID bit is contained in the file's st_mode value. • This bit can be tested against the constant S_ISUID. • man 2 stat for more info on S_ISUID • How to do this bit testing? ?

Bit testing • if (buf. st_mode & S_ISUID) //true if set uid bit is on else // false if set id bit is off

Group IDs • Group IDs is handled similarly. • Read Section 4. 4 for details.

File Access Permissions • • • st_mode also encode access permissions Bitmasks used are as follows: S_IRUSR user-read S_IWUSR user-write S_IXUSR user-execute S_IRGRP group-read S_IWGRP group-write S_IXGRP group-execute S_IROTH other-read S_IWOTH other-write S_IXOTH other-execute

File Access permissions… • How are these permissions are used by file i/o system calls? ? • Some cases are obvious but some are not • For details please read Section 4. 5 of book

Variants of stat • int fstat(int filedes, struct stat *buf); • fstat works on open file referred to by filedes • int lstat(const char *restrict pathname, struct stat *restrict buf); • lstat is similar to stat but if file is a symbolic link file then it gives info about the symbolic link instead of the file it points to (stat follows the link)

mode flag of open • Mode flag of open specifies the permissions for a new file • It uses the same constants/bitmask values as we just saw in stat (S_IRUSR, S_IRGRP etc. ) • See createfile. c (examples)

Assignment • See web page for report and assignment 4 b

umask • #include <sys/stat. h> • mode_t umask(mode_t cmask); • Returns: previous file mode creation mask • Never fails!!!

umask • Default value is 022 • Specifies that group-write, others-write should be masked when a file is being created. • See createfile 2. c • You will find that created file has groupwrite and others-write permission disabled!! • This is due to umask value of 022

umask … • See createfile 3. c which solves the problem. • Go through Section 4. 8 of book

chmod, chown • Very straightforward – Just read section 4. 9 and then 4. 11

link, unlink, rename • Hard link: ln command • Symbolic link: ln command with –s argument • Most commands on a symbolic link follow the link [cat, vi etc. ]

link, unlink • See 4. 14 File Systems of book: – – Fig 4. 13: Disk drive, partitions, file system Fig 4. 14: i-nodes and data blocks Directory is just a data file listing inode-filename pairs. Creation of new file needs: Creation of data block, inode and addition of new inode-filename pair entry to directory file. – Deletion of file needs: Removal of data block, inode and removal of inode-filename pair entry from directory file

link, unlink • Section 4. 14 contd. : – But same data file can have multiple hard links. See Fig 4. 14 – two different inode-filename pairs point to same inode (and so same data block) – Inode has a link count which specifies number of inodepairs ‘linked’ to it. (st_nlink member of stat structure) – rm command reduces link count in inode – And if that results in link count becoming zero, then and only then is the inode and data block deleted (assuming that the file is not open)

link, unlink • Therefore system call associated with rm is called unlink (and not delete). • Moving a file from one directory to another in the same filesystem only involves removal of inode-filename pair from source directory file and addition of inode-filename pair in destination directory

link • #include <unistd. h> • int link(const char *existingpath, const char *newpath); • Create newpath as a hard link to existing path • On Linux, newpath must be on same filesystem as existingpath

unlink • #include <unistd. h> • int unlink(const char *pathname); • Removes the directory entry and decrements the link count

Temporary file • Even when link count goes to 0, if file is open, the file is not deleted. • As soon as file is closed then the file is deleted. • This is used to create temporary files in Unix. See Fig 4. 16 (Sect 4. 15)

rename • #include <stdio. h> • int rename(const char *oldname, const char *newname); • Newname can be in a different directory in which case the file is moved to that directory (with a possible filename change as well) – See examples/filesanddir/rename. c • Also see rename. cpp

symlink, readlink • Symbolic links overcome following limitations of hard links: – Linked file must be on same filesystem – Only superuser can create link to a directory (danger of creating a loop in the filesystem – for more details refer to example in Section 4. 16) • ln –s file symbolic-link-file • Most commands (vi, cat etc. ) when given a symbolic link filename argument, actually operate on the file pointed to by the symbolic link

Symbolic link … • When a system call is given a symbolic link filename argument does it – operate on the symbolic link itself (does not follow the link)? – or does it operate on the file pointed to by the symbolic link (follows the link)? ? • Most system calls follow the link (chdir, chmod, open, stat etc. ) • But some do not (lchown, lstat, rename, unlink)

symlink • #include <unistd. h> • int symlink(const char *actualpath, const char *sympath); • Creates a symbolic link named sympath

readlink • How to read the symbolic link file? ? Open follows the link!! • #include <unistd. h> • ssize_t readlink(const char* pathname, char * buf, size_t bufsize); • readlink reads the symbolic link file itself. • Symbolic link file simply has the path of the file it is linked to • readlink places that data into passed buf and returns the number of bytes copied into buf • buf is NOT null terminated. • readlink combines the action of open, read and close in one single system call

mkdir, rmdir • #include <sys/stat. h> • int mkdir(const char *pathname, mode_t mode); • On successful completion, entries for. and. . are automatically added. • #include <unistd. h> • int rmdir(const char *pathname); • Removes empty directory

Reading a directory file • How do we read a directory file? ? • A directory file simply contains inodefilename pairs. • How these are stored is implementation dependent.

dirent structure • But functions that read a directory file use the following structure from <dirent. h> struct dirent { ino_t d_ino; /* i-node number */ char d_name[NAME_MAX + 1]; /* null-terminated filename */ } • Note that struct dirent is guaranteed to have above two members but it could have more members.

opendir, readdir, closedir • #include <dirent. h> • DIR *opendir(const char *pathname); Returns: pointer if OK, NULL on error • struct dirent *readdir(DIR *dp); Returns: pointer if OK, NULL at end of directory or error • int closedir(DIR *dp); Returns: 0 if OK, 1 on error • Note these are section 3 functions (library function) in Linux • Linux also has a system call (section 2) readdir which is not recommended for general usage.

Listing a directory • See examples/filesanddir/listdir. c (Simple directory list program) • ‘Simple’ file tree walker – Fig 4. 22 of Section 4. 21

Assignments • See web page for report and assignments 4 a, 4 c [4 b assignment has been already given] • The ambitious can do 4 d • The even-more-ambitious can look at the ‘Assignments given in previous years …’ and do those programs as well