summaryrefslogtreecommitdiff
path: root/util/libreboot-utils
diff options
context:
space:
mode:
authorLeah Rowe <leah@libreboot.org>2026-03-31 11:54:41 +0100
committerLeah Rowe <leah@libreboot.org>2026-03-31 12:03:46 +0100
commit277c0c8e87a1ad3012b606d17c8afc3e785f3d39 (patch)
treebfd01b5ba92f683370ee23a596f87c594195f098 /util/libreboot-utils
parentaacf9fb6c9f6f364c8d1799b02f4d5fc0f63e98f (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.c32
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