|
|
Normally, file I/O is sequential: each read or write proceeds from the point in the file right after the previous one. This means that if a particular byte in the file was the last byte written (or read), the next I/O call implicitly refers to the immediately following byte. For each open file, UNIX System V maintains a file-offset that indicates the next byte to be read or written. If n bytes are read or written, the file-offset advances by n bytes. When necessary, however, a file can be read or written in any arbitrary order using lseek to move around in a file without actually reading or writing.
To do random (direct-access) I/O it is only necessary to move the file-offset to the appropriate location in the file with a call to lseek. Calling lseek as follows:
lseek(fildes, offset, whence);
or as follows:
location = lseek(fildes, offset, whence);
forces the current position in the file denoted by file-descriptor
fildes to move to position offset as specified by
whence.
Subsequent reading or writing begins at the new position.
The file-offset associated with fildes is moved to a position
offset bytes from the beginning of the file, from the current
position of the file-offset or from the end of the file, depending on
whence; offset may be negative.
For some devices (e.g., paper tape and terminals) lseek calls are ignored.
The value of location equals the actual offset from the beginning
of the file to which the file-offset was moved.
The argument offset is of type off_t defined by the
header file <types.h> as a long; fildes
and whence are int's.
The argument whence can be SEEK_SET, SEEK_CUR
or SEEK_END to specify that offset is to be measured
from the beginning, from the current position, or from the end of
the file respectively.
For example, to append a file, seek to the end before writing:
lseek(fildes, 0L, SEEK_END);
To get back to the beginning (``rewind''),
lseek(fildes, 0L, SEEK_SET);
Notice the 0L argument; it could also be written as (long) 0.
With lseek, you can treat files more or less like large arrays, at the price of slower access. For example, the following simple function reads any number of bytes from any arbitrary point in a file:
get(fd, p, buf, n) /* read n bytes from position p */ int fd, n; long p; char *buf; { lseek(fd, p, SEEK_SET); /* move to p */ return(read(fd, buf, n)); }