Advanced Programming in the UNIX® Environment

(lily) #1
ptg10805159

68 File I/O Chapter 3


If we invoke this program interactively, we get
$./a.out < /etc/passwd
seek OK
$cat < /etc/passwd | ./a.out
cannot seek
$./a.out < /var/spool/cron/FIFO
cannot seek

Normally,afile’s current offset must be a non-negative integer.It is possible,
however,that certain devices could allow negative offsets. But for regular files, the
offset must be non-negative. Because negative offsets arepossible, we should be careful
to comparethe return value fromlseekas being equal to or not equal to−1, rather
than testing whether it is less than 0.
The/dev/kmemdevice on FreeBSD for the Intel x86 processor supports negative offsets.
Because the offset (off_t) is a signed data type (Figure2.21), we lose a factor of 2 in the
maximum file size. Ifoff_tis a 32-bit integer,the maximum file size is 2^31 −1bytes.
lseekonly records the current file offset within the kernel—itdoes not cause any
I/O to take place. This offset is then used by the next read or write operation.
The file’s offset can be greater than the file’s current size, in which case the next
writeto the file will extend the file. This is referred to as creating a hole in a file and is
allowed. Any bytes in a file that have not been written areread back as 0.
Ahole in a file isn’t required to have storage backing it on disk. Depending on the
file system implementation, when you write after seeking past the end of a file, new
disk blocks might be allocated to storethe data, but there is noneed to allocate disk
blocks for the data between the old end of file and the location whereyou start writing.

Example


The program shown in Figure3.2 creates a file with a hole in it.
#include "apue.h"
#include <fcntl.h>
char buf1[]="abcdefghij";
char buf2[]="ABCDEFGHIJ";
int
main(void)
{
int fd;
if ((fd = creat("file.hole", FILE_MODE)) < 0)
err_sys("creat error");
if (write(fd, buf1, 10) != 10)
err_sys("buf1 write error");
/* offset now = 10 */
Free download pdf