diff options
Diffstat (limited to 'util/libreboot-utils/lib/file.c')
| -rw-r--r-- | util/libreboot-utils/lib/file.c | 110 |
1 files changed, 44 insertions, 66 deletions
diff --git a/util/libreboot-utils/lib/file.c b/util/libreboot-utils/lib/file.c index d44d8cf9..efc23ba9 100644 --- a/util/libreboot-utils/lib/file.c +++ b/util/libreboot-utils/lib/file.c @@ -16,10 +16,6 @@ more correct usage example: long max = pathconf("/", _PC_PATH_MAX); */ -#ifndef _XOPEN_SOURCE -#define _XOPEN_SOURCE 700 -#endif - /* for openat2: */ #ifdef __linux__ #if !defined(USE_OPENAT) || \ @@ -114,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); @@ -122,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 @@ -145,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; @@ -154,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) @@ -174,31 +170,22 @@ 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); } @@ -212,7 +199,7 @@ err_rw_file_exact: * * WARNING: this function allows zero-byte returns. * this is intentional, to mimic libc behaviour. - * use rw_file_exact if you need to avoid this. + * use rw_exact if you need to avoid this. * (ditto partial writes/reads) * */ @@ -432,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; @@ -445,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); @@ -621,7 +608,7 @@ 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 */ @@ -629,13 +616,13 @@ open_file_on_eintr(const char *path, #if defined(__linux__) && \ - ((USE_OPENAT) < 1) /* we use openat2 on 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 | @@ -683,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) @@ -734,22 +707,39 @@ 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; + /* nuance regarding EINTR on close(): + * EINTR can be set on error, but there's + * no guarantee whether the fd is then still + * open or closed. on some other commands, we + * loop EINTR, but for close, we instead skip + * aborting *if the errno is EINTR* - so don't + * loop it, but do regard EINTR with rval -1 + * as essenitally a successful close() + */ + + /* because we don't want to mess with someone + * elses file if that fd is then reassigned. + * if the operation truly did fail, we ignore + * it. just leave it flying in the wind */ + errno = 0; - while (fs_retry(saved_errno, - rval = close(*fd))); + if ((rval = close(*fd)) < 0) { + if (errno != EINTR) + exitf("xclose: could not close"); - if (rval < 0) - exitf("close_on_eintr: could not close"); + /* regard EINTR as a successful close */ + rval = 0; + } *fd = -1; @@ -792,18 +782,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 */ |
