Team BBL
Previous Page Next Page

Chapter 4

4.1

If stat is called, it always tries to follow a symbolic link (Figure 4.17), so the program will never print a file type of "symbolic link." For the example shown in the text, where /dev/cdrom is a symbolic link to cdroms/cdrom0 (which itself is a symbolic link to ../scsi/host0/bus0/target0/lun0/cd), stat reports that /dev/cdrom is a block special file, not a symbolic link. If the symbolic link points to a nonexistent file, stat returns an error.

4.2

All permissions are turned off:

     $ umask 777
     $ date > temp.foo
     $ ls -l temp.foo
     ----------  1 sar           0 Feb 5 14:06 temp.foo

4.3

The following shows what happens when user-read permission is turned off:

     $ date > foo
     $ chmod u-r foo                    turn off user-read permission
     $ ls -l foo                        verify the file's permissions
     --w-r--r--  1 sar          29 Feb   5 14:21 foo
     $ cat foo                          and try to read it
     cat: foo: Permission denied

4.4

If we try, using either open or creat, to create a file that already exists, the file's access permission bits are not changed. We can verify this by running the program from Figure 4.9:

     $ rm foo bar               delete the files in case they already exist
     $ date > foo               create them with some data
     $ date > bar
     $ chmod a-r foo bar             turn off all read permissions
     $ ls -l foo bar                 verify their permissions
     --w-------   1 sar     29 Feb 5 14:25 bar
     --w-------   1 sar     29 Feb 5 14:25 foo
     $ ./a.out                       run program from Figure 4.9
     $ ls -l foo bar                 check permissions and sizes
     --w-------   1 sar     0 Feb   5 14:26 bar
     --w-------   1 sar     0 Feb   5 14:26 foo

Note that the permissions didn't change but that the files were truncated.

4.5

The size of a directory should never be 0, since there should always be entries for dot and dot-dot. The size of a symbolic link is the number of characters in the pathname contained in the symbolic link, and this pathname must always contain at least one character.

4.7

The kernel has a default setting for the file access permission bits when it creates a new core file. In this example, it was rw-r--r--. This default value may or may not be modified by the umask value. The shell also has a default setting for the file access permission bits when it creates a new file for redirection. In this example, it was rw-rw-rw-, and this value is always modified by our current umask. In this example, our umask was 02.

4.8

We can't use du, because it requires either the name of the file, as in

     du tempfile

or a directory name, as in

     du .

But when the unlink function returns, the directory entry for tempfile is gone. The du . command just shown would not account for the space still taken by tempfile. We have to use the df command in this example to see the actual amount of free space on the file system.

4.9

If the link being removed is not the last link to the file, the file is not removed. In this case, the changed-status time of the file is updated. But if the link being removed is the last link to the file, it makes no sense to update this time, because all the information about the file (the i-node) is removed with the file.

4.10

We recursively call our function dopath after opening a directory with opendir. Assuming that opendir uses a single file descriptor, this means that each time we descend one level, we use another descriptor. (We assume that the descriptor isn't closed until we're finished with a directory and call closedir.) This limits the depth of the file system tree that we can traverse to the maximum number of open descriptors for the process. Note that the ftw function as specified in the XSI extensions of the Single UNIX Specification allows the caller to specify the number of descriptors to use, implying that it can close and reuse descriptors.

4.12

The chroot function is used by the Internet File Transfer Program (FTP) to aid in security. Users without accounts on a system (termed anonymous FTP) are placed in a separate directory, and a chroot is done to that directory. This prevents the user from accessing any file outside this new root directory.

In addition, chroot can be used to build a copy of a file system hierarchy at a new location and then modify this new copy without changing the original file system. This could be used, for example, to test the installation of new software packages.

Only the superuser can execute chroot, and once you change the root of a process, it (and all its descendants) can never get back to the original root.

4.13

First, call stat to fetch the three times for the file; then call utime to set the desired value. The value that we don't want to change in the call to utime should be the corresponding value from stat.

4.14

The finger(1) command calls stat on the mailbox. The last-modification time is the time that mail was last received, and the last-access time is when the mail was last read.

4.15

Both cpio and tar store only the modification time (st_mtime) on the archive. The access time isn't stored, because its value corresponds to the time the archive was created, since the file has to be read to be archived. The -a option to cpio has it reset the access time of each input file after the file has been read. This way, the creation of the archive doesn't change the access time. (Resetting the access time, however, does modify the changed-status time.) The changed-status time isn't stored on the archive, because we can't set this value on extraction even if it was archived. (The utime function can change only the access time and the modification time.)

When the archive is read back (extracted), tar, by default, restores the modification time to the value on the archive. The m option to tar tells it to not restore the modification time from the archive; instead, the modification time is set to the time of extraction. In all cases with tar, the access time after extraction will be the time of extraction.

On the other hand, cpio sets the access time and the modification time to the time of extraction. By default, it doesn't try to set the modification time to the value on the archive. The -m option to cpio has it set both the access time and the modification time to the value that was archived.

4.16

The kernel has no inherent limit on the depth of a directory tree. But many commands will fail on pathnames that exceed PATH_MAX. The program shown in Figure C.3 creates a directory tree that is 100 levels deep, with each level being a 45-character name. We are able to create this structure on all platforms; however, we cannot obtain the absolute pathname of the directory at the 100th level using getcwd on all platforms. On Linux 2.4.22 and Solaris 9, we can never get getcwd to succeed while in the directory at the end of this long path. The program is able to retrieve the pathname on FreeBSD 5.2.1 and Mac OS X 10.3, but we have to call realloc numerous times to obtain a buffer that is large enough. Running this program on FreeBSD 5.2.1 gives us

Figure C.3. Create a deep directory tree
#include "apue.h"
#include <fcntl.h>

#define DEPTH    100           /* directory depth */
#define MYHOME   "/home/sar"
#define NAME     "alonglonglonglonglonglonglonglonglonglongname"
#define MAXSZ    8192

int
main(void)
{
    int      i, size;
    char     *path;

    if (chdir(MYHOME) < 0)
        err_sys("chdir error");

    for (i = 0; i < DEPTH; i++) {
        if (mkdir(NAME, DIR_MODE) < 0)
            err_sys("mkdir failed, i = %d", i);
        if (chdir(NAME) < 0)
            err_sys("chdir failed, i = %d", i);
    }
    if (creat("afile", FILE_MODE) < 0)
        err_sys("creat error");

    /*
     * The deep directory is created, with a file at the leaf.
     * Now let's try to obtain its pathname.
     */
    path = path_alloc(&size);
    for ( ; ; ) {
        if (getcwd(path, size) != NULL) {
            break;
        } else {
            err_ret("getcwd failed, size = %d", size);
            size += 100;
            if (size > MAXSZ)
                err_quit("giving up");
            if ((path = realloc(path, size)) == NULL)
                err_sys("realloc error");
        }
    }
    printf("length = %d\n%s\n", strlen(path), path);

    exit(0);
}

    $ ./a.out
    getcwd failed, size = 1025: Result too large
    getcwd failed, size = 1125: Result too large
    ...                        33 more lines
    getcwd failed, size = 4525: Result too large
    length = 4610
                           the 4,610-byte pathname is printed here

We are not able to archive this directory, however, using either tar or cpio. Both complain of a filename that is too long.

4.17

The /dev directory has all write permissions turned off to prevent a normal user from removing the filenames in the directory. This means that the unlink fails.

    Team BBL
    Previous Page Next Page