compiler/clib: Rename IoErr2errno() to __arosc_ioerr2errno(); function is now defined...
[AROS.git] / compiler / clib / fseek.c
blob3b1da320e9863d638d74332ea4d2cbb7fafc0b12
1 /*
2 Copyright © 1995-2012, 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 SEE ALSO
54 fopen(), fwrite()
56 INTERNALS
58 ******************************************************************************/
60 int cnt = 0;
61 int finalseekposition = 0;
62 int eofposition = 0;
63 struct FileInfoBlock *fib = NULL;
64 BPTR fh = BNULL;
65 fdesc *fdesc = __getfdesc(stream->fd);
67 if (!fdesc)
69 errno = EBADF;
70 return -1;
73 fh = (BPTR)(fdesc->fcb->fh);
75 /* This is buffered IO, flush the buffer before any Seek */
76 Flush (fh);
78 /* Handling for fseek specific behaviour (not all cases handled) */
79 /* Get current position */
80 cnt = Seek (fh, 0, OFFSET_CURRENT);
81 if (cnt == -1)
83 errno = __arosc_ioerr2errno (IoErr ());
84 return -1;
87 /* Get file size */
88 fib = AllocDosObject(DOS_FIB, NULL);
89 if (!fib)
91 errno = __arosc_ioerr2errno(IoErr());
92 return -1;
95 if (ExamineFH(fh, fib))
96 eofposition = fib->fib_Size;
97 else
99 /* Does not happen on sfs/affs */
100 FreeDosObject(DOS_FIB, fib);
101 fib = NULL;
102 errno = EBADF;
103 return -1;
106 FreeDosObject(DOS_FIB, fib);
107 fib = NULL;
109 switch(whence)
111 case SEEK_SET: finalseekposition = offset; break;
112 case SEEK_CUR: finalseekposition = cnt + offset; break;
113 case SEEK_END: finalseekposition = eofposition + offset; break;
114 default:
115 errno = EINVAL;
116 return -1;
119 /* Check conditions */
120 /* Seek before beginning of file */
121 if (finalseekposition < 0)
123 errno = EINVAL;
124 return -1;
127 /* Seek beyond end of file and in write mode */
128 if (finalseekposition > eofposition)
130 if (fdesc->fcb->flags & O_WRITE)
132 /* Write '0' to fill up to requested size - compatible fseek does not write but allows write */
133 int i = 0;
134 int bytestowrite = finalseekposition - eofposition;
135 int chunkcount = (bytestowrite)/128;
136 char zeroarray[128] = {0};
138 Seek (fh, 0, OFFSET_END);
139 for (i = 0; i < chunkcount; i++)
140 FWrite(fh, (STRPTR)zeroarray, 128, 1);
141 FWrite(fh, (STRPTR)zeroarray, bytestowrite - (chunkcount * 128), 1);
142 Flush (fh);
146 cnt = Seek (fh, finalseekposition, OFFSET_BEGINNING);
148 if (cnt == -1)
149 errno = __arosc_ioerr2errno (IoErr ());
150 else
152 /* It's specified that upon success fseek should clear EOF flag
153 so here we go.
155 stream->flags &= ~(_STDIO_EOF);
156 cnt = 0;
159 return cnt;
160 } /* fseek */