2 Copyright © 1995-2003, The AROS Development Team. All rights reserved.
5 Reposition read/write file offset.
10 #include <exec/exec.h>
11 #include <proto/exec.h>
12 #include <clib/macros.h>
16 /*****************************************************************************
29 Reposition read/write file offset
32 filedef - the filedescriptor being modified
34 How to modify the current position. whence
35 can be SEEK_SET, then offset is the absolute position
36 in the file (0 is the first byte), SEEK_CUR then the
37 position will change by offset (ie. -5 means to move
38 5 bytes to the beginning of the file) or SEEK_END.
39 SEEK_END means that the offset is relative to the
40 end of the file (-1 is the last byte and 0 is
44 The new position on success and -1 on error. If an error occurred, the global
45 variable errno is set.
52 File is extended with zeros if desired position is beyond the end of
55 Since it's not possible to use Seek() for directories, this
56 implementation fails with EISDIR for directory file descriptors.
63 ******************************************************************************/
66 fdesc
*fdesc
= __getfdesc(filedes
);
82 case SEEK_SET
: whence
= OFFSET_BEGINNING
; break;
83 case SEEK_CUR
: whence
= OFFSET_CURRENT
; break;
84 case SEEK_END
: whence
= OFFSET_END
; break;
91 cnt
= Seek ((BPTR
)fdesc
->fcb
->fh
, offset
, whence
);
95 if(IoErr() == ERROR_SEEK_ERROR
)
97 LONG saved_error
= IoErr();
98 /* Most likely we tried to seek behind EOF. POSIX lseek allows
99 that, and if anything is written at the end on the gap,
100 reads from the gap should return 0 unless some real data
101 is written there. Since implementing it would be rather
102 difficult, we simply extend the file by writing zeros
103 and hope for the best. */
104 LONG abs_cur_pos
= Seek(fdesc
->fcb
->fh
, 0, OFFSET_CURRENT
);
105 if(abs_cur_pos
== -1)
107 LONG file_size
= Seek(fdesc
->fcb
->fh
, 0, OFFSET_END
);
110 /* Now compute how much we have to extend the file */
111 LONG abs_new_pos
= 0;
114 case OFFSET_BEGINNING
: abs_new_pos
= offset
; break;
115 case OFFSET_CURRENT
: abs_new_pos
= abs_cur_pos
+ offset
; break;
116 case OFFSET_END
: abs_new_pos
= file_size
+ offset
; break;
118 if(abs_new_pos
> abs_cur_pos
)
120 ULONG bufsize
= 4096;
121 APTR zeros
= AllocMem(bufsize
, MEMF_ANY
| MEMF_CLEAR
);
124 /* Restore previous position */
125 Seek(fdesc
->fcb
->fh
, abs_cur_pos
, OFFSET_BEGINNING
);
130 LONG towrite
= abs_new_pos
- abs_cur_pos
;
133 Write(fdesc
->fcb
->fh
, zeros
, MIN(towrite
, bufsize
));
138 FreeMem(zeros
, bufsize
);
142 /* Hmm, that's strange. Looks like ERROR_SEEK_ERROR has
143 been caused by something else */
144 SetIoErr(saved_error
);
152 return Seek((BPTR
)fdesc
->fcb
->fh
, 0, OFFSET_CURRENT
);
154 errno
= IoErr2errno (IoErr ());