Skip to content

Commit

Permalink
unistd/file: provide safe write/read/open/close functions
Browse files Browse the repository at this point in the history
JIRA: RTOS-874
  • Loading branch information
lukileczo committed Jul 26, 2024
1 parent 29afcd9 commit ea158db
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 77 deletions.
58 changes: 12 additions & 46 deletions stdio/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
#include <unistd.h>
#include <limits.h>

#include "../unistd/file-internal.h"


#define F_EOF (1 << 0)
#define F_WRITING (1 << 1)
Expand Down Expand Up @@ -158,42 +160,6 @@ static void file_free(FILE *file)
}


static ssize_t safe_read(int fd, void *buf, size_t size)
{
int err;
while ((err = read(fd, buf, size)) < 0 && errno == EINTR) {
}
return err;
}


static ssize_t safe_write(int fd, const void *buf, size_t size)
{
int err;
while ((err = write(fd, buf, size)) < 0 && errno == EINTR) {
}
return err;
}


static int safe_open(const char *path, int oflag, mode_t mode)
{
int err;
while ((err = open(path, oflag, mode)) < 0 && errno == EINTR) {
}
return err;
}


static int safe_close(int fd)
{
int err;
while ((err = close(fd)) < 0 && errno == EINTR) {
}
return err;
}


int fclose(FILE *file)
{
int err;
Expand All @@ -203,7 +169,7 @@ int fclose(FILE *file)
}

fflush(file);
while ((err = safe_close(file->fd)) < 0 && errno == EINTR) {
while ((err = __safe_close(file->fd)) < 0 && errno == EINTR) {
}
file_free(file);

Expand All @@ -222,17 +188,17 @@ FILE *fopen(const char *filename, const char *mode)
return NULL;
}

if ((fd = safe_open(filename, m, DEFFILEMODE)) < 0) {
if ((fd = __safe_open(filename, m, DEFFILEMODE)) < 0) {
return NULL;
}

if ((f = calloc(1, sizeof(FILE))) == NULL) {
safe_close(fd);
__safe_close(fd);
return NULL;
}

if ((f->buffer = buffAlloc(BUFSIZ)) == NULL) {
safe_close(fd);
__safe_close(fd);
free(f);
return NULL;
}
Expand Down Expand Up @@ -307,9 +273,9 @@ FILE *freopen(const char *pathname, const char *mode, FILE *stream)
fflush(stream);

if (pathname != NULL) {
safe_close(stream->fd);
__safe_close(stream->fd);

if ((stream->fd = safe_open(pathname, m, DEFFILEMODE)) < 0) {
if ((stream->fd = __safe_open(pathname, m, DEFFILEMODE)) < 0) {
file_free(stream);
return NULL;
}
Expand All @@ -330,7 +296,7 @@ static int full_read(int fd, void *ptr, size_t size)
int total = 0;

while (size) {
if ((err = safe_read(fd, ptr, size)) < 0) {
if ((err = __safe_read(fd, ptr, size)) < 0) {
return -1;
}
else if (!err) {
Expand All @@ -349,7 +315,7 @@ static int full_write(int fd, const void *ptr, size_t size)
{
int err;
while (size) {
if ((err = safe_write(fd, ptr, size)) < 0) {
if ((err = __safe_write(fd, ptr, size)) < 0) {
return -1;
}
ptr += err;
Expand Down Expand Up @@ -397,7 +363,7 @@ 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) {
if ((err = __safe_read(stream->fd, stream->buffer, stream->bufsz)) == -1) {
return 0;
}

Expand Down Expand Up @@ -462,7 +428,7 @@ size_t fwrite_unlocked(const void *ptr, size_t size, size_t nmemb, FILE *stream)

if (stream->buffer == NULL) {
/* unbuffered write */
if ((err = safe_write(stream->fd, ptr, writesz)) < 0) {
if ((err = __safe_write(stream->fd, ptr, writesz)) < 0) {
return 0;
}

Expand Down
35 changes: 4 additions & 31 deletions stdio/fprintf.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
#include "format.h"
#include "sys/debug.h"

#include "../unistd/file-internal.h"


/* clang-format off */
struct feed_ctx_s {
Expand All @@ -37,35 +39,6 @@ struct feed_ctx_s {
/* clang-format on */


static size_t safe_write(int fd, const char *buff, size_t size)
{
size_t todo = size;
ssize_t wlen;

while (todo != 0) {
wlen = write(fd, buff, todo);
if (wlen > 0) {
todo -= wlen;
buff += wlen;
continue;
}
else if (wlen < 0) {
if ((errno == EINTR) || (errno == EAGAIN)) {
continue;
}
break;
}
else {
/* Undefined behaviour (wlen==0) */
errno = EIO;
break;
}
}

return size - todo;
}


static void format_feed(void *context, char c)
{
size_t res;
Expand All @@ -81,7 +54,7 @@ static void format_feed(void *context, char c)
if (ctx->n == sizeof(ctx->buff) - 1) {
res = (ctx->hType == feed_hStream) ?
fwrite(ctx->buff, 1, ctx->n, ctx->h.stream) :
safe_write(ctx->h.fd, ctx->buff, ctx->n);
__safe_write(ctx->h.fd, ctx->buff, ctx->n);

ctx->total += res;
if (ctx->n != res) {
Expand Down Expand Up @@ -152,7 +125,7 @@ int vdprintf(int fd, const char *format, va_list arg)
ret = format_parse(&ctx, format_feed, format, arg);

if ((ret == 0) && (ctx.n != 0)) {
res = safe_write(ctx.h.fd, ctx.buff, ctx.n);
res = __safe_write(ctx.h.fd, ctx.buff, ctx.n);
ctx.total += res;

if (ctx.n != res) {
Expand Down
35 changes: 35 additions & 0 deletions unistd/file-internal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Phoenix-RTOS
*
* libphoenix
*
* Internal file operations
*
* Copyright 2024 Phoenix Systems
* Author: Lukasz Leczkowski
*
* This file is part of Phoenix-RTOS.
*
* %LICENSE%
*/

#ifndef _LIBPHOENIX_INTERNAL_FILE_H_
#define _LIBPHOENIX_INTERNAL_FILE_H_


#include <sys/types.h>


size_t __safe_write(int fd, const void *buff, size_t size);


ssize_t __safe_read(int fd, void *buf, size_t size);


int __safe_open(const char *path, int oflag, mode_t mode);


int __safe_close(int fd);


#endif
80 changes: 80 additions & 0 deletions unistd/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,86 @@ WRAP_ERRNO_DEF(int, dup2, (int fildes, int fildes2), (fildes, fildes2))
WRAP_ERRNO_DEF(int, fsync, (int fildes), (fildes))


size_t __safe_write(int fd, const void *buff, size_t size)
{
size_t todo = size;
ssize_t wlen;
const char *ptr = buff;

while (todo != 0) {
wlen = write(fd, ptr, todo);
if (wlen > 0) {
todo -= wlen;
ptr += wlen;
continue;
}
else if (wlen < 0) {
if ((errno == EINTR) || (errno == EAGAIN)) {
continue;
}
break;
}
else {
/* Undefined behaviour (wlen==0) */
errno = EIO;
break;
}
}

return size - todo;
}


ssize_t __safe_read(int fd, void *buf, size_t size)
{
ssize_t rlen;
size_t todo = size;
char *ptr = buf;

while (todo > 0) {
rlen = read(fd, ptr, todo);
if (rlen > 0) {
todo -= rlen;
ptr += rlen;
}
else if (rlen == 0) {
/* EOF */
break;
}
else if ((errno == EINTR) || (errno == EAGAIN)) {
continue;
}
else {
break;
}
}

return size - todo;
}


int __safe_open(const char *path, int oflag, mode_t mode)
{
int err;
do {
err = open(path, oflag, mode);
} while ((err < 0) && (errno == EINTR));

return err;
}


int __safe_close(int fd)
{
int err;
do {
err = close(fd);
} while ((err < 0) && (errno == EINTR));

return err;
}


off_t lseek(int fildes, off_t offset, int whence)
{
int retval = sys_lseek(fildes, &offset, whence);
Expand Down

0 comments on commit ea158db

Please sign in to comment.