diff options
| author | Leah Rowe <leah@libreboot.org> | 2026-03-31 12:22:42 +0100 |
|---|---|---|
| committer | Leah Rowe <leah@libreboot.org> | 2026-03-31 12:22:42 +0100 |
| commit | 6d9f162f5b649c68e95a534a06339a83ddfe621c (patch) | |
| tree | 2ec5b7a525ef11d674eba117d54d4f0f4fbccdc6 /util | |
| parent | a7695375549797a2894546d51ab8c8c3b093f8a8 (diff) | |
lbutils/file: only support real pread/pwrite
the portable version was written for fun, but
it's bloat, and makes the code hard to read.
every unix since about 2005 has these functions.
Signed-off-by: Leah Rowe <leah@libreboot.org>
Diffstat (limited to 'util')
| -rw-r--r-- | util/libreboot-utils/include/common.h | 25 | ||||
| -rw-r--r-- | util/libreboot-utils/lib/command.c | 4 | ||||
| -rw-r--r-- | util/libreboot-utils/lib/file.c | 184 | ||||
| -rw-r--r-- | util/libreboot-utils/lib/io.c | 12 |
4 files changed, 24 insertions, 201 deletions
diff --git a/util/libreboot-utils/include/common.h b/util/libreboot-utils/include/common.h index b2e6f0d9..bc0eb3b3 100644 --- a/util/libreboot-utils/include/common.h +++ b/util/libreboot-utils/include/common.h @@ -88,17 +88,6 @@ int fchmod(int fd, mode_t mode); #define MAX_ZERO_RW_RETRY 5 #endif -#ifndef REAL_POS_IO -#define REAL_POS_IO 1 -#endif - -#ifndef LOOP_EAGAIN -#define LOOP_EAGAIN 1 -#endif -#ifndef LOOP_EINTR -#define LOOP_EINTR 1 -#endif - #ifndef _FILE_OFFSET_BITS #define _FILE_OFFSET_BITS 64 #endif @@ -179,9 +168,6 @@ int fchmod(int fd, mode_t mode); #define ARGC_3 3 #define ARGC_4 4 -#define NO_LOOP_EAGAIN 0 -#define NO_LOOP_EINTR 0 - /* For checking if an fd is a normal file. * Portable for old Unix e.g. v7 (S_IFREG), * 4.2BSD (S_IFMT), POSIX (S_ISREG). @@ -477,18 +463,15 @@ ssize_t rw_gbe_file_exact(int fd, unsigned char *mem, size_t nrw, int fsync_dir(const char *path); ssize_t rw_file_exact(int fd, unsigned char *mem, size_t len, - off_t off, int rw_type, int loop_eagain, int loop_eintr, - size_t max_retries, int off_reset); + off_t off, int rw_type, size_t max_retries, int off_reset); ssize_t prw(int fd, void *mem, size_t nrw, - off_t off, int rw_type, int loop_eagain, int loop_eintr, - int off_reset); + off_t off, int rw_type); int io_args(int fd, void *mem, size_t nrw, off_t off, int rw_type); int check_file(int fd, struct stat *st); ssize_t rw_over_nrw(ssize_t r, size_t nrw); off_t lseek_on_eintr(int fd, off_t off, int whence, int loop_eagain, int loop_eintr); -int try_err(int loop_err, int errval); ssize_t read_on_eintr(int fd, void *buf, size_t count); ssize_t write_on_eintr(int fd, @@ -635,10 +618,6 @@ typedef char bool_skip_checksum_read[(SKIP_CHECKSUM_READ==0)?1:-1]; typedef char bool_checksum_read[(CHECKSUM_READ==1)?1:-1]; typedef char bool_skip_checksum_write[(SKIP_CHECKSUM_WRITE==0)?1:-1]; typedef char bool_checksum_write[(CHECKSUM_WRITE==1)?1:-1]; -typedef char bool_loop_eintr[(LOOP_EINTR==1||LOOP_EINTR==0)?1:-1]; -typedef char bool_loop_eagain[(LOOP_EAGAIN==1||LOOP_EAGAIN==0)?1:-1]; -typedef char bool_no_loop_eintr[(NO_LOOP_EINTR==0)?1:-1]; -typedef char bool_no_loop_eagain[(NO_LOOP_EAGAIN==0)?1:-1]; typedef char bool_off_err[(OFF_ERR==0)?1:-1]; typedef char bool_off_reset[(OFF_RESET==0||OFF_RESET==1)?1:-1]; diff --git a/util/libreboot-utils/lib/command.c b/util/libreboot-utils/lib/command.c index 3ee75628..16ca8346 100644 --- a/util/libreboot-utils/lib/command.c +++ b/util/libreboot-utils/lib/command.c @@ -496,8 +496,8 @@ cat_buf(unsigned char *b) err_exit(errno, "null pointer in cat command"); if (rw_file_exact(STDOUT_FILENO, b, - GBE_PART_SIZE, 0, IO_WRITE, LOOP_EAGAIN, LOOP_EINTR, - MAX_ZERO_RW_RETRY, OFF_ERR) < 0) + GBE_PART_SIZE, 0, IO_WRITE, MAX_ZERO_RW_RETRY, OFF_ERR) + < 0) err_exit(errno, "stdout: cat"); } void diff --git a/util/libreboot-utils/lib/file.c b/util/libreboot-utils/lib/file.c index 5ab00031..42c91843 100644 --- a/util/libreboot-utils/lib/file.c +++ b/util/libreboot-utils/lib/file.c @@ -160,9 +160,7 @@ err_fsync_dir: ssize_t rw_file_exact(int fd, unsigned char *mem, size_t nrw, - off_t off, int rw_type, int loop_eagain, - int loop_eintr, size_t max_retries, - int off_reset) + off_t off, int rw_type, size_t max_retries, int off_reset) { ssize_t rval; ssize_t rc; @@ -208,8 +206,7 @@ rw_file_exact(int fd, unsigned char *mem, size_t nrw, off_cur = off + (off_t)rc; rval = prw(fd, mem_cur, nrw_cur, off_cur, - rw_type, loop_eagain, loop_eintr, - off_reset); + rw_type); if (rval < 0) goto err_rw_file_exact; @@ -247,180 +244,42 @@ err_rw_file_exact: /* prw() - portable read-write with more * safety checks than barebones libc * - * If you need real pwrite/pread, just compile - * with flag: REAL_POS_IO=1 - * * A fallback is provided for regular read/write. * rw_type can be IO_READ (read), IO_WRITE (write), * IO_PREAD (pread) or IO_PWRITE - * - * loop_eagain does a retry loop on EAGAIN if set - * loop_eintr does a retry loop on EINTR if set - * - * race conditions on non-libc pread/pwrite: - * if a file offset changes, abort, to mitage. - * - * off_reset 1: reset the file offset *once* if - * a change was detected, assuming - * nothing else is touching it now - * off_reset 0: never reset if changed - * - * REAL_POS_IO is enabled by default in common.h - * and the fallback version was written for fun. - * You should just use the real one (REAL_POS_IO 1), - * since it is generally more reliable. */ ssize_t prw(int fd, void *mem, size_t nrw, - off_t off, int rw_type, - int loop_eagain, int loop_eintr, - int off_reset) + off_t off, int rw_type) { ssize_t rval; ssize_t r; - int positional_rw; struct stat st; -#if !defined(REAL_POS_IO) || \ - REAL_POS_IO < 1 - off_t verified; - off_t off_orig; - off_t off_last; -#endif int saved_errno = errno; errno = 0; - if (io_args(fd, mem, nrw, off, rw_type) - == -1) - goto err_prw; + if (io_args(fd, mem, nrw, off, rw_type) == -1) + return set_errno(saved_errno, EIO); r = -1; - /* do not use loop_eagain on - * normal files - */ - - if (!loop_eagain) { - /* check whether the file - * changed - */ - - if (check_file(fd, &st) == -1) - goto err_prw; - } - - if (rw_type >= IO_PREAD) - positional_rw = 1; /* pread/pwrite */ - else - positional_rw = 0; /* read/write */ - -try_rw_again: - - if (!positional_rw) { -#if defined(REAL_POS_IO) && \ - REAL_POS_IO > 0 -real_pread_pwrite: -#endif - if (rw_type == IO_WRITE) - r = write_on_eintr(fd, mem, nrw); - else if (rw_type == IO_READ) - r = read_on_eintr(fd, mem, nrw); -#if defined(REAL_POS_IO) && \ - REAL_POS_IO > 0 - else if (rw_type == IO_PWRITE) - r = pwrite_on_eintr(fd, mem, nrw, off); - else if (rw_type == IO_PREAD) - r = pread_on_eintr(fd, mem, nrw, off); -#endif - - if (r == -1 && (errno == try_err(loop_eintr, EINTR) - || errno == try_err(loop_eagain, EAGAIN))) - goto try_rw_again; - - rval = rw_over_nrw(r, nrw); - if (rval < 0) - goto err_prw; - - errno = saved_errno; - - return rval; - } - -#if defined(REAL_POS_IO) && \ - REAL_POS_IO > 0 - goto real_pread_pwrite; -#else - if ((off_orig = lseek_on_eintr(fd, (off_t)0, SEEK_CUR, - loop_eagain, loop_eintr)) == (off_t)-1) { - r = -1; - } else if (lseek_on_eintr(fd, off, SEEK_SET, - loop_eagain, loop_eintr) == (off_t)-1) { - r = -1; - } else { - verified = lseek_on_eintr(fd, (off_t)0, SEEK_CUR, - loop_eagain, loop_eintr); - - /* abort if the offset changed, - * indicating race condition. if - * off_reset enabled, reset *ONCE* - */ + if (rw_type == IO_WRITE) + r = write_on_eintr(fd, mem, nrw); + else if (rw_type == IO_READ) + r = read_on_eintr(fd, mem, nrw); + else if (rw_type == IO_PWRITE) + r = pwrite_on_eintr(fd, mem, nrw, off); + else if (rw_type == IO_PREAD) + r = pread_on_eintr(fd, mem, nrw, off); - if (off_reset && off != verified) - lseek_on_eintr(fd, off, SEEK_SET, - loop_eagain, loop_eintr); - - do { - /* check offset again, repeatedly. - * even if off_reset is set, this - * aborts if offsets change again - */ - - verified = lseek_on_eintr(fd, (off_t)0, SEEK_CUR, - loop_eagain, loop_eintr); - - if (off != verified) { - - errno = EBUSY; - goto err_prw; - } - - if (rw_type == IO_PREAD) - r = read_on_eintr(fd, mem, nrw); - else if (rw_type == IO_PWRITE) - r = write_on_eintr(fd, mem, nrw); - - if (rw_over_nrw(r, nrw) == -1) - break; - - } while (r == -1 && - (errno == try_err(loop_eintr, EINTR) || - errno == try_err(loop_eagain, EAGAIN))); - } - - saved_errno = errno; - - off_last = lseek_on_eintr(fd, off_orig, SEEK_SET, - loop_eagain, loop_eintr); + if ((rval = rw_over_nrw(r, nrw)) < 0) + return set_errno(saved_errno, EIO); - if (off_last != off_orig) { + if (rval >= 0 && !errno) errno = saved_errno; - goto err_prw; - } - - errno = saved_errno; - - rval = rw_over_nrw(r, nrw); - if (rval < 0) - goto err_prw; - - errno = saved_errno; return rval; - -#endif - -err_prw: - return set_errno(saved_errno, EIO); } int @@ -501,17 +360,6 @@ if_err_sys(int condition) return 0; return 1; } -/* errno can never be -1, so you can - * use this to conditionally set an integer - * for comparison. see example in lseek_on_eintr - */ -int -try_err(int loop_err, int errval) -{ - if (loop_err) - return errval; - return -1; -} int fs_rename_at(int olddirfd, const char *old, diff --git a/util/libreboot-utils/lib/io.c b/util/libreboot-utils/lib/io.c index 3b3a892f..f74ce261 100644 --- a/util/libreboot-utils/lib/io.c +++ b/util/libreboot-utils/lib/io.c @@ -104,8 +104,7 @@ read_file(void) /* read main file */ _r = rw_file_exact(f->gbe_fd, f->buf, f->gbe_file_size, - 0, IO_PREAD, NO_LOOP_EAGAIN, LOOP_EINTR, - MAX_ZERO_RW_RETRY, OFF_ERR); + 0, IO_PREAD, MAX_ZERO_RW_RETRY, OFF_ERR); if (_r < 0) err_exit(errno, "%s: read failed", f->fname); @@ -113,8 +112,7 @@ read_file(void) /* copy to tmpfile */ _r = rw_file_exact(f->tmp_fd, f->buf, f->gbe_file_size, - 0, IO_PWRITE, NO_LOOP_EAGAIN, LOOP_EINTR, - MAX_ZERO_RW_RETRY, OFF_ERR); + 0, IO_PWRITE, MAX_ZERO_RW_RETRY, OFF_ERR); if (_r < 0) err_exit(errno, "%s: %s: copy failed", @@ -137,8 +135,7 @@ read_file(void) err_exit(errno, "%s: fsync (tmpfile copy)", f->tname); _r = rw_file_exact(f->tmp_fd, f->bufcmp, f->gbe_file_size, - 0, IO_PREAD, NO_LOOP_EAGAIN, LOOP_EINTR, - MAX_ZERO_RW_RETRY, OFF_ERR); + 0, IO_PREAD, MAX_ZERO_RW_RETRY, OFF_ERR); if (_r < 0) err_exit(errno, "%s: read failed (cmp)", f->tname); @@ -570,8 +567,7 @@ rw_gbe_file_exact(int fd, unsigned char *mem, size_t nrw, goto err_rw_gbe_file_exact; r = rw_file_exact(fd, mem, nrw, off, rw_type, - NO_LOOP_EAGAIN, LOOP_EINTR, MAX_ZERO_RW_RETRY, - OFF_ERR); + MAX_ZERO_RW_RETRY, OFF_ERR); return rw_over_nrw(r, nrw); |
