File and device input/output

Random access -- lseek

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));

Next topic: File and record locking
Previous topic: Simplified version of cp

© 2004 The SCO Group, Inc. All rights reserved.
UnixWare 7 Release 7.1.4 - 27 April 2004