diff options
| author | Leah Rowe <leah@libreboot.org> | 2026-03-31 11:54:41 +0100 |
|---|---|---|
| committer | Leah Rowe <leah@libreboot.org> | 2026-03-31 12:03:46 +0100 |
| commit | 277c0c8e87a1ad3012b606d17c8afc3e785f3d39 (patch) | |
| tree | bfd01b5ba92f683370ee23a596f87c594195f098 /util/libreboot-utils | |
| parent | aacf9fb6c9f6f364c8d1799b02f4d5fc0f63e98f (diff) | |
lbutils/file: don't reset errno on successful io
some io syscalls may set errno on success. this patch
honours that. we try to preserve caller errno, but it
is important for debugging not to clobber it.
if fs_err_retry errs, then we don't reset errno.
if fs_err is successful but errno wasn't set, we
restore caller errno. this is done by setting errno
to zero in callers, which also restore caller errno.
Signed-off-by: Leah Rowe <leah@libreboot.org>
Diffstat (limited to 'util/libreboot-utils')
| -rw-r--r-- | util/libreboot-utils/lib/file.c | 32 |
1 files changed, 31 insertions, 1 deletions
diff --git a/util/libreboot-utils/lib/file.c b/util/libreboot-utils/lib/file.c index b4636865..3f94a4ab 100644 --- a/util/libreboot-utils/lib/file.c +++ b/util/libreboot-utils/lib/file.c @@ -770,6 +770,7 @@ open_file_on_eintr(const char *path, err_exit(EBADF, "%s: open_file_on_eintr: file already open", path); + errno = 0; while (fs_retry(saved_errno, rval = open(path, flags, mode))); @@ -814,6 +815,7 @@ openat_on_eintr(int dirfd, const char *path, if_err(path == NULL, EFAULT)) return set_errno(saved_errno, EIO); + errno = 0; while (sys_retry(saved_errno, rval = syscall(SYS_openat2, dirfd, path, &how, sizeof(how)))); @@ -834,6 +836,7 @@ openat_on_eintr(int dirfd, const char *path, if_err(path == NULL, EFAULT)) return set_errno(saved_errno, EIO); + errno = 0; while (fs_retry(saved_errno, rval = openat(dirfd, path, flags, mode))); @@ -848,6 +851,7 @@ lseek_on_eintr(int fd, off_t off, int whence, int saved_errno = errno; off_t rval; + errno = 0; while (off_retry(saved_errno, rval = lseek(fd, off, whence))); @@ -865,6 +869,7 @@ mkdirat_on_eintr(int dirfd, if_err(path == NULL, EFAULT)) return set_errno(saved_errno, EIO); + errno = 0; while (fs_retry(saved_errno, rval = mkdirat(dirfd, path, mode))); @@ -883,6 +888,7 @@ read_on_eintr(int fd, if_err(count == 0, EINVAL)) return set_errno(saved_errno, EIO); + errno = 0; while (rw_retry(saved_errno, rval = read(fd, buf, count))); @@ -903,6 +909,7 @@ pread_on_eintr(int fd, if_err(count == 0, EINVAL)) return set_errno(saved_errno, EIO); + errno = 0; while (rw_retry(saved_errno, rval = pread(fd, buf, count, off))); @@ -921,6 +928,7 @@ write_on_eintr(int fd, if_err(count == 0, EINVAL)) return set_errno(saved_errno, EIO); + errno = 0; while (rw_retry(saved_errno, rval = write(fd, buf, count))); @@ -941,6 +949,7 @@ pwrite_on_eintr(int fd, if_err(count == 0, EINVAL)) return set_errno(saved_errno, EIO); + errno = 0; while (rw_retry(saved_errno, rval = pwrite(fd, buf, count, off))); @@ -956,6 +965,7 @@ fsync_on_eintr(int fd) if (if_err(fd < 0, EBADF)) return set_errno(saved_errno, EIO); + errno = 0; while (fs_retry(saved_errno, rval = fsync(fd))); @@ -973,6 +983,7 @@ close_on_eintr(int *fd) if (*fd < 0) return; + errno = 0; while (fs_retry(saved_errno, rval = close(*fd))); @@ -995,9 +1006,28 @@ close_on_eintr(int *fd) errno == EWOULDBLOCK || \ errno == ETXTBSY)) \ return 1; \ - if (rval >= 0) \ + if (rval >= 0 && !errno) \ errno = saved_errno; \ return 0 +/* + * Regarding the errno logic above: + * on success, it is permitted that + * a syscall could still set errno. + * We reset errno after storingit + * for later preservation, in functions + * that call *_retry() functions. + * + * They rely ultimately on this + * macro for errno restoration. We + * assume therefore that errno was + * reset to zero before the retry + * loop. If errno is then *set* on + * success, we leave it alone. Otherwise, + * we restore the caller's saved errno. + * + * This offers some consistency, while + * complying with POSIX specification. + */ /* retry switch for offset-based |
