use aros_target_toolchain to determine if we need to use the wrappers
[AROS.git] / compiler / posixc / fseek.c
blobdf822336cd365cb46446108b36505d6d49fbf9f6
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 fseek (
22 /* SYNOPSIS */
23 FILE * stream,
24 long 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
47 EXAMPLE
49 BUGS
50 Not fully compatible with iso fseek, especially in 'ab' and 'a+b'
51 modes
53 Since it's not possible to use Seek() for directories, this
54 implementation fails with EISDIR for directory file descriptors.
56 SEE ALSO
57 fopen(), fwrite()
59 INTERNALS
61 ******************************************************************************/
63 int cnt = 0;
64 int finalseekposition = 0;
65 int eofposition = 0;
66 struct FileInfoBlock *fib = NULL;
67 BPTR fh = BNULL;
68 fdesc *fdesc = __getfdesc(stream->fd);
70 if (!fdesc)
72 errno = EBADF;
73 return -1;
76 if (fdesc->fcb->privflags & _FCB_ISDIR)
78 errno = EISDIR;
79 return -1;
82 fh = fdesc->fcb->handle;
84 /* This is buffered IO, flush the buffer before any Seek */
85 Flush (fh);
87 /* Handling for fseek specific behaviour (not all cases handled) */
88 /* Get current position */
89 cnt = Seek (fh, 0, OFFSET_CURRENT);
90 if (cnt == -1)
92 errno = __stdc_ioerr2errno (IoErr ());
93 return -1;
96 /* Get file size */
97 fib = AllocDosObject(DOS_FIB, NULL);
98 if (!fib)
100 errno = __stdc_ioerr2errno(IoErr());
101 return -1;
104 if (ExamineFH(fh, fib))
105 eofposition = fib->fib_Size;
106 else
108 /* Does not happen on sfs/affs */
109 FreeDosObject(DOS_FIB, fib);
110 fib = NULL;
111 errno = EBADF;
112 return -1;
115 FreeDosObject(DOS_FIB, fib);
116 fib = NULL;
118 switch(whence)
120 case SEEK_SET: finalseekposition = offset; break;
121 case SEEK_CUR: finalseekposition = cnt + offset; break;
122 case SEEK_END: finalseekposition = eofposition + offset; break;
123 default:
124 errno = EINVAL;
125 return -1;
128 /* Check conditions */
129 /* Seek before beginning of file */
130 if (finalseekposition < 0)
132 errno = EINVAL;
133 return -1;
136 /* Seek beyond end of file and in write mode */
137 if (finalseekposition > eofposition)
139 if (fdesc->fcb->flags & O_WRITE)
141 /* Write '0' to fill up to requested size - compatible fseek does not write but allows write */
142 int i = 0;
143 int bytestowrite = finalseekposition - eofposition;
144 int chunkcount = (bytestowrite)/128;
145 char zeroarray[128] = {0};
147 Seek (fh, 0, OFFSET_END);
148 for (i = 0; i < chunkcount; i++)
149 FWrite(fh, (STRPTR)zeroarray, 128, 1);
150 FWrite(fh, (STRPTR)zeroarray, bytestowrite - (chunkcount * 128), 1);
151 Flush (fh);
155 cnt = Seek (fh, finalseekposition, OFFSET_BEGINNING);
157 if (cnt == -1)
158 errno = __stdc_ioerr2errno (IoErr ());
159 else
161 /* It's specified that upon success fseek should clear EOF flag
162 so here we go.
164 stream->flags &= ~(__POSIXC_STDIO_EOF);
165 cnt = 0;
168 return cnt;
169 } /* fseek */