Next: Descriptors and Streams, Previous: I/O Primitives, Up: Low-Level I/O
Just as you can set the file position of a stream with fseek
, you
can set the file position of a descriptor with lseek
. This
specifies the position in the file for the next read
or
write
operation. See File Positioning, for more information
on the file position and what it means.
To read the current file position value from a descriptor, use
lseek (
desc, 0, SEEK_CUR)
.
The
lseek
function is used to change the file position of the file with descriptor filedes.The whence argument specifies how the offset should be interpreted, in the same way as for the
fseek
function, and it must be one of the symbolic constantsSEEK_SET
,SEEK_CUR
, orSEEK_END
.
SEEK_SET
- Specifies that whence is a count of characters from the beginning of the file.
SEEK_CUR
- Specifies that whence is a count of characters from the current file position. This count may be positive or negative.
SEEK_END
- Specifies that whence is a count of characters from the end of the file. A negative count specifies a position within the current extent of the file; a positive count specifies a position past the current end. If you set the position past the current end, and actually write data, you will extend the file with zeros up to that position.
The return value from
lseek
is normally the resulting file position, measured in bytes from the beginning of the file. You can use this feature together withSEEK_CUR
to read the current file position.If you want to append to the file, setting the file position to the current end of file with
SEEK_END
is not sufficient. Another process may write more data after you seek but before you write, extending the file so the position you write onto clobbers their data. Instead, use theO_APPEND
operating mode; see Operating Modes.You can set the file position past the current end of the file. This does not by itself make the file longer;
lseek
never changes the file. But subsequent output at that position will extend the file. Characters between the previous end of file and the new position are filled with zeros. Extending the file in this way can create a “hole”: the blocks of zeros are not actually allocated on disk, so the file takes up less space than it appears to; it is then called a “sparse file”. If the file position cannot be changed, or the operation is in some way invalid,lseek
returns a value of -1. The followingerrno
error conditions are defined for this function:
EBADF
- The filedes is not a valid file descriptor.
EINVAL
- The whence argument value is not valid, or the resulting file offset is not valid. A file offset is invalid.
ESPIPE
- The filedes corresponds to an object that cannot be positioned, such as a pipe, FIFO or terminal device. (POSIX.1 specifies this error only for pipes and FIFOs, but in the GNU system, you always get
ESPIPE
if the object is not seekable.)When the source file is compiled with
_FILE_OFFSET_BITS == 64
thelseek
function is in factlseek64
and the typeoff_t
has 64 bits which makes it possible to handle files up to 2^63 bytes in length.This function is a cancellation point in multi-threaded programs. This is a problem if the thread allocates some resources (like memory, file descriptors, semaphores or whatever) at the time
lseek
is called. If the thread gets canceled these resources stay allocated until the program ends. To avoid this calls tolseek
should be protected using cancellation handlers.The
lseek
function is the underlying primitive for thefseek
,fseeko
,ftell
,ftello
andrewind
functions, which operate on streams instead of file descriptors.
This function is similar to the
lseek
function. The difference is that the offset parameter is of typeoff64_t
instead ofoff_t
which makes it possible on 32 bit machines to address files larger than 2^31 bytes and up to 2^63 bytes. The file descriptorfiledes
must be opened usingopen64
since otherwise the large offsets possible withoff64_t
will lead to errors with a descriptor in small file mode.When the source file is compiled with
_FILE_OFFSET_BITS == 64
on a 32 bits machine this function is actually available under the namelseek
and so transparently replaces the 32 bit interface.
You can have multiple descriptors for the same file if you open the file
more than once, or if you duplicate a descriptor with dup
.
Descriptors that come from separate calls to open
have independent
file positions; using lseek
on one descriptor has no effect on the
other. For example,
{ int d1, d2; char buf[4]; d1 = open ("foo", O_RDONLY); d2 = open ("foo", O_RDONLY); lseek (d1, 1024, SEEK_SET); read (d2, buf, 4); }
will read the first four characters of the file foo. (The error-checking code necessary for a real program has been omitted here for brevity.)
By contrast, descriptors made by duplication share a common file position with the original descriptor that was duplicated. Anything which alters the file position of one of the duplicates, including reading or writing data, affects all of them alike. Thus, for example,
{ int d1, d2, d3; char buf1[4], buf2[4]; d1 = open ("foo", O_RDONLY); d2 = dup (d1); d3 = dup (d2); lseek (d3, 1024, SEEK_SET); read (d1, buf1, 4); read (d2, buf2, 4); }
will read four characters starting with the 1024'th character of foo, and then four more characters starting with the 1028'th character.
This is an arithmetic data type used to represent file sizes. In the GNU system, this is equivalent to
fpos_t
orlong int
.If the source is compiled with
_FILE_OFFSET_BITS == 64
this type is transparently replaced byoff64_t
.
This type is used similar to
off_t
. The difference is that even on 32 bit machines, where theoff_t
type would have 32 bits,off64_t
has 64 bits and so is able to address files up to 2^63 bytes in length.When compiling with
_FILE_OFFSET_BITS == 64
this type is available under the nameoff_t
.
These aliases for the `SEEK_...' constants exist for the sake of compatibility with older BSD systems. They are defined in two different header files: fcntl.h and sys/file.h.
L_SET
SEEK_SET
.
L_INCR
SEEK_CUR
.
L_XTND
SEEK_END
.