Skip to content

Commit

Permalink
stdio/file: fix numerous issues in the fread/fwrite functions
Browse files Browse the repository at this point in the history
Fixed fread function issues:
 - non-blocking fread was not supported
 - unbuffered read was not setting F_ERROR on read errors
 - unbuffered read was not setting F_EOF at the end-of-file
 - unbuffered read was dropping bytes on EAGAIN
 - buffered read was not setting F_ERROR when refilling the buffer
 - buffered read was dropping bytes on EAGAIN
 - buffered read was incorrectly setting F_EOF on EAGAIN

Fixed fwrite function issues:
 - interleaved fread/fwrite functions weren't working for Unix sockets (caused by an unnecessary seek trigerring an error)
 - fwrite was returning 0 when read buffer discarding failed due to seek errors

JIRA: RTOS-892
  • Loading branch information
ziemleszcz committed Aug 21, 2024
1 parent 4ee5a4a commit bf2a36e
Showing 1 changed file with 60 additions and 28 deletions.
88 changes: 60 additions & 28 deletions stdio/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -290,16 +290,25 @@ FILE *freopen(const char *pathname, const char *mode, FILE *stream)
}


static int full_read(int fd, void *ptr, size_t size)
static int full_read(int fd, void *ptr, size_t size, int *eof)
{
int err;
int total = 0;

*eof = 0;

while (size) {
if ((err = __safe_read(fd, ptr, size)) < 0) {
return -1;
err = __safe_read_nonblocking(fd, ptr, size);
if (err < 0) {
if (errno == EAGAIN) {
return total;
}
else {
return -1;
}
}
else if (!err) {
*eof = 1;
return total;
}
ptr += err;
Expand Down Expand Up @@ -328,21 +337,34 @@ static int full_write(int fd, const void *ptr, size_t size)

size_t fread_unlocked(void *ptr, size_t size, size_t nmemb, FILE *stream)
{
int err;
int err, eof;
size_t readsz = nmemb * size;
size_t bytes;

if (!readsz) {
if (readsz == 0) {
return 0;
}

if (stream->buffer == NULL) {
/* unbuffered read */
if ((err = full_read(stream->fd, ptr, readsz)) < 0) {
err = full_read(stream->fd, ptr, readsz, &eof);
if (err >= 0) {
if (err < readsz) {
if (eof == 1) {
stream->flags |= F_EOF;
}
else {
/* received EAGAIN */
stream->flags |= F_ERROR;
}
}

return err / size;
}
else {
stream->flags |= F_ERROR;
return 0;
}

return err / size;
}

/* flush write buffer if writing */
Expand All @@ -363,43 +385,49 @@ size_t fread_unlocked(void *ptr, size_t size, size_t nmemb, FILE *stream)

/* refill read buffer */
if (stream->bufpos == stream->bufeof) {
if ((err = __safe_read(stream->fd, stream->buffer, stream->bufsz)) == -1) {
err = __safe_read_nonblocking(stream->fd, stream->buffer, stream->bufsz);
if (err < 0) {
stream->flags |= F_ERROR;
return 0;
}

stream->bufpos = 0;
stream->bufeof = err;

if (!err) {
else if (err == 0) {
stream->flags |= F_EOF;
return 0;
}
else {
stream->bufpos = 0;
stream->bufeof = err;
}
}

if ((bytes = stream->bufeof - stream->bufpos)) {
bytes = min(bytes, readsz);
memcpy(ptr, stream->buffer + stream->bufpos, bytes);
bytes = min(stream->bufeof - stream->bufpos, readsz);
memcpy(ptr, stream->buffer + stream->bufpos, bytes);

ptr += bytes;
stream->bufpos += bytes;
readsz -= bytes;
ptr += bytes;
stream->bufpos += bytes;
readsz -= bytes;

if (!readsz) {
return nmemb;
}
if (readsz == 0) {
return nmemb;
}

/* read remainder directly into ptr */
if ((err = full_read(stream->fd, ptr, readsz)) != -1) {
/* read the remaining bytes directly into the user buffer */
err = full_read(stream->fd, ptr, readsz, &eof);
if (err >= 0) {
bytes += err;

if (err < readsz) {
stream->flags |= F_EOF;
if (eof == 1) {
stream->flags |= F_EOF;
}
else {
/* received EAGAIN */
stream->flags |= F_ERROR;
}
}
}
else {
stream->flags |= F_ERROR;
return 0;
}

return bytes / size;
Expand Down Expand Up @@ -437,7 +465,11 @@ size_t fwrite_unlocked(const void *ptr, size_t size, size_t nmemb, FILE *stream)

/* discard reading buffer */
if (!(stream->flags & F_WRITING)) {
fflush_unlocked(stream);
if (stream->bufpos != stream->bufeof) {
if (fflush_unlocked(stream) < 0) {
return 0;
}
}
stream->flags |= F_WRITING;
stream->bufpos = 0;
}
Expand Down

0 comments on commit bf2a36e

Please sign in to comment.