Team-FLY |
The open function associates a file descriptor (the handle used in the program) with a file or physical device. The path parameter of open points to the pathname of the file or device, and the oflag parameter specifies status flags and access modes for the opened file. You must include a third parameter to specify access permissions if you are creating a file. SYNOPSIS #include <fcntl.h> #include <sys/stat.h> int open(const char *path, int oflag, ...); POSIX If successful, open returns a nonnegative integer representing the open file descriptor. If unsuccessful , open returns “1 and sets errno . The following table lists the mandatory errors for open .
Construct the oflag argument by taking the bitwise OR ( ) of the desired combination of the access mode and the additional flags. The POSIX values for the access mode flags are O_RDONLY, O_WRONLY and O_RDWR . You must specify exactly one of these designating read-only, write-only or read-write access, respectively. The additional flags include O_APPEND, O_CREAT, O_EXCL, O_NOCTTY, O_NONBLOCK and O_TRUNC . The O_APPEND flag causes the file offset to be moved to the end of the file before a write, allowing you to add to an existing file. In contrast, O_TRUNC truncates the length of a regular file opened for writing to 0. The O_CREAT flag causes a file to be created if it doesn't already exist. If you include the O_CREAT flag, you must also pass a third argument to open to designate the permissions. If you want to avoid writing over an existing file, use the combination O_CREAT O_EXCL . This combination returns an error if the file already exists. The O_NOCTTY flag prevents an opened device from becoming a controlling terminal. Controlling terminals are discussed in Section 11.5. The O_NONBLOCK flag controls whether the open returns immediately or blocks until the device is ready. Section 4.8 discusses how the O_NONBLOCK flag affects the behavior of read and write . Certain POSIX extensions specify additional flags. You can find the flags in fcntl.h . Example 4.11The following code segment opens the file /home/ann/my.dat for reading. int myfd; myfd = open("/home/ann/my.dat", O_RDONLY); This code does no error checking. Exercise 4.12How can the call to open of Example 4.11 fail? Answer: The open function returns “1 if the file doesn't exist, the open call was interrupted by a signal or the process doesn't have the appropriate access permissions. If your code uses myfd for a subsequent read or write operation, the operation fails. Example 4.13The following code segment restarts open after a signal occurs. int myfd; while((myfd = open("/home/ann/my.dat", O_RDONLY)) == -1 && errno == EINTR) ; if (myfd == -1) /* it was a real error, not a signal */ perror("Failed to open the file"); else /* continue on */ Exercise 4.14How would you modify Example 4.13 to open /home/ann/my.dat for nonblocking read? Answer: You would OR the O_RDONLY and the O_NONBLOCK flags. myfd = open("/home/ann/my.dat", O_RDONLY O_NONBLOCK); Each file has three classes associated with it: a user (or owner), a group and everybody else (others). The possible permissions or privileges are read(r), write(w) and execute(x). These privileges are specified separately for the user , the group and others. When you open a file with the O_CREAT flag, you must specify the permissions as the third argument to open in a mask of type mode_t . Historically, the file permissions were laid out in a mask of bits with 1's in designated bit positions of the mask, signifying that a class had the corresponding privilege. Figure 4.1 shows an example of a typical layout of such a permission mask. Although numerically coded permission masks frequently appear in legacy code, you should avoid using numerical values in your programs . Figure 4.1. Historical layout of the permissions mask.
POSIX defines symbolic names for masks corresponding to the permission bits so that you can specify file permissions independently of the implementation. These names are defined in sys/stat.h . Table 4.1 lists the symbolic names and their meanings. To form the permission mask, bitwise OR the symbols corresponding to the desired permissions. Table 4.1. POSIX symbolic names for file permissions.
Example 4.15The following code segment creates a file, info .dat , in the current directory. If the info.dat file already exists, it is overwritten. The new file can be read or written by the user and only read by everyone else. int fd; mode_t fdmode = (S_IRUSR S_IWUSR S_IRGRP S_IROTH); if ((fd = open("info.dat", O_RDWR O_CREAT, fdmode)) == -1) perror("Failed to open info.dat"); Program 4.9 copies a source file to a destination file. Both filenames are passed as command-line arguments. Because the open function for the destination file has O_CREAT O_EXCL , the file copy fails if that file already exists. Program 4.9 copyfilemain.cA program to copy a file . #include <fcntl.h> #include <stdio.h> #include <unistd.h> #include <sys/stat.h> #include "restart.h" #define READ_FLAGS O_RDONLY #define WRITE_FLAGS (O_WRONLY O_CREAT O_EXCL) #define WRITE_PERMS (S_IRUSR S_IWUSR) int main(int argc, char *argv[]) { int bytes; int fromfd, tofd; if (argc != 3) { fprintf(stderr, "Usage: %s from_file to_file\n", argv[0]); return 1; } if ((fromfd = open(argv[1], READ_FLAGS)) == -1) { perror("Failed to open input file"); return 1; } if ((tofd = open(argv[2], WRITE_FLAGS, WRITE_PERMS)) == -1) { perror("Failed to create output file"); return 1; } bytes = copyfile(fromfd, tofd); printf("%d bytes copied from %s to %s\n", bytes, argv[1], argv[2]); return 0; /* the return closes the files */ } Program 4.9 returns immediately after performing the copy and does not explicitly close the file. The return from main causes the necessary cleanup to release the resources associated with open files. In general, however, you should be careful to release open file descriptors by calling close . The close function has a single parameter, fildes , representing the open file whose resources are to be released. SYNOPSIS #include <unistd.h> int close(int fildes); POSIX If successful, close returns 0. If unsuccessful, close returns “1 and sets errno . The following table lists the mandatory errors for close .
Program 4.10 shows an r_close function that restarts itself after interruption by a signal. Its prototype is in the header file restart.h . Program 4.10 r_close.cThe r_close.c function is similar to close except that it restarts itself if interrupted by a signal . #include <errno.h> #include <unistd.h> int r_close(int fd) { int retval; while (retval = close(fd), retval == -1 && errno == EINTR) ; return retval; } |
Team-FLY |