diff options
| author | Leah Rowe <leah@libreboot.org> | 2026-03-24 18:46:36 +0000 |
|---|---|---|
| committer | Leah Rowe <leah@libreboot.org> | 2026-03-24 18:46:36 +0000 |
| commit | c1befbcd3eb4a51831260c7c7b743a673512e6a5 (patch) | |
| tree | 04fee08997783de473bdd69d12f6b6cfc4c2b558 /util/libreboot-utils/lib | |
| parent | 6593e76c6a17d1e0cb82a2f29e832348fa9aa5ca (diff) | |
util/nvmutil: never do cross-filesystem moves
make a local TMPDIR instead, where gbe.bin is.
this avoids the EXDEV errno, so we don't have
to handle it, and it's just better performant
for everyone.
Signed-off-by: Leah Rowe <leah@libreboot.org>
Diffstat (limited to 'util/libreboot-utils/lib')
| -rw-r--r-- | util/libreboot-utils/lib/io.c | 64 | ||||
| -rw-r--r-- | util/libreboot-utils/lib/mkhtemp.c | 92 | ||||
| -rw-r--r-- | util/libreboot-utils/lib/state.c | 13 |
3 files changed, 41 insertions, 128 deletions
diff --git a/util/libreboot-utils/lib/io.c b/util/libreboot-utils/lib/io.c index de5f8c76..ef87d521 100644 --- a/util/libreboot-utils/lib/io.c +++ b/util/libreboot-utils/lib/io.c @@ -458,70 +458,6 @@ gbe_mv(void) err(errno, "TODO: cross-filesystem atomic writes currently broken"); - /* - * cross-filesystem: copy into target dir tmp - */ - - if (fs_dirname_basename(f->fname, - &dir, &base, 0) < 0) - goto ret_gbe_mv; - - dirfd = fs_open(dir, - O_RDONLY | O_DIRECTORY); - - if (dirfd < 0) - goto ret_gbe_mv; - - if (fstat(dirfd, &st_dir) < 0) - goto ret_gbe_mv; - - if (new_tmpfile_at(dirfd, &st_dir, - &dest_fd, &dest_name) < 0) - goto ret_gbe_mv; - - /* copy: tmp to local tmp */ - - rval = 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); - - if (rval < 0) - goto ret_gbe_mv; - - rval = rw_file_exact(dest_fd, f->bufcmp, - f->gbe_file_size, 0, IO_PWRITE, - NO_LOOP_EAGAIN, LOOP_EINTR, - MAX_ZERO_RW_RETRY, OFF_ERR); - - if (rval < 0) - goto ret_gbe_mv; - - if (fsync_on_eintr(dest_fd) == -1) - goto ret_gbe_mv; - - if (close_on_eintr(dest_fd) == -1) { - dest_fd = -1; - goto ret_gbe_mv; - } - dest_fd = -1; - - /* atomic replace */ - - if (fs_rename_at(dirfd, dest_name, - dirfd, base) == -1) - goto ret_gbe_mv; - - if (fsync_dir(f->fname) < 0) { - f->io_err_gbe_bin = 1; - goto ret_gbe_mv; - } - - free_if_null(&dest_name); - free_if_null(&dir); - - tmp_gbe_bin_exists = 0; - ret_gbe_mv: /* TODO: this whole section is bloat. diff --git a/util/libreboot-utils/lib/mkhtemp.c b/util/libreboot-utils/lib/mkhtemp.c index d1ebea25..87d7c8dc 100644 --- a/util/libreboot-utils/lib/mkhtemp.c +++ b/util/libreboot-utils/lib/mkhtemp.c @@ -27,70 +27,21 @@ #include "../include/common.h" +/* note: tmpdir is an override of TMPDIR or /tmp or /var/tmp */ int -new_tmpfile(int *fd, char **path) +new_tmpfile(int *fd, char **path, char *tmpdir) { - return new_tmp_common(fd, path, MKHTEMP_FILE); + return new_tmp_common(fd, path, MKHTEMP_FILE, tmpdir); } +/* note: tmpdir is an override of TMPDIR or /tmp or /var/tmp */ int -new_tmpdir(int *fd, char **path) +new_tmpdir(int *fd, char **path, char *tmpdir) { - return new_tmp_common(fd, path, MKHTEMP_DIR); -} - -/* not used by mkhtemp util, but by nvmutil. - * it leaves an st variable set after return, - * so that verification can be done on a file - * being used, before writing it elsewhere - */ -int -new_tmpfile_at(int dirfd, struct stat *st_dir, - int *fd, char **name) -{ - struct stat st; - char suffix[] = "tmp.XXXXXXXXXX"; - size_t len; - char *buf = NULL; - char *fname; - int saved_errno = errno; - -#if defined(PATH_LEN) && \ - (PATH_LEN) >= 256 - size_t maxlen = PATH_LEN; -#else - size_t maxlen = 4096; -#endif - - if (if_err(fd == NULL || name == NULL || st_dir == NULL, EFAULT) || - if_err(*fd >= 0, EEXIST) || - if_err(dirfd < 0, EBADF) || - if_err_sys(slen(suffix, maxlen, &len) < 0) || - if_err_sys((malloc(len + 1)) == NULL)) - return -1; - - memcpy(buf, suffix, len + 1); - fname = buf; - - *fd = mkhtemp(fd, &st, - buf, dirfd, fname, - st_dir, MKHTEMP_FILE); - - if (*fd < 0) - goto err; - - *name = buf; - errno = saved_errno; - - return 0; - -err: - free_if_null(&buf); - close_no_err(fd); - - return -1; + return new_tmp_common(fd, path, MKHTEMP_DIR, tmpdir); } +/* note: tmpdir is an override of TMPDIR or /tmp or /var/tmp */ /* WARNING: * on error, *path (at **path) may be NULL, or if the error pertains to @@ -107,7 +58,8 @@ err: * default to /tmp or /var/tmp */ int -new_tmp_common(int *fd, char **path, int type) +new_tmp_common(int *fd, char **path, int type, + char *tmpdir) { #if defined(PATH_LEN) && \ (PATH_LEN) >= 256 @@ -118,7 +70,6 @@ new_tmp_common(int *fd, char **path, int type) struct stat st; char suffix[] = "tmp.XXXXXXXXXX"; - char *tmpdir = NULL; size_t dirlen; size_t destlen; @@ -152,15 +103,25 @@ new_tmp_common(int *fd, char **path, int type) * (on error, it will not be touched) */ - *fd = -1; + if (tmpdir == NULL) { /* no user override */ +#if defined(PERMIT_NON_STICKY_ALWAYS) && \ + ((PERMIT_NON_STICKY_ALWAYS) > 0) + tmpdir = env_tmpdir(PERMIT_NON_STICKY_ALWAYS, &fail_dir, NULL); +#else + tmpdir = env_tmpdir(0, &fail_dir, NULL); +#endif + } else { + #if defined(PERMIT_NON_STICKY_ALWAYS) && \ ((PERMIT_NON_STICKY_ALWAYS) > 0) - tmpdir = env_tmpdir(PERMIT_NON_STICKY_ALWAYS, &fail_dir); + tmpdir = env_tmpdir(PERMIT_NON_STICKY_ALWAYS, &fail_dir, + tmpdir); #else - tmpdir = env_tmpdir(0, &fail_dir); + tmpdir = env_tmpdir(0, &fail_dir, tmpdir); #endif + } if (tmpdir == NULL) goto err; @@ -241,7 +202,8 @@ err: */ char * -env_tmpdir(int bypass_all_sticky_checks, char **tmpdir) +env_tmpdir(int bypass_all_sticky_checks, char **tmpdir, + char *override_tmpdir) { char *t; int allow_noworld_unsticky; @@ -250,7 +212,11 @@ env_tmpdir(int bypass_all_sticky_checks, char **tmpdir) char tmp[] = "/tmp"; char vartmp[] = "/var/tmp"; - t = getenv("TMPDIR"); + /* tmpdir is a user override, if set */ + if (override_tmpdir == NULL) + t = getenv("TMPDIR"); + else + t = override_tmpdir; if (t != NULL && *t != '\0') { diff --git a/util/libreboot-utils/lib/state.c b/util/libreboot-utils/lib/state.c index 2fc22d52..2d2f6087 100644 --- a/util/libreboot-utils/lib/state.c +++ b/util/libreboot-utils/lib/state.c @@ -26,6 +26,9 @@ struct xstate * xstart(int argc, char *argv[]) { static int first_run = 1; + static char *dir = NULL; + static char *base = NULL; + char *realdir = NULL; static struct xstate us = { { @@ -107,7 +110,15 @@ xstart(int argc, char *argv[]) us.f.tmp_fd = -1; us.f.tname = NULL; - if (new_tmpfile(&us.f.tmp_fd, &us.f.tname) < 0) + if ((realdir = realpath(us.f.fname, NULL)) == NULL) + err_no_cleanup(errno, "xstart: can't get realpath of %s", + us.f.fname); + + if (fs_dirname_basename(realdir, &dir, &base, 0) < 0) + err_no_cleanup(errno, "xstart: don't know CWD of %s", + us.f.fname); + + if (new_tmpfile(&us.f.tmp_fd, &us.f.tname, dir) < 0) err_no_cleanup(errno, "%s", us.f.tname); if (us.f.tname == NULL) |
