2 Copyright © 1995-2012, 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>
15 /*****************************************************************************
28 Reposition read/write file offset
31 filedef - the filedescriptor being modified
33 How to modify the current position. whence
34 can be SEEK_SET, then offset is the absolute position
35 in the file (0 is the first byte), SEEK_CUR then the
36 position will change by offset (ie. -5 means to move
37 5 bytes to the beginning of the file) or SEEK_END.
38 SEEK_END means that the offset is relative to the
39 end of the file (-1 is the last byte and 0 is
43 The new position on success and -1 on error. If an error occurred, the global
44 variable errno is set.
51 File is extended with zeros if desired position is beyond the end of
54 Since it's not possible to use Seek() for directories, this
55 implementation fails with EISDIR for directory file descriptors.
62 ******************************************************************************/
65 fdesc
*fdesc
= __getfdesc(filedes
);
73 if(fdesc
->fcb
->privflags
& _FCB_ISDIR
)
83 case SEEK_SET
: whence
= OFFSET_BEGINNING
; break;
84 case SEEK_CUR
: whence
= OFFSET_CURRENT
; break;
85 case SEEK_END
: whence
= OFFSET_END
; break;
92 cnt
= Seek (fdesc
->fcb
->handle
, offset
, whence
);
96 if(IoErr() == ERROR_SEEK_ERROR
)
98 LONG saved_error
= IoErr();
99 /* Most likely we tried to seek behind EOF. POSIX lseek allows
100 that, and if anything is written at the end on the gap,
101 reads from the gap should return 0 unless some real data
102 is written there. Since implementing it would be rather
103 difficult, we simply extend the file by writing zeros
104 and hope for the best. */
105 LONG abs_cur_pos
= Seek(fdesc
->fcb
->handle
, 0, OFFSET_CURRENT
);
106 if(abs_cur_pos
== -1)
108 LONG file_size
= Seek(fdesc
->fcb
->handle
, 0, OFFSET_END
);
111 /* Now compute how much we have to extend the file */
112 LONG abs_new_pos
= 0;
115 case OFFSET_BEGINNING
: abs_new_pos
= offset
; break;
116 case OFFSET_CURRENT
: abs_new_pos
= abs_cur_pos
+ offset
; break;
117 case OFFSET_END
: abs_new_pos
= file_size
+ offset
; break;
119 if(abs_new_pos
> abs_cur_pos
)
121 ULONG bufsize
= 4096;
122 APTR zeros
= AllocMem(bufsize
, MEMF_ANY
| MEMF_CLEAR
);
125 /* Restore previous position */
126 Seek(fdesc
->fcb
->handle
, abs_cur_pos
, OFFSET_BEGINNING
);
131 LONG towrite
= abs_new_pos
- abs_cur_pos
;
134 Write(fdesc
->fcb
->handle
, zeros
, MIN(towrite
, bufsize
));
139 FreeMem(zeros
, bufsize
);
143 /* Hmm, that's strange. Looks like ERROR_SEEK_ERROR has
144 been caused by something else */
145 SetIoErr(saved_error
);
153 return Seek(fdesc
->fcb
->handle
, 0, OFFSET_CURRENT
);
155 errno
= __stdc_ioerr2errno (IoErr ());