Fixed compatibility of output.
[AROS.git] / compiler / posixc / fseeko.c
blobd5f0fb6a0703c7a416a24eea3c1dcf1fb45e868f
1 /*
2 Copyright © 1995-2013, The AROS Development Team. All rights reserved.
3 $Id$
5 Change the position in a stream.
6 */
8 #include <fcntl.h>
9 #include <errno.h>
10 #include <dos/dos.h>
11 #include <proto/dos.h>
12 #include "__stdio.h"
13 #include "__fdesc.h"
15 /*****************************************************************************
17 NAME */
18 #include <stdio.h>
20 int fseeko (
22 /* SYNOPSIS */
23 FILE * stream,
24 off_t offset,
25 int whence)
27 /* FUNCTION
28 Change the current position in a stream.
30 INPUTS
31 stream - Modify this stream
32 offset, whence - How to modify the current position. whence
33 can be SEEK_SET, then offset is the absolute position
34 in the file (0 is the first byte), SEEK_CUR then the
35 position will change by offset (ie. -5 means to move
36 5 bytes to the beginning of the file) or SEEK_END.
37 SEEK_END means that the offset is relative to the
38 end of the file (-1 is the last byte and 0 is
39 the EOF).
41 RESULT
42 0 on success and -1 on error. If an error occurred, the global
43 variable errno is set.
45 NOTES
46 64-bit version
48 EXAMPLE
50 BUGS
51 Not fully compatible with iso fseeko, especially in 'ab' and 'a+b'
52 modes
54 SEE ALSO
55 fseek()
57 INTERNALS
58 just a hack, not 64-bit
60 ******************************************************************************/
62 off_t cnt = 0;
63 off_t finalseekposition = 0;
64 off_t eofposition = 0;
65 struct FileInfoBlock *fib = NULL;
66 BPTR fh = BNULL;
67 fdesc *fdesc = __getfdesc(stream->fd);
69 if (!fdesc)
71 errno = EBADF;
72 return -1;
75 fh = fdesc->fcb->handle;
77 /* This is buffered IO, flush the buffer before any Seek */
78 Flush (fh);
80 /* Handling for fseeko specific behaviour (not all cases handled) */
81 /* Get current position */
82 cnt = Seek (fh, 0, OFFSET_CURRENT);
83 if (cnt == -1)
85 errno = __stdc_ioerr2errno (IoErr ());
86 return -1;
89 /* Get file size */
90 fib = AllocDosObject(DOS_FIB, NULL);
91 if (!fib)
93 errno = __stdc_ioerr2errno(IoErr());
94 return -1;
97 if (ExamineFH(fh, fib))
98 eofposition = fib->fib_Size;
99 else
101 /* Does not happen on sfs/affs */
102 FreeDosObject(DOS_FIB, fib);
103 fib = NULL;
104 errno = EBADF;
105 return -1;
108 FreeDosObject(DOS_FIB, fib);
109 fib = NULL;
111 switch(whence)
113 case SEEK_SET: finalseekposition = offset; break;
114 case SEEK_CUR: finalseekposition = cnt + offset; break;
115 case SEEK_END: finalseekposition = eofposition + offset; break;
116 default:
117 errno = EINVAL;
118 return -1;
121 /* Check conditions */
122 /* Seek before beginning of file */
123 if (finalseekposition < 0)
125 errno = EINVAL;
126 return -1;
129 /* Seek beyond end of file and in write mode */
130 if (finalseekposition > eofposition)
132 if (fdesc->fcb->flags & O_WRITE)
134 /* Write '0' to fill up to requested size
135 * compatible fseeko does not write but allows write */
136 int bytestowrite = finalseekposition - eofposition;
137 int chunkcount = (bytestowrite)/128;
138 int remainder = bytestowrite - (chunkcount * 128);
139 char zeroarray[128] = {0};
141 Seek (fh, 0, OFFSET_END);
142 if (chunkcount > 0)
143 FWrite (fh, zeroarray, 128, chunkcount);
144 if (remainder > 0)
145 FWrite (fh, zeroarray, remainder, 1);
146 Flush (fh);
150 cnt = Seek (fh, finalseekposition, OFFSET_BEGINNING);
152 if (cnt == -1)
153 errno = __stdc_ioerr2errno (IoErr ());
154 else
156 /* It's specified that upon success fseeko should clear EOF flag
157 so here we go.
159 stream->flags &= ~(__POSIXC_STDIO_EOF);
160 cnt = 0;
163 return cnt;
164 } /* fseeko */