ack/plat/msdos/libsys/read.c

82 lines
1.6 KiB
C
Raw Normal View History

/* $Source$
* $State$
* $Revision$
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include "libsys.h"
ssize_t read(int fd, void* buffer, size_t count)
{
char *p, *q;
ssize_t r, tot;
size_t left;
int eof = 0;
if (!count || _sys_getmode(fd) == O_BINARY)
return _sys_rawread(fd, buffer, count);
if (_sys_iseof(fd))
return 0;
/*
* If the file descriptor is an O_TEXT fd, read from it, and then
* remove CRs from the input. After removing CRs, if the buffer is
* not filled and the fd still has bytes left to read, then keep
* reading, and keep removing CRs.
*
* Also handle end-of-file indicators (^Z). If we see one, move the
* file pointer to just before the ^Z. Also set an internal flag
* for the fd so that we do not try to read any further (until e.g.
* a seek happens).
*
* If a low-level read returns an error (-1) before anything has
* actually been read, we can pass the error indication (-1) up to
* the caller.
*/
p = buffer;
tot = 0;
do
{
r = _sys_rawread(fd, p, count - (p - (char *)buffer));
if (r <= 0)
return tot ? tot : r;
q = memchr(p, 0x1a, (size_t)r);
if (q)
{
_sys_rawlseek(fd, (off_t)(q - p) - r, SEEK_CUR);
r = q - p;
eof = 1;
_sys_seteof(fd, 1);
}
q = memchr(p, '\r', (size_t)r);
if (!q)
return tot + r;
tot += q - p;
left = r - (q + 1 - p);
p = q;
++q;
while (left)
{
char c = *q++;
if (c != '\r')
{
*p++ = c;
++tot;
}
--left;
}
} while (tot < count && !eof && _sys_isreadyr(fd));
return tot;
}