Add Book to My BookshelfPurchase This Book Online

Chapter 6 - Special-Purpose File Operations

UNIX Systems Programming for SVR4
David A. Curry
 Copyright © 1996 O'Reilly & Associates, Inc.

Miscellaneous Functions
There are several other special-purpose functions that are occasionally useful as well. Some of these are described in this section.
Controlling File Creation Modes
When a file is created, its permission bits are specified in the call to creat or open. As indicated in Chapter 3, Low-Level I/O Routines, these bits are modified by the process' umask value. Quite simply, the umask value is a set of permission bits to turn back off in any file creation mode. When a file is created, the permission bits specified in the call to creat or open are anded with the complement of the umask value to determine the actual bits that will be set:
    actual_mode = create_mode & ~umask;
Convention dictates that whenever a file is created with creat or open, the permission bits should be specified as 0666 (read/write for owner, group, and world). Each user can then use the umask value to control the actual permissions with which the file is created. For example, if a file is created with mode 0666 and the user's umask is 022, you get:
    actual_mode = create_mode & ~umask;
    actual_mode = 0666 & ~022;
    actual_mode = 0666 & 0755;
    actual_mode = 0644;
The file is created readable and writable by the user and readable by everyone else. If the user's umask is 077 instead, you get:
    actual_mode = create_mode & ~umask;
    actual_mode = 0666 & ~077;
    actual_mode = 0666 & 0700;
    actual_mode = 0600;
The file is created readable and writable by the user and nobody else is able to access it.
A process' umask value is set with the umask function:
    #include <sys/types.h>
    #include <sys/stat.h>
    mode_t umask(mode_t cmask);
The new value is specified by the cmask parameter, and the old value is returned. The umask is inherited by child processes, so all of the shells provide a built-in umask command to set the umask value of the shell (and therefore of all processes started by the shell).
The Root Directory
UNIX allows a process to change its notion of where the root of the filesystem is; that is, from where in the filesystem absolute pathnames begin. By default, each process uses / (the real root of the filesystem) as its root. However, in some instances, it is desirable to restrict a process to a specific area in the filesystem.
For example, many sites allow users from all over the world to connect to their hosts using the File Transfer Protocol (FTP) and log in as “anonymous” for the purpose of downloading files. However, these sites obviously don't want to give the entire world access to every file on the system; rather, these users should only be allowed to access files in a specific area. Even when one of these users specifies an absolute pathname (one that begins with a /), that pathname should be taken relative to this specific area.
To implement this, use the chroot function:
    #include <unistd.h>
    int chroot(const char *path);
    int fchroot(int fd);
The chroot function changes the calling process' root directory to the directory named in path. The fchroot function changes the calling process' root directory to the directory referenced by the file descriptor fd. Once this call has succeeded, all absolute pathnames are taken relative to this directory. Note that on systems that do not offer fchroot (most of them), there is no way to undo this call—because there is no way to reference a directory outside of the one named in path, there is no way to go back up. With fchroot, however, the higher-level directory can be opened prior to calling chroot and then can be used later to reset the root directory. Use of these two functions is restricted to the superuser.
Synchronizing a File with the Disk
When a process issues a write, the operating system transfers that data to a disk buffer and returns control to the process. At some later time (within a few milliseconds), the data is actually written to disk. This makes the system run much more efficiently, by allowing processes to run without having to stop and wait on (relatively) slow devices, and also by allowing the system to optimize device accesses. However, there are times when a program needs to know that the data on the disk is an accurate representation of what is written; it can't wait those extra few milliseconds.
To do this, the program uses the fsync function:
    #include <unistd.h>
    int fsync(int fd);
This function moves all modified data and attributes of the file referenced by the file descriptor fd to a storage device. When fsync returns, the calling process can be certain that all disk buffers associated with the file are written to the physical storage medium.
 NoteThe fsync function is not simply an alternative form of the sync function. A call to sync causes all modified disk buffers (for all files, not just those belonging to the calling process) to be scheduled for writing to disk. However, the call returns as soon as scheduling is complete; it does not wait for all the writes to be performed. The fsync function, on the other hand, causes the calling process to block until the disk buffers associated with fd are actually written to the disk (or other device).

Previous SectionNext Section
Books24x7.com, Inc © 2000 –  Feedback