diff options
Diffstat (limited to 'util/libreboot-utils/lib/file.c')
| -rw-r--r-- | util/libreboot-utils/lib/file.c | 242 |
1 files changed, 68 insertions, 174 deletions
diff --git a/util/libreboot-utils/lib/file.c b/util/libreboot-utils/lib/file.c index 9c4683ce..a788d4af 100644 --- a/util/libreboot-utils/lib/file.c +++ b/util/libreboot-utils/lib/file.c @@ -16,9 +16,17 @@ more correct usage example: long max = pathconf("/", _PC_PATH_MAX); */ +/* for openat2: */ +#ifdef __linux__ +#if !defined(USE_OPENAT) || \ + ((USE_OPENAT) < 1) /* if 1: use openat, not openat2 */ #ifndef _GNU_SOURCE #define _GNU_SOURCE 1 #endif +#include <linux/openat2.h> +#include <sys/syscall.h> +#endif +#endif #include <sys/types.h> #include <sys/stat.h> @@ -30,12 +38,6 @@ long max = pathconf("/", _PC_PATH_MAX); #include <string.h> #include <unistd.h> -/* for openat2: */ -#ifdef __linux__ -#include <linux/openat2.h> -#include <sys/syscall.h> -#endif - #include "../include/common.h" /* check that a file changed @@ -108,7 +110,7 @@ fsync_dir(const char *path) if_err_sys((rval = fsync_on_eintr(dirfd)) == -1)) goto err_fsync_dir; - close_on_eintr(&dirfd); + xclose(&dirfd); free_and_set_null(&dirbuf); reset_caller_errno(rval); @@ -116,12 +118,12 @@ fsync_dir(const char *path) err_fsync_dir: free_and_set_null(&dirbuf); - close_on_eintr(&dirfd); + xclose(&dirfd); return with_fallback_errno(EIO); } -/* rw_file_exact() - Read perfectly or die +/* rw_exact() - Read perfectly or die * * Read/write, and absolutely insist on an * absolute read; e.g. if 100 bytes are @@ -139,8 +141,8 @@ err_fsync_dir: */ ssize_t -rw_file_exact(int fd, unsigned char *mem, size_t nrw, - off_t off, int rw_type, size_t max_retries) +rw_exact(int fd, unsigned char *mem, size_t nrw, + off_t off, int rw_type) { int saved_errno = errno; ssize_t rval = 0; @@ -148,17 +150,17 @@ rw_file_exact(int fd, unsigned char *mem, size_t nrw, size_t nrw_cur; off_t off_cur; void *mem_cur; - size_t retries_on_zero = 0; errno = 0; if (io_args(fd, mem, nrw, off, rw_type) == -1) - goto err_rw_file_exact; + goto err_rw_exact; while (1) { /* Prevent theoretical overflow */ - if (if_err(rval >= 0 && (size_t)rval > (nrw - rc), EOVERFLOW)) - goto err_rw_file_exact; + if (if_err(rval >= 0 && (size_t)rval > (nrw - (size_t)rc), + EOVERFLOW)) + goto err_rw_exact; rc += rval; if ((size_t)rc >= nrw) @@ -168,42 +170,39 @@ rw_file_exact(int fd, unsigned char *mem, size_t nrw, nrw_cur = (size_t)(nrw - (size_t)rc); if (if_err(off < 0, EOVERFLOW)) - goto err_rw_file_exact; + goto err_rw_exact; off_cur = off + (off_t)rc; - if ((rval = rw(fd, mem_cur, nrw_cur, off_cur, rw_type)) < 0) - goto err_rw_file_exact; - - if (rval == 0) { - if (retries_on_zero++ < max_retries) - continue; - - goto err_rw_file_exact; - } - - retries_on_zero = 0; + if ((rval = rw(fd, mem_cur, nrw_cur, off_cur, rw_type)) <= 0) + goto err_rw_exact; } if (if_err((size_t)rc != nrw, EIO) || (rval = rw_over_nrw(rc, nrw)) < 0) - goto err_rw_file_exact; + goto err_rw_exact; reset_caller_errno(rval); return rval; -err_rw_file_exact: +err_rw_exact: return with_fallback_errno(EIO); } -/* rw() - read-write but with more +/** + * rw() - read-write but with more * safety checks than barebones libc * * A fallback is provided for regular read/write. * rw_type can be IO_READ (read), IO_WRITE (write), * IO_PREAD (pread) or IO_PWRITE + * + * WARNING: this function allows zero-byte returns. + * this is intentional, to mimic libc behaviour. + * use rw_exact if you need to avoid this. + * (ditto partial writes/reads) + * */ - ssize_t rw(int fd, void *mem, size_t nrw, off_t off, int rw_type) @@ -213,27 +212,34 @@ rw(int fd, void *mem, size_t nrw, int saved_errno = errno; errno = 0; - if (io_args(fd, mem, nrw, off, rw_type) == -1) - return with_fallback_errno(EINVAL); - - switch (rw_type) { - case IO_WRITE: - r = write_on_eintr(fd, mem, nrw); - break; - case IO_READ: - r = read_on_eintr(fd, mem, nrw); - break; - case IO_PWRITE: - r = pwrite_on_eintr(fd, mem, nrw, off); - break; - case IO_PREAD: - r = pread_on_eintr(fd, mem, nrw, off); - break; - default: - errno = EINVAL; - break; - } + if (io_args(fd, mem, nrw, off, rw_type) == -1 || + if_err(mem == NULL, EFAULT) || + if_err(fd < 0, EBADF) || + if_err(off < 0, EFAULT) || + if_err(nrw == 0, EINVAL)) + return with_fallback_errno(EIO); + do { + switch (rw_type) { + case IO_READ: + r = read(fd, mem, nrw); + break; + case IO_WRITE: + r = write(fd, mem, nrw); + break; + case IO_PREAD: + r = pread(fd, mem, nrw, off); + break; + case IO_PWRITE: + r = pwrite(fd, mem, nrw, off); + break; + default: + errno = EINVAL; + break; + } + + } while (rw_retry(saved_errno, r)); + if ((rval = rw_over_nrw(r, nrw)) < 0) return with_fallback_errno(EIO); @@ -413,7 +419,7 @@ fs_resolve_at(int dirfd, const char *path, int flags) /* close previous fd if not the original input */ if (curfd != dirfd) - close_on_eintr(&curfd); + xclose(&curfd); curfd = nextfd; nextfd = -1; @@ -426,11 +432,11 @@ err: saved_errno = errno; if (nextfd >= 0) - close_on_eintr(&nextfd); + xclose(&nextfd); /* close curfd only if it's not the original */ if (curfd != dirfd && curfd >= 0) - close_on_eintr(&curfd); + xclose(&curfd); errno = saved_errno; return with_fallback_errno(EIO); @@ -602,20 +608,21 @@ open_file_on_eintr(const char *path, exitf("%s: not a regular file", path); } - if (lseek_on_eintr(*fd, 0, SEEK_CUR) == (off_t)-1) + if (lseek(*fd, 0, SEEK_CUR) == (off_t)-1) exitf("%s: file not seekable", path); errno = saved_errno; /* see previous comment */ } -#ifdef __linux__ /* we use openat2 on linux */ +#if defined(__linux__) && \ + (!defined(USE_OPENAT) || ((USE_OPENAT) < 1)) /* we use openat2 on linux */ int openat_on_eintr(int dirfd, const char *path, int flags, mode_t mode) { struct open_how how = { - .flags = flags, + .flags = (unsigned long long)flags, .mode = mode, .resolve = RESOLVE_BENEATH | @@ -663,20 +670,6 @@ openat_on_eintr(int dirfd, const char *path, } #endif -off_t -lseek_on_eintr(int fd, off_t off, int whence) -{ - int saved_errno = errno; - off_t rval = 0; - errno = 0; - - while (off_retry(saved_errno, - rval = lseek(fd, off, whence))); - - reset_caller_errno(rval); - return rval; -} - int mkdirat_on_eintr(int dirfd, const char *path, mode_t mode) @@ -696,90 +689,6 @@ mkdirat_on_eintr(int dirfd, return rval; } -ssize_t -read_on_eintr(int fd, - void *buf, size_t count) -{ - int saved_errno = errno; - ssize_t rval = 0; - errno = 0; - - if (if_err(buf == NULL, EFAULT) || - if_err(fd < 0, EBADF) || - if_err(count == 0, EINVAL)) - return with_fallback_errno(EIO); - - while (rw_retry(saved_errno, - rval = read(fd, buf, count))); - - reset_caller_errno(rval); - return rval; -} - -ssize_t -pread_on_eintr(int fd, - void *buf, size_t count, - off_t off) -{ - int saved_errno = errno; - ssize_t rval = 0; - errno = 0; - - if (if_err(buf == NULL, EFAULT) || - if_err(fd < 0, EBADF) || - if_err(off < 0, EFAULT) || - if_err(count == 0, EINVAL)) - return with_fallback_errno(EIO); - - while (rw_retry(saved_errno, - rval = pread(fd, buf, count, off))); - - reset_caller_errno(rval); - return rval; -} - -ssize_t -write_on_eintr(int fd, - void *buf, size_t count) -{ - int saved_errno = errno; - ssize_t rval = 0; - errno = 0; - - if (if_err(buf == NULL, EFAULT) || - if_err(fd < 0, EBADF) || - if_err(count == 0, EINVAL)) - return with_fallback_errno(EIO); - - while (rw_retry(saved_errno, - rval = write(fd, buf, count))); - - reset_caller_errno(rval); - return rval; -} - -ssize_t -pwrite_on_eintr(int fd, - void *buf, size_t count, - off_t off) -{ - int saved_errno = errno; - ssize_t rval = 0; - errno = 0; - - if (if_err(buf == NULL, EFAULT) || - if_err(fd < 0, EBADF) || - if_err(off < 0, EFAULT) || - if_err(count == 0, EINVAL)) - return with_fallback_errno(EIO); - - while (rw_retry(saved_errno, - rval = pwrite(fd, buf, count, off))); - - reset_caller_errno(rval); - return rval; -} - int fsync_on_eintr(int fd) { @@ -798,22 +707,19 @@ fsync_on_eintr(int fd) } void -close_on_eintr(int *fd) +xclose(int *fd) { int saved_errno = errno; int rval = 0; if (fd == NULL) - exitf("close_on_eintr: null pointer"); + exitf("xclose: null pointer"); if (*fd < 0) return; errno = 0; - while (fs_retry(saved_errno, - rval = close(*fd))); - - if (rval < 0) - exitf("close_on_eintr: could not close"); + if ((rval = close(*fd)) < 0) + exitf("xclose: could not close"); *fd = -1; @@ -856,18 +762,6 @@ close_on_eintr(int *fd) */ -/* retry switch for offset-based - * functions e.g. lseek - */ -/* retry switch for functions that - return long status e.g. linux syscall - */ -int -off_retry(int saved_errno, off_t rval) -{ - fs_err_retry(); -} - /* retry switch for functions that return long status e.g. linux syscall */ |
