CS 3733 Operating Systems Notes: Files



Directories

Figure 5.1 (page 146): Tree structures of a file system.


Current Working Directory

  #include <unistd.h>

  int chdir(const char *path);
  char *getcwd(char *buf, size_t size);
Program 5.1, page 149, outputs the pathname of the current working directory. It uses PATH_MAX to determine the size of the buffer needed.

Program 5.2, page 150, determines the implementation's maximum pathname length relative to the root directory using pathconf.

  #include <unistd.h>

  long fpathconf(int filedes, int name);
  long pathconf(const char *path, int name);
  long sysconf(int name);

Directory Access

  #include <dirent.h>

  DIR *opendir(const char *filename);
  struct dirent *readdir(DIR *dirp);
  void rewinddir(DIR *dirp);
  int closedir(DIR *dirp);
opendir provides a handle for the other functions.
readdir gets the next entry in the directory.
rewinddir restarts from the beginning.
closedir closes the handle.
Note that like strtok these are not reentrant.

Program 5.3 (page 153) lists the files in a directory.


Accessing file status information

  #include <sys/stat.h>

  int lstat(const char *restrict path, struct stat *restrict buf);
  int stat(const char *restrict path, struct stat *restrict buf);
  int fstat(int fildes, struct stat *buf);
stat is given the name of a file.
fstat is used for open files.
lstat does the same thing as stat except that if the file is a symbolic link, it gives information about the link, rather than the file it is linked to.
The contents of the struct stat are system dependent, but the standard says that it must contain at least the following foelds:
    dev_t    st_dev;      /* device ID of device containing file */
    ino_t    st_ino;      /* file serial number */
    mode_t   st_mode;     /* file mode */
    nlink_t  st_nlink;    /* number of hard links */
    uid_t    st_uid;      /* user ID of file */
    gid_t    st_gid;      /* group ID of file */
    off_t    st_size;     /* file size in bytes (regular files) */
                          /* path size (symbolic links) */
    time_t   st_atime;    /* time of last access */
    time_t   st_mtime;    /* time of last data modification */
    time_t   st_ctime;    /* time of last file status change */
Example 5.8, printaccess, page 155, displays the time that a file was last accessed.

Exercise 5.9, printaccessmodbad, page 156 shows an incorrect way of printing two times.

A correct solution is shown in prontaccessmod, page 156.

Use the following macros to test the st_mode field for the file type.
S_ISBLK(m) block special file
S_ISCHR(m) character special file
S_ISDIR(m) directory
S_ISFIFO(m) pipe or FIFO special file
S_ISLNK(m) symbolic link
S_ISREG(m) regular file
S_ISSOCK(m) socket

Example 5.10, isdirectory, page 157, shows how to determine whether a file is a directory.


Unix File System Implementation

Figure 5.2 (page 159): Structure of a typical UNIX file system.

Inodes
A directory entry contains only a name and an index into a table giving information about a file. The table and the index are both referred to as an inode.

This is what an inode looks like:

Figure 5.3 (page 160): Schematic structure of a traditional UNIX inide.


Exercise 5.12, page 160 (in part):
Suppose that the block size is 8K and pointers are 4 bytes. How large a file can be represented using single indirect pointers, double indirect pointers, and triple indirect pointers?
A block contains 2K pointers. A single indirect block can address 2K x 8K = 16 megabytes.
A double indirect block will contain 2K pointers to single indirect blocks for a total of 2K x 16 megabytes, or 32 gigabytes.
A triple indirect block can reference 2K times this, or 64 terabytes, however, this number is 233, so for 4-byte pointers we would be restricted to 32 terabytes.


Links

Figure 5.4 (page 91) shows a simple hard link and the associated inode.
Figure 5.5 (page 92) shows two hard links to the same file.

Figure 5.4 (page 163): A directory entry, inode, and data block for a simple file. Figure 5.5 (page 165): Two hard links to the same file as in Figure 5.4.


Exercise 5.17, page 166
What would happen to Figure 5.5 after the following sequence of operations:
open("/dirA/name1");
read
close
modify memory image of the file
unlink("/dirA/name1");
open("/dirA/name1");
write
close
Answer: The result is Figure 5.6 (page 167).
Figure 5.5 (page 165): Two hard links to the same file as in Figure 5.4. Figure 5.6 (page 167): The situation after editing the file. The original file had inode 12345 and two hard links prior to being edited.

Some editors make a backup copy of the file being edited. One way to do this is with the following:
open("/dirA/name1");
read
close
modify memory image file file
rename("/dirA/name1","dirA/name1.bak");
open("/dirA/name1");
write
close
The result is in Figure 5.7 (page 168).
Figure 5.5 (page 165): Two hard links to the same file as in Figure 5.4. Figure 5.7 (page 168): The situation after editing the file with an editor that makes a backup copy.


How to do it right:
open("/dirA/name1");
read
close
modify memory image file file
open("/dirA/name1",O_WRONLY|O_TRUNC);
write
close


Symbolic Links

Figure 5.8 (page 170) shows a file with a symbolic link.

Figure 5.8 (page 170): An ordinary file with a symbolic link to it.


Figure 5.9 (page 171) shows the result of making an editing change in the file /dirB/name2 when the editor changes the inode associated with the file read in.

Figure 5.9 (page 171): The situation after editing a file that has a symbolic link.