From ea158dbf0092d0c9e79baf53e43ec012b0a1d96e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Leczkowski?= Date: Fri, 26 Jul 2024 10:14:31 +0200 Subject: [PATCH] unistd/file: provide safe write/read/open/close functions JIRA: RTOS-874 --- stdio/file.c | 58 +++++++----------------------- stdio/fprintf.c | 35 +++--------------- unistd/file-internal.h | 35 ++++++++++++++++++ unistd/file.c | 80 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 131 insertions(+), 77 deletions(-) create mode 100644 unistd/file-internal.h diff --git a/stdio/file.c b/stdio/file.c index f97f41ac..390b10af 100644 --- a/stdio/file.c +++ b/stdio/file.c @@ -32,6 +32,8 @@ #include #include +#include "../unistd/file-internal.h" + #define F_EOF (1 << 0) #define F_WRITING (1 << 1) @@ -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; @@ -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); @@ -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; } @@ -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; } @@ -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) { @@ -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; @@ -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; } @@ -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; } diff --git a/stdio/fprintf.c b/stdio/fprintf.c index b494fbc6..60aa16a5 100644 --- a/stdio/fprintf.c +++ b/stdio/fprintf.c @@ -20,6 +20,8 @@ #include "format.h" #include "sys/debug.h" +#include "../unistd/file-internal.h" + /* clang-format off */ struct feed_ctx_s { @@ -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; @@ -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) { @@ -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) { diff --git a/unistd/file-internal.h b/unistd/file-internal.h new file mode 100644 index 00000000..6698c1de --- /dev/null +++ b/unistd/file-internal.h @@ -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 + + +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 diff --git a/unistd/file.c b/unistd/file.c index cbe7db68..44a71ccd 100644 --- a/unistd/file.c +++ b/unistd/file.c @@ -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);