Merging NList MCC 0.119 into the main branch.
[AROS.git] / rom / dos / fread.c
blobe0458a18f1cde580eec2e0dc9f0e4263db406a95
1 /*
2 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc:
6 Lang: english
7 */
8 #include <aros/debug.h>
10 #include "dos_intern.h"
12 #define FETCHERR (-2)
14 /*****************************************************************************
16 NAME */
17 #include <proto/dos.h>
19 AROS_LH4(LONG, FRead,
21 /* SYNOPSIS */
22 AROS_LHA(BPTR , fh, D1),
23 AROS_LHA(APTR , block, D2),
24 AROS_LHA(ULONG, blocklen, D3),
25 AROS_LHA(ULONG, number, D4),
27 /* LOCATION */
28 struct DosLibrary *, DOSBase, 54, Dos)
30 /* FUNCTION
31 Read a number of blocks from a file.
32 The read is buffered.
34 INPUTS
35 fh - Read from this file
36 block - The data is put here
37 blocklen - This is the size of a single block
38 number - The number of blocks
40 RESULT
41 The number of blocks read from the file or 0 on EOF.
42 This function may return fewer than the requested number of blocks.
43 IoErr() gives additional information in case of an error.
45 NOTES
47 EXAMPLE
49 BUGS
51 SEE ALSO
52 Open(), FWrite(), FPutc(), Close()
54 INTERNALS
56 *****************************************************************************/
58 AROS_LIBFUNC_INIT
60 UBYTE *ptr;
61 LONG res = 0;
62 ULONG fetchsize = number * blocklen;
63 ULONG readsize;
65 ptr = block;
67 SetIoErr(0);
69 if((fetchsize == 0) || (fh == BNULL))
70 return 0;
72 while(fetchsize > 0)
74 res = vbuf_fetch(fh, ptr, fetchsize, DOSBase);
75 if (res < 0)
76 break;
77 ptr += res;
78 fetchsize -= res;
81 if(res == FETCHERR)
83 return EOF;
86 readsize = (ULONG)(ptr - (UBYTE *)block);
89 return (LONG)(readsize / blocklen);
91 AROS_LIBFUNC_EXIT
92 } /* FRead */
94 static LONG handle_write_mode(BPTR file, struct DosLibrary * DOSBase)
96 struct FileHandle *fh = (struct FileHandle *)BADDR(file);
98 /* If the file is in write mode... */
99 if(fh->fh_Flags & FHF_WRITE)
101 /* write the buffer (in many pieces if the first one isn't enough). */
102 LONG pos = 0;
104 while(pos != fh->fh_Pos)
106 LONG size = Write(file, BADDR(fh->fh_Buf) + pos, fh->fh_Pos - pos);
108 /* An error happened? Return it. */
109 if(size < 0)
111 return FETCHERR;
114 pos += size;
117 /* Reinit filehandle. */
118 fh->fh_Flags &= ~FHF_WRITE;
119 fh->fh_Pos = fh->fh_End = 0;
122 return 0;
125 /* Fetches up to remaining buffer content from file buffer
126 * Return values:
127 * (-2) on error
128 * (EOF) on EOF
129 * (>0) on sucesfull fetch
131 LONG vbuf_fetch(BPTR file, UBYTE * buffer, ULONG fetchsize, struct DosLibrary *DOSBase)
133 /* Get pointer to filehandle */
134 struct FileHandle *fh = (struct FileHandle *)BADDR(file);
136 LONG size;
137 LONG bufsize;
139 if (fh == NULL)
141 return FETCHERR;
144 if (handle_write_mode(file, DOSBase) == FETCHERR)
146 return FETCHERR;
149 /* No normal characters left. */
150 if(fh->fh_Pos >= fh->fh_End)
152 /* Check for a pushed back EOF. */
153 if(fh->fh_Pos > fh->fh_End)
155 D(bug("FGetC: Weird pos: fh_Pos (%d) > fh_End (%d)\n", fh->fh_Pos, fh->fh_End));
156 /* Return EOF. */
157 return EOF;
160 /* Is there a buffer? */
161 if(fh->fh_Buf == BNULL)
163 if (NULL == vbuf_alloc(fh, NULL, IOBUFSIZE))
165 D(bug("FGetC: Can't allocate buffer\n"));
166 return FETCHERR;
170 /* Fill the buffer. */
171 if (fh->fh_Buf != fh->fh_OrigBuf) {
172 D(bug("FGetC: Can't trust fh_BufSize. Using 208 as the buffer size.\n"));
173 bufsize = 208;
174 } else {
175 bufsize = fh->fh_BufSize;
177 size = Read(file, BADDR(fh->fh_Buf), bufsize);
179 /* Prepare filehandle for data. */
180 if(size <= 0)
181 size = 0;
183 fh->fh_Pos = 0;
184 fh->fh_End = size;
186 /* No data read? Return EOF. */
187 if(size == 0)
189 D(bug("FGetC: Tried to Read() to a %d byte buffer, got 0)\n", bufsize));
190 return EOF;
194 /* If fh_End == 0, simulate an EOF */
195 if (fh->fh_End == 0) {
196 D(bug("FGetC: Got an EOF via fh_End == 0\n"));
197 return EOF;
200 /* All OK. Get requested data. */
201 size = fh->fh_End - fh->fh_Pos;
202 if (size > fetchsize) size = fetchsize;
203 if (size == 1) /* Don't do function call for 1 byte reads */
204 *buffer = ((UBYTE *)BADDR(fh->fh_Buf))[fh->fh_Pos];
205 else
206 CopyMem(((UBYTE *)BADDR(fh->fh_Buf)) + fh->fh_Pos, buffer, size);
208 fh->fh_Pos += size;
210 return size;