summaryrefslogtreecommitdiff
path: root/util/libreboot-utils/lib/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/libreboot-utils/lib/file.c')
-rw-r--r--util/libreboot-utils/lib/file.c242
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
*/