Base API


The open , read , and write functions can also be used for file I/O. The API differs somewhat, but we ll also look here at how to switch between file and stream mode with fdopen .

Note  

These functions are referred to as the base API because they are the platform from which the standard I/O library is built.

The open function allows us to open or create a new file. Two variations are provided, with their APIs listed here:

 int  open  ( const char *pathname, int flags );     int  open  ( const char *pathname, int flags, mode_t mode ); 

The pathname argument defines the file (with path ) to be opened or created (such as temp.txt or /tmp/myfile.txt ). The flags argument is one of O_RDONLY , O_WRONLY , or O_RDWR . One or more of the flags shown in Table 10.3 may also be OR d in, depending on the needs of the open call.

Table 10.3: Additional Flags for the open Function

Flag

Description

O_CREAT

Create the file if it doesn t exist.

O_EXCL

If used with O_CREAT , will return an error if the file already exists, otherwise the file is created.

O_NOCTTY

If the file descriptor refers to a TTY device, this process will not become the controlling terminal.

O_TRUNC

The file will be truncated (if it exists) and the length reset to zero if write privileges are permitted.

O_APPEND

The file pointer is repositioned to the end of the file prior to each write.

O_NONBLOCK

Opens the file in nonblocking mode. Operations on the file will not block (such as read , write , and so on).

O_SYNC

write functions are blocked until the data is written to the physical device.

O_NOFOLLOW

Fail following symbolic links.

O_DIRECTORY

Fail the open if the file being opened is not a directory.

O_DIRECT

Attempts to minimize cache effects by doing I/O directly to/from user space buffers (synchronously as with O_SYNC ).

O_ASYNC

Requests a signal when data is available on input or output of this file descriptor.

O_LARGEFILE

Request a large filesystem file to be opened on a 32-bit system whose size cannot be represented in 32 bits.

The third argument for the second open instance is a mode. This mode defines the permissions to be used with the file is created (used only with the flag O_CREAT ). Table 10.4 lists the possible symbolic constants that can be OR d together.

Table 10.4: Mode Arguments for the open System Call

Constant

Use

S_IRWXU

User has read/write/execute permissions.

S_IREAD

User has read permission.

S_IWRITE

User has write permission.

S_IEXEC

User has execute permission.

S_IRWXG

Group has read/write/execute permissions.

S_IRGRP

Group has read permission.

S_IWGRP

Group has write permission.

S_IXGRP

Group has execute permission.

S_IRWXO

Others have read/write/execute permissions.

S_IROTH

Others have read permission.

S_IWOTH

Others have write permission.

S_IXOTH

Others have execute permission.

To open a new file in the tmp directory, we could do this simply as:

 int fd;     fd =  open  ( "/tmp/newfile.txt", O_CREAT  O_WRONLY ); 

To instead open an existing file for read, we could open as follows :

 int fd;     fd =  open  ( "/tmp/newfile.txt", O_RDONLY ); 

Reading and writing to these files is done very simply with the read and write API functions.

 ssize_t  read  ( int fd, void *buf, size_t count );     ssize_t  write  ( int fd, const void *buf, size_t count ); 

These are used simply with a buffer and a size to represent the number of bytes to read or write, such as:

 unsigned char buffer[MAX_BUF+1];     int fd, ret;     ...     ret =  read  ( fd, (void *)buffer, MAX_BUF );     ...     ret =  write  ( fd, (void *)buffer, MAX_BUF ); 

We ll see more examples of these in Chapter 11. What s interesting here is that the same set of API functions to read and write data to a file can also be used for pipes and sockets. This represents a unique aspect of the UNIX-like operating systems, where many types of devices can be represented as files.

Finally, a file descriptor can be attached to a stream by using the fdopen system call. This call has the prototype:

 FILE *  fdopen  ( int filedes, const char *mode ); 

Therefore, if we ve opened a device using the open function call, we can associate a stream with it using fdopen and then use stream system calls on the device (such as fscanf or fprintf). Consider the following example:

 FILE *fp;     int fd;     fd =  open  ( "/tmp/myfile.txt", O_RDWR );     fp =  fdopen  ( fd, "rw" ); 

Once this is done, we can use read/write with the fd descriptor or fscanf/_fprintf with the fp descriptor.

One other useful API to consider is the pread/pwrite API. These functions require an offset into the file to read or write, but they do not affect the file pointer. These functions have the prototype:

 ssize_t  pread  ( int filedes, void *buf, size_t nbyte, off_t offset );     ssize_t  pwrite  ( int filedes, void *buf, size_t nbyte, off_t offset ); 

These functions require that the target be seekable (in other words, regular files) and are used regularly for record I/O in databases.




GNU/Linux Application Programming
GNU/Linux Application Programming (Programming Series)
ISBN: 1584505680
EAN: 2147483647
Year: 2006
Pages: 203
Authors: M. Tim Jones

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