4.3 Opening and Closing Files

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 .

errno

cause

EACCES

search permission on component of path prefix denied , or file exists and permissions specified by oflag denied, or file does not exist and write permission on parent directory denied, or O_TRUNC specified and write permission denied

EEXIST

O_CREAT and OEXCL are set and named file already exists

EINTR

signal was caught during open

EISDIR

named file is directory and oflag includes O_WRONLY or O_RDWR

ELOOP

a loop exists in resolution of path

EMFILE

OPEN_MAX file descriptors currently open in calling process

ENAMETOOLONG

the length of path exceeds PATH_MAX , or a pathname component is longer than NAME_MAX

ENFILE

maximum allowable number of files currently open in system

ENOENT

O_CREAT not set and name file does not exist, or O_CREAT is set and either path prefix does not exist or or path is an empty string

ENOSPC

directory or file system for new file cannot be expanded, the file does not exist and O_CREAT is specified

ENOTDIR

a component of the path prefix is not a directory

ENXIO

O_NONBLOCK is set, the named file is a FIFO, O_WRONLY is set, no process has file open for reading; file is a special file and device associated with file does not exist

EOVERFLOW

named file is a regular file and size cannot be represented by an object of type off_t

EROFS

the named file resides on a read-only file system and one of O_WRONLY, O_RDWR, O_CREAT (if the file does not exist), or O_TRUNC is set in oflag

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.11

The 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.12

How 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.13

The 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.14

How 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.

graphics/04fig01.gif

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.

symbol

meaning

S_IRUSR

read by owner

S_IWUSR

write by owner

S_IXUSR

execute by owner

S_IRWXU

read, write, execute by owner

S_IRGRP

read by group

S_IWGRP

write by group

S_IXGRP

execute by group

S_IRWXG

read, write, execute by group

S_IROTH

read by others

S_IWOTH

write by others

S_IXOTH

execute by others

S_IRWXO

read, write, execute by others

S_ISUID

set user ID on execution

S_ISGID

set group ID on execution

Example 4.15

The 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.c

A 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 .

errno

cause

EBADF

fildes is not a valid file descriptor

EINTR

the close function was interrupted by a signal

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.c

The 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


Unix Systems Programming
UNIX Systems Programming: Communication, Concurrency and Threads
ISBN: 0130424110
EAN: 2147483647
Year: 2003
Pages: 274

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net