diff options
| author | Leah Rowe <leah@libreboot.org> | 2026-03-28 06:53:37 +0000 |
|---|---|---|
| committer | Leah Rowe <leah@libreboot.org> | 2026-03-28 06:53:37 +0000 |
| commit | 0f1a22174fc7c6a0767617974640d521074174d5 (patch) | |
| tree | 5d13587d08a95332518b3191b7440424f0f190c6 /util/libreboot-utils | |
| parent | 55f0e6ac8e540cea24af64070bfc49a032729511 (diff) | |
libreboot-utils: unified error handling
i now use a singleton hook function per program:
nvmutil, mkhtemp and lottery
call this at the startup of your program:
(void) errhook(exit_cleanup);
then provide that function. make it static,
so that each program has its own version.
if you're writing a program that handles lots
of files for example, and you want to do certain
cleanup on exit (including error exit), this can
be quite useful.
Signed-off-by: Leah Rowe <leah@libreboot.org>
Diffstat (limited to 'util/libreboot-utils')
| -rw-r--r-- | util/libreboot-utils/include/common.h | 13 | ||||
| -rw-r--r-- | util/libreboot-utils/lib/checksum.c | 4 | ||||
| -rw-r--r-- | util/libreboot-utils/lib/command.c | 58 | ||||
| -rw-r--r-- | util/libreboot-utils/lib/file.c | 8 | ||||
| -rw-r--r-- | util/libreboot-utils/lib/io.c | 48 | ||||
| -rw-r--r-- | util/libreboot-utils/lib/num.c | 2 | ||||
| -rw-r--r-- | util/libreboot-utils/lib/rand.c | 12 | ||||
| -rw-r--r-- | util/libreboot-utils/lib/state.c | 92 | ||||
| -rw-r--r-- | util/libreboot-utils/lib/string.c | 51 | ||||
| -rw-r--r-- | util/libreboot-utils/lib/usage.c | 2 | ||||
| -rw-r--r-- | util/libreboot-utils/lib/word.c | 2 | ||||
| -rw-r--r-- | util/libreboot-utils/lottery.c | 11 | ||||
| -rw-r--r-- | util/libreboot-utils/mkhtemp.c | 31 | ||||
| -rw-r--r-- | util/libreboot-utils/nvmutil.c | 34 |
14 files changed, 182 insertions, 186 deletions
diff --git a/util/libreboot-utils/include/common.h b/util/libreboot-utils/include/common.h index 652b8c08..9ec8a0e3 100644 --- a/util/libreboot-utils/include/common.h +++ b/util/libreboot-utils/include/common.h @@ -225,10 +225,12 @@ int fchmod(int fd, mode_t mode); /* command table */ +typedef void (*func_t)(void); + struct commands { size_t chk; char *str; - void (*run)(void); + func_t run; int argc; unsigned char arg_part; unsigned char chksum_read; @@ -488,12 +490,11 @@ int try_err(int loop_err, int errval); */ void usage(void); -void err_no_cleanup(int stfu, int nvm_errval, const char *msg, ...); -void b0rk(int nvm_errval, const char *msg, ...); -int exit_cleanup(void); +void err_exit(int nvm_errval, const char *msg, ...); +func_t errhook(func_t ptr); /* hook function for cleanup on err */ const char *getnvmprogname(void); - -void err_mkhtemp(int stfu, int errval, const char *msg, ...); +void no_op(void); +void err_mkhtemp(int errval, const char *msg, ...); /* libc hardening */ diff --git a/util/libreboot-utils/lib/checksum.c b/util/libreboot-utils/lib/checksum.c index 9a041989..97b0efca 100644 --- a/util/libreboot-utils/lib/checksum.c +++ b/util/libreboot-utils/lib/checksum.c @@ -59,10 +59,10 @@ read_checksums(void) if (_num_invalid >= _max_invalid) { if (_max_invalid == 1) - b0rk(ECANCELED, "%s: part %lu has a bad checksum", + err_exit(ECANCELED, "%s: part %lu has a bad checksum", f->fname, (size_t)f->part); - b0rk(ECANCELED, "%s: No valid checksum found in file", + err_exit(ECANCELED, "%s: No valid checksum found in file", f->fname); } } diff --git a/util/libreboot-utils/lib/command.c b/util/libreboot-utils/lib/command.c index c7048a23..d0f783dd 100644 --- a/util/libreboot-utils/lib/command.c +++ b/util/libreboot-utils/lib/command.c @@ -46,27 +46,27 @@ sanitize_command_index(size_t c) check_command_num(c); if (cmd->argc < 3) - b0rk(EINVAL, "cmd index %lu: argc below 3, %d", + err_exit(EINVAL, "cmd index %lu: argc below 3, %d", (size_t)c, cmd->argc); if (cmd->str == NULL) - b0rk(EINVAL, "cmd index %lu: NULL str", + err_exit(EINVAL, "cmd index %lu: NULL str", (size_t)c); if (*cmd->str == '\0') - b0rk(EINVAL, "cmd index %lu: empty str", + err_exit(EINVAL, "cmd index %lu: empty str", (size_t)c); if (slen(cmd->str, MAX_CMD_LEN +1, &rval) < 0) - b0rk(errno, "Could not get command length"); + err_exit(errno, "Could not get command length"); if (rval > MAX_CMD_LEN) { - b0rk(EINVAL, "cmd index %lu: str too long: %s", + err_exit(EINVAL, "cmd index %lu: str too long: %s", (size_t)c, cmd->str); } if (cmd->run == NULL) - b0rk(EINVAL, "cmd index %lu: cmd ptr null", + err_exit(EINVAL, "cmd index %lu: cmd ptr null", (size_t)c); check_bin(cmd->arg_part, "cmd.arg_part"); @@ -80,19 +80,19 @@ sanitize_command_index(size_t c) case NVM_SIZE: break; default: - b0rk(EINVAL, "Unsupported rw_size: %lu", + err_exit(EINVAL, "Unsupported rw_size: %lu", (size_t)gbe_rw_size); } if (gbe_rw_size > GBE_PART_SIZE) - b0rk(EINVAL, "rw_size larger than GbE part: %lu", + err_exit(EINVAL, "rw_size larger than GbE part: %lu", (size_t)gbe_rw_size); _flag = (cmd->flags & O_ACCMODE); if (_flag != O_RDONLY && _flag != O_RDWR) - b0rk(EINVAL, "invalid cmd.flags setting"); + err_exit(EINVAL, "invalid cmd.flags setting"); } void @@ -110,7 +110,7 @@ set_cmd(int argc, char *argv[]) cmd = x->cmd[c].str; if (scmp(argv[2], cmd, MAX_CMD_LEN, &rval) < 0) - err_no_cleanup(0, EINVAL, + err_exit(EINVAL, "could not compare command strings"); if (rval != 0) continue; /* not the right command */ @@ -123,7 +123,7 @@ set_cmd(int argc, char *argv[]) return; } - err_no_cleanup(0, EINVAL, + err_exit(EINVAL, "Too few args on command '%s'", cmd); } @@ -148,11 +148,11 @@ set_cmd_args(int argc, char *argv[]) /* Maintainer bug */ if (cmd->arg_part && argc < 4) - b0rk(EINVAL, + err_exit(EINVAL, "arg_part set for command that needs argc4"); if (cmd->arg_part && i == CMD_SETMAC) - b0rk(EINVAL, + err_exit(EINVAL, "arg_part set on CMD_SETMAC"); if (i == CMD_SETMAC) { @@ -174,13 +174,13 @@ conv_argv_part_num(const char *part_str) unsigned char ch; if (part_str[0] == '\0' || part_str[1] != '\0') - b0rk(EINVAL, "Partnum string '%s' wrong length", part_str); + err_exit(EINVAL, "Partnum string '%s' wrong length", part_str); /* char signedness is implementation-defined */ ch = (unsigned char)part_str[0]; if (ch < '0' || ch > '1') - b0rk(EINVAL, "Bad part number (%c)", ch); + err_exit(EINVAL, "Bad part number (%c)", ch); return (size_t)(ch - '0'); } @@ -189,7 +189,7 @@ void check_command_num(size_t c) { if (!valid_command(c)) - b0rk(EINVAL, "Invalid run_cmd arg: %lu", + err_exit(EINVAL, "Invalid run_cmd arg: %lu", (size_t)c); } @@ -205,7 +205,7 @@ valid_command(size_t c) cmd = &x->cmd[c]; if (c != cmd->chk) - b0rk(EINVAL, + err_exit(EINVAL, "Invalid cmd chk value (%lu) vs arg: %lu", cmd->chk, c); @@ -240,10 +240,10 @@ parse_mac_string(void) size_t rval; if (slen(x->mac.str, 18, &rval) < 0) - b0rk(EINVAL, "Could not determine MAC length"); + err_exit(EINVAL, "Could not determine MAC length"); if (rval != 17) - b0rk(EINVAL, "MAC address is the wrong length"); + err_exit(EINVAL, "MAC address is the wrong length"); memset(mac->mac_buf, 0, sizeof(mac->mac_buf)); @@ -251,10 +251,10 @@ parse_mac_string(void) set_mac_byte(mac_byte); if ((mac->mac_buf[0] | mac->mac_buf[1] | mac->mac_buf[2]) == 0) - b0rk(EINVAL, "Must not specify all-zeroes MAC address"); + err_exit(EINVAL, "Must not specify all-zeroes MAC address"); if (mac->mac_buf[0] & 1) - b0rk(EINVAL, "Must not specify multicast MAC address"); + err_exit(EINVAL, "Must not specify multicast MAC address"); } void @@ -272,7 +272,7 @@ set_mac_byte(size_t mac_byte_pos) if (mac_str_pos < 15) { if ((separator = mac->str[mac_str_pos + 2]) != ':') - b0rk(EINVAL, "Invalid MAC address separator '%c'", + err_exit(EINVAL, "Invalid MAC address separator '%c'", separator); } @@ -294,9 +294,9 @@ set_mac_nib(size_t mac_str_pos, if ((hex_num = hextonum(mac_ch)) > 15) { if (hex_num >= 17) - b0rk(EIO, "Randomisation failure"); + err_exit(EIO, "Randomisation failure"); else - b0rk(EINVAL, "Invalid character '%c'", + err_exit(EINVAL, "Invalid character '%c'", mac->str[mac_str_pos + mac_nib_pos]); } @@ -509,7 +509,7 @@ cat(size_t nff) if ((size_t)x->cat != nff) { - b0rk(ECANCELED, "erroneous call to cat"); + err_exit(ECANCELED, "erroneous call to cat"); } fflush(NULL); @@ -532,12 +532,12 @@ void cat_buf(unsigned char *b) { if (b == NULL) - b0rk(errno, "null pointer in cat command"); + 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) - b0rk(errno, "stdout: cat"); + err_exit(errno, "stdout: cat"); } void check_cmd(void (*fn)(void), @@ -547,7 +547,7 @@ check_cmd(void (*fn)(void), size_t i = x->i; if (x->cmd[i].run != fn) - b0rk(ECANCELED, "Running %s, but cmd %s is set", + err_exit(ECANCELED, "Running %s, but cmd %s is set", name, x->cmd[i].str); /* prevent second command @@ -559,6 +559,6 @@ check_cmd(void (*fn)(void), void cmd_helper_err(void) { - b0rk(ECANCELED, + err_exit(ECANCELED, "Erroneously running command twice"); } diff --git a/util/libreboot-utils/lib/file.c b/util/libreboot-utils/lib/file.c index 3b3e57d8..fbb4e53f 100644 --- a/util/libreboot-utils/lib/file.c +++ b/util/libreboot-utils/lib/file.c @@ -73,16 +73,16 @@ void xopen(int *fd_ptr, const char *path, int flags, struct stat *st) { if ((*fd_ptr = open(path, flags)) < 0) - err_no_cleanup(0, errno, "%s", path); + err_exit(errno, "%s", path); if (fstat(*fd_ptr, st) < 0) - err_no_cleanup(0, errno, "%s: stat", path); + err_exit(errno, "%s: stat", path); if (!S_ISREG(st->st_mode)) - err_no_cleanup(0, errno, "%s: not a regular file", path); + err_exit(errno, "%s: not a regular file", path); if (lseek_on_eintr(*fd_ptr, 0, SEEK_CUR, 1, 1) == (off_t)-1) - err_no_cleanup(0, errno, "%s: file not seekable", path); + err_exit(errno, "%s: file not seekable", path); } int diff --git a/util/libreboot-utils/lib/io.c b/util/libreboot-utils/lib/io.c index 1f2064a0..4fa6bf72 100644 --- a/util/libreboot-utils/lib/io.c +++ b/util/libreboot-utils/lib/io.c @@ -32,16 +32,16 @@ open_gbe_file(void) O_NOFOLLOW | O_CLOEXEC | O_NOCTTY, &f->gbe_st); if (f->gbe_st.st_nlink > 1) - b0rk(EINVAL, + err_exit(EINVAL, "%s: warning: file has multiple (%lu) hard links\n", f->fname, (size_t)f->gbe_st.st_nlink); if (f->gbe_st.st_nlink == 0) - b0rk(EIO, "%s: file unlinked while open", f->fname); + err_exit(EIO, "%s: file unlinked while open", f->fname); _flags = fcntl(f->gbe_fd, F_GETFL); if (_flags == -1) - b0rk(errno, "%s: fcntl(F_GETFL)", f->fname); + err_exit(errno, "%s: fcntl(F_GETFL)", f->fname); /* O_APPEND allows POSIX write() to ignore * the current write offset and write at EOF, @@ -49,7 +49,7 @@ open_gbe_file(void) */ if (_flags & O_APPEND) - b0rk(EIO, "%s: O_APPEND flag", f->fname); + err_exit(EIO, "%s: O_APPEND flag", f->fname); f->gbe_file_size = f->gbe_st.st_size; @@ -59,11 +59,11 @@ open_gbe_file(void) case SIZE_128KB: break; default: - b0rk(EINVAL, "File size must be 8KB, 16KB or 128KB"); + err_exit(EINVAL, "File size must be 8KB, 16KB or 128KB"); } if (lock_file(f->gbe_fd, cmd->flags) == -1) - b0rk(errno, "%s: can't lock", f->fname); + err_exit(errno, "%s: can't lock", f->fname); } void @@ -98,7 +98,7 @@ read_file(void) MAX_ZERO_RW_RETRY, OFF_ERR); if (_r < 0) - b0rk(errno, "%s: read failed", f->fname); + err_exit(errno, "%s: read failed", f->fname); /* copy to tmpfile */ @@ -107,34 +107,34 @@ read_file(void) MAX_ZERO_RW_RETRY, OFF_ERR); if (_r < 0) - b0rk(errno, "%s: %s: copy failed", + err_exit(errno, "%s: %s: copy failed", f->fname, f->tname); /* file size comparison */ if (fstat(f->tmp_fd, &_st) == -1) - b0rk(errno, "%s: stat", f->tname); + err_exit(errno, "%s: stat", f->tname); f->gbe_tmp_size = _st.st_size; if (f->gbe_tmp_size != f->gbe_file_size) - b0rk(EIO, "%s: %s: not the same size", + err_exit(EIO, "%s: %s: not the same size", f->fname, f->tname); /* needs sync, for verification */ if (fsync_on_eintr(f->tmp_fd) == -1) - b0rk(errno, "%s: fsync (tmpfile copy)", f->tname); + 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); if (_r < 0) - b0rk(errno, "%s: read failed (cmp)", f->tname); + err_exit(errno, "%s: read failed (cmp)", f->tname); if (memcmp(f->buf, f->bufcmp, f->gbe_file_size) != 0) - b0rk(errno, "%s: %s: read contents differ (pre-test)", + err_exit(errno, "%s: %s: read contents differ (pre-test)", f->fname, f->tname); } @@ -152,10 +152,10 @@ write_gbe_file(void) return; if (same_file(f->tmp_fd, &f->tmp_st, 0) < 0) - b0rk(errno, "%s: file inode/device changed", f->tname); + err_exit(errno, "%s: file inode/device changed", f->tname); if (same_file(f->gbe_fd, &f->gbe_st, 1) < 0) - b0rk(errno, "%s: file has changed", f->fname); + err_exit(errno, "%s: file has changed", f->fname); update_checksum = cmd->chksum_write; @@ -188,7 +188,7 @@ rw_gbe_file_part(size_t p, int rw_type, gbe_rw_size = cmd->rw_size; if (rw_type < IO_PREAD || rw_type > IO_PWRITE) - b0rk(errno, "%s: %s: part %lu: invalid rw_type, %d", + err_exit(errno, "%s: %s: part %lu: invalid rw_type, %d", f->fname, rw_type_str, (size_t)p, rw_type); mem_offset = gbe_mem_offset(p, rw_type_str); @@ -198,11 +198,11 @@ rw_gbe_file_part(size_t p, int rw_type, gbe_rw_size, file_offset, rw_type); if (rval == -1) - b0rk(errno, "%s: %s: part %lu", + err_exit(errno, "%s: %s: part %lu", f->fname, rw_type_str, (size_t)p); if ((size_t)rval != gbe_rw_size) - b0rk(EIO, "%s: partial %s: part %lu", + err_exit(EIO, "%s: partial %s: part %lu", f->fname, rw_type_str, (size_t)p); } @@ -226,7 +226,7 @@ write_to_gbe_bin(void) */ if (fsync_on_eintr(f->tmp_fd) == -1) - b0rk(errno, "%s: fsync (pre-verification)", + err_exit(errno, "%s: fsync (pre-verification)", f->tname); check_written_part(0); @@ -235,7 +235,7 @@ write_to_gbe_bin(void) report_io_err_rw(); if (f->io_err_gbe) - b0rk(EIO, "%s: bad write", f->fname); + err_exit(EIO, "%s: bad write", f->fname); saved_errno = errno; @@ -307,10 +307,10 @@ check_written_part(size_t p) memset(f->pad, 0xff, sizeof(f->pad)); if (same_file(f->tmp_fd, &f->tmp_st, 0) < 0) - b0rk(errno, "%s: file inode/device changed", f->tname); + err_exit(errno, "%s: file inode/device changed", f->tname); if (same_file(f->gbe_fd, &f->gbe_st, 1) < 0) - b0rk(errno, "%s: file changed during write", f->fname); + err_exit(errno, "%s: file changed during write", f->fname); rval = rw_gbe_file_exact(f->tmp_fd, f->pad, gbe_rw_size, file_offset, IO_PREAD); @@ -540,11 +540,11 @@ gbe_x_offset(size_t p, const char *f_op, const char *d_type, off = ((off_t)p) * (off_t)nsize; if (off > ncmp - GBE_PART_SIZE) - b0rk(ECANCELED, "%s: GbE %s %s out of bounds", + err_exit(ECANCELED, "%s: GbE %s %s out of bounds", f->fname, d_type, f_op); if (off != 0 && off != ncmp >> 1) - b0rk(ECANCELED, "%s: GbE %s %s at bad offset", + err_exit(ECANCELED, "%s: GbE %s %s at bad offset", f->fname, d_type, f_op); return off; diff --git a/util/libreboot-utils/lib/num.c b/util/libreboot-utils/lib/num.c index f53f0cee..66fc26f1 100644 --- a/util/libreboot-utils/lib/num.c +++ b/util/libreboot-utils/lib/num.c @@ -51,6 +51,6 @@ void check_bin(size_t a, const char *a_name) { if (a > 1) - err_no_cleanup(0, EINVAL, "%s must be 0 or 1, but is %lu", + err_exit(EINVAL, "%s must be 0 or 1, but is %lu", a_name, (size_t)a); } diff --git a/util/libreboot-utils/lib/rand.c b/util/libreboot-utils/lib/rand.c index 863ace17..3ca19d0c 100644 --- a/util/libreboot-utils/lib/rand.c +++ b/util/libreboot-utils/lib/rand.c @@ -77,7 +77,7 @@ rsize(size_t n) { size_t rval = SIZE_MAX; if (!n) - err_no_cleanup(0, EFAULT, "rsize: division by zero"); + err_exit(EFAULT, "rsize: division by zero"); /* rejection sampling (clamp rand to eliminate modulo bias) */ for (; rval >= SIZE_MAX - (SIZE_MAX % n); rset(&rval, sizeof(rval))); @@ -92,13 +92,13 @@ mkrstr(size_t n) /* emulates spkmodem-decode */ size_t i; if (n == 0) - err_no_cleanup(0, EPERM, "mkrbuf: zero-byte request"); + err_exit(EPERM, "mkrbuf: zero-byte request"); if (n >= SIZE_MAX - 1) - err_no_cleanup(0, EOVERFLOW, "mkrbuf: overflow"); + err_exit(EOVERFLOW, "mkrbuf: overflow"); if (if_err((s = mkrbuf(n + 1)) == NULL, EFAULT)) - err_no_cleanup(0, EFAULT, "mkrstr: null"); + err_exit(EFAULT, "mkrstr: null"); for (i = 0; i < n; i++) while(*(s + i) == '\0') @@ -126,7 +126,7 @@ rset(void *buf, size_t n) goto err; if (n == 0) - err_no_cleanup(0, EPERM, "rset: zero-byte request"); + err_exit(EPERM, "rset: zero-byte request"); #if (defined(__OpenBSD__) || defined(__FreeBSD__) || \ defined(__NetBSD__) || defined(__APPLE__) || \ @@ -181,7 +181,7 @@ err: ((USE_URANDOM) > 0) close_no_err(&fd); #endif - err_no_cleanup(0, ECANCELED, + err_exit(ECANCELED, "Randomisation failure, possibly unsupported in your kernel"); exit(EXIT_FAILURE); } diff --git a/util/libreboot-utils/lib/state.c b/util/libreboot-utils/lib/state.c index 41c851fb..a3cd5b1f 100644 --- a/util/libreboot-utils/lib/state.c +++ b/util/libreboot-utils/lib/state.c @@ -4,9 +4,6 @@ * State machine (singleton) for nvmutil data. */ -#ifdef __OpenBSD__ -#include <sys/param.h> -#endif #include <sys/types.h> #include <sys/stat.h> @@ -98,9 +95,9 @@ xstart(int argc, char *argv[]) return &us; if (argc < 3) - err_no_cleanup(0, EINVAL, "xstart: Too few arguments"); + err_exit(EINVAL, "xstart: Too few arguments"); if (argv == NULL) - err_no_cleanup(0, EINVAL, "xstart: NULL argv"); + err_exit(EINVAL, "xstart: NULL argv"); first_run = 0; @@ -113,41 +110,41 @@ xstart(int argc, char *argv[]) us.f.tname = NULL; if ((realdir = realpath(us.f.fname, NULL)) == NULL) - err_no_cleanup(0, errno, "xstart: can't get realpath of %s", + err_exit(errno, "xstart: can't get realpath of %s", us.f.fname); if (fs_dirname_basename(realdir, &dir, &base, 0) < 0) - err_no_cleanup(0, errno, "xstart: don't know CWD of %s", + err_exit(errno, "xstart: don't know CWD of %s", us.f.fname); if ((us.f.base = strdup(base)) == NULL) - err_no_cleanup(0, errno, "strdup base"); + err_exit(errno, "strdup base"); us.f.dirfd = fs_open(dir, O_RDONLY | O_DIRECTORY); if (us.f.dirfd < 0) - err_no_cleanup(0, errno, "%s: open dir", dir); + err_exit(errno, "%s: open dir", dir); if (new_tmpfile(&us.f.tmp_fd, &us.f.tname, dir, ".gbe.XXXXXXXXXX") < 0) - err_no_cleanup(0, errno, "%s", us.f.tname); + err_exit(errno, "%s", us.f.tname); if (fs_dirname_basename(us.f.tname, &tmpdir, &tmpbase_local, 0) < 0) - err_no_cleanup(0, errno, "tmp basename"); + err_exit(errno, "tmp basename"); us.f.tmpbase = strdup(tmpbase_local); if (us.f.tmpbase == NULL) - err_no_cleanup(0, errno, "strdup tmpbase"); + err_exit(errno, "strdup tmpbase"); free_and_set_null(&tmpdir); if (us.f.tname == NULL) - err_no_cleanup(0, errno, "x->f.tname null"); + err_exit(errno, "x->f.tname null"); if (*us.f.tname == '\0') - err_no_cleanup(0, errno, "x->f.tname empty"); + err_exit(errno, "x->f.tname empty"); if (fstat(us.f.tmp_fd, &us.f.tmp_st) < 0) - err_no_cleanup(0, errno, "%s: stat", us.f.tname); + err_exit(errno, "%s: stat", us.f.tname); memset(us.f.real_buf, 0, sizeof(us.f.real_buf)); memset(us.f.bufcmp, 0, sizeof(us.f.bufcmp)); @@ -164,70 +161,7 @@ xstatus(void) struct xstate *x = xstart(0, NULL); if (x == NULL) - err_no_cleanup(0, EACCES, "NULL pointer to xstate"); + err_exit(EACCES, "NULL pointer to xstate"); return x; } - -void -b0rk(int nvm_errval, const char *msg, ...) -{ - struct xstate *x = xstatus(); - - va_list args; - - if (errno == 0) - errno = nvm_errval; - if (!errno) - errno = ECANCELED; - - (void)exit_cleanup(); - - if (x != NULL) - fprintf(stderr, "%s: ", getnvmprogname()); - - va_start(args, msg); - vfprintf(stderr, msg, args); - va_end(args); - - fprintf(stderr, ": %s\n", strerror(errno)); - - exit(EXIT_FAILURE); -} - -int -exit_cleanup(void) -{ - struct xstate *x = xstatus(); - struct xfile *f; - - int close_err; - int saved_errno; - - close_err = 0; - saved_errno = errno; - - if (x != NULL) { - f = &x->f; - - close_no_err(&f->gbe_fd); - close_no_err(&f->tmp_fd); - close_no_err(&f->tmp_fd); - - if (f->tname != NULL) - if (unlink(f->tname) == -1) - close_err = 1; - - close_no_err(&f->dirfd); - free_and_set_null(&f->base); - free_and_set_null(&f->tmpbase); - } - - if (saved_errno) - errno = saved_errno; - - if (close_err) - return -1; - - return 0; -} diff --git a/util/libreboot-utils/lib/string.c b/util/libreboot-utils/lib/string.c index dd11c039..9e38a9e9 100644 --- a/util/libreboot-utils/lib/string.c +++ b/util/libreboot-utils/lib/string.c @@ -40,9 +40,9 @@ vmalloc(void **buf, size_t size) void *rval = NULL; if (size >= SIZE_MAX - 1) - err_no_cleanup(0, EOVERFLOW, "integer overflow in vmalloc"); + err_exit(EOVERFLOW, "integer overflow in vmalloc"); if (buf == NULL) - err_no_cleanup(0, EFAULT, "Bad pointer passed to vmalloc"); + err_exit(EFAULT, "Bad pointer passed to vmalloc"); /* lots of programs will * re-initialise a buffer @@ -52,14 +52,14 @@ vmalloc(void **buf, size_t size) * force the programmer to behave */ if (*buf != NULL) - err_no_cleanup(0, EFAULT, "Non-null pointer given to vmalloc"); + err_exit(EFAULT, "Non-null pointer given to vmalloc"); if (!size) - err_no_cleanup(0, EFAULT, + err_exit(EFAULT, "Tried to vmalloc(0) and that is very bad. Fix it now"); if ((rval = malloc(size)) == NULL) - err_no_cleanup(0, errno, "malloc fail in vmalloc"); + err_exit(errno, "malloc fail in vmalloc"); return *buf = rval; } @@ -288,12 +288,16 @@ err: /* the one for nvmutil state is in state.c */ /* this one just exits */ void -err_no_cleanup(int stfu, int nvm_errval, const char *msg, ...) +err_exit(int nvm_errval, const char *msg, ...) { va_list args; int saved_errno = errno; const char *p; + func_t err_cleanup = errhook(NULL); + err_cleanup(); + errno = saved_errno; + if (!errno) saved_errno = errno = ECANCELED; @@ -312,6 +316,37 @@ err_no_cleanup(int stfu, int nvm_errval, const char *msg, ...) exit(EXIT_FAILURE); } +/* the err function will + * call this upon exit, and + * cleanup will be performed + * e.g. you might want to + * close some files, depending + * on your program. + * see: err_exit() + */ +func_t errhook(func_t ptr) +{ + static int set = 0; + static func_t hook = NULL; + + if (!set) { + set = 1; + + if (ptr == NULL) + hook = no_op; + else + hook = ptr; + } + + return hook; +} + +void +no_op(void) +{ + return; +} + const char * getnvmprogname(void) { @@ -366,7 +401,7 @@ xpledgex(const char *promises, const char *execpromises) (void) promises, (void) execpromises, (void) saved_errno; #ifdef __OpenBSD__ if (pledge(promises, execpromises) == -1) - err_no_cleanup(0, errno, "pledge"); + err_exit(errno, "pledge"); #endif errno = saved_errno; return 0; @@ -378,7 +413,7 @@ xunveilx(const char *path, const char *permissions) (void) path, (void) permissions, (void) saved_errno; #ifdef __OpenBSD__ if (pledge(promises, execpromises) == -1) - err_no_cleanup(0, errno, "pledge"); + err_exit(errno, "pledge"); #endif errno = saved_errno; return 0; diff --git a/util/libreboot-utils/lib/usage.c b/util/libreboot-utils/lib/usage.c index 2b5a93ca..ebec119e 100644 --- a/util/libreboot-utils/lib/usage.c +++ b/util/libreboot-utils/lib/usage.c @@ -26,5 +26,5 @@ usage(void) util, util, util, util, util, util, util); - b0rk(EINVAL, "Too few arguments"); + err_exit(EINVAL, "Too few arguments"); } diff --git a/util/libreboot-utils/lib/word.c b/util/libreboot-utils/lib/word.c index 6563e67a..85e1d88b 100644 --- a/util/libreboot-utils/lib/word.c +++ b/util/libreboot-utils/lib/word.c @@ -63,6 +63,6 @@ check_nvm_bound(size_t c, size_t p) check_bin(p, "part number"); if (c >= NVM_WORDS) - b0rk(ECANCELED, "check_nvm_bound: out of bounds %lu", + err_exit(ECANCELED, "check_nvm_bound: out of bounds %lu", (size_t)c); } diff --git a/util/libreboot-utils/lottery.c b/util/libreboot-utils/lottery.c index fd0728fd..cbe8a871 100644 --- a/util/libreboot-utils/lottery.c +++ b/util/libreboot-utils/lottery.c @@ -11,6 +11,9 @@ #include "include/common.h" static void +exit_cleanup(void); + +static void spew_buf(const void *data, size_t len); int @@ -22,6 +25,8 @@ main(int argc, char **argv) (void) argc, (void) argv; xpledgex("stdio", NULL); + (void) errhook(exit_cleanup); + buf = mkrbuf(BUFSIZ + 1); if (!memcmp(buf, buf + (BUFSIZ >> 1), BUFSIZ >> 1)) same = 1; @@ -73,3 +78,9 @@ spew_buf(const void *data, size_t len) printf("%08zx\n", len); } + +static void +exit_cleanup(void) +{ + return; +} diff --git a/util/libreboot-utils/mkhtemp.c b/util/libreboot-utils/mkhtemp.c index 32a967d1..5be5a38a 100644 --- a/util/libreboot-utils/mkhtemp.c +++ b/util/libreboot-utils/mkhtemp.c @@ -34,6 +34,9 @@ #include "include/common.h" +static void +exit_cleanup(void); + int main(int argc, char *argv[]) { @@ -57,10 +60,11 @@ main(int argc, char *argv[]) int fd = -1; int type = MKHTEMP_FILE; - int stfu = 0; /* -q option */ + + (void) errhook(exit_cleanup); if (lbgetprogname(argv[0]) == NULL) - err_no_cleanup(stfu, errno, "could not set progname"); + err_exit(errno, "could not set progname"); /* https://man.openbsd.org/pledge.2 */ xpledgex("stdio flock rpath wpath cpath", NULL); @@ -79,7 +83,6 @@ main(int argc, char *argv[]) case 'q': /* don't print errors */ /* (exit status unchanged) */ - stfu = 1; break; default: @@ -95,14 +98,14 @@ main(int argc, char *argv[]) /* custom template e.g. foo.XXXXXXXXXXXXXXXXXXXXX */ if (template != NULL) { if (slen(template, maxlen, &tlen) < 0) - err_no_cleanup(stfu, EINVAL, + err_exit(EINVAL, "invalid template"); for (p = template + tlen; p > template && *--p == 'X'; xc++); if (xc < 3) /* the gnu mktemp errs on less than 3 */ - err_no_cleanup(stfu, EINVAL, + err_exit(EINVAL, "template must have 3 X or more on end (12+ advised"); } @@ -116,31 +119,37 @@ main(int argc, char *argv[]) if (tmpdir != NULL) { rp = realpath(tmpdir, resolved); if (rp == NULL) - err_no_cleanup(stfu, errno, "%s", tmpdir); + err_exit(errno, "%s", tmpdir); tmpdir = resolved; } if (new_tmp_common(&fd, &s, type, tmpdir, template) < 0) - err_no_cleanup(stfu, errno, "%s", s); + err_exit(errno, "%s", s); xpledgex("stdio", NULL); if (s == NULL) - err_no_cleanup(stfu, EFAULT, "bad string initialisation"); + err_exit(EFAULT, "bad string initialisation"); if (*s == '\0') - err_no_cleanup(stfu, EFAULT, "empty string initialisation"); + err_exit(EFAULT, "empty string initialisation"); if (slen(s, maxlen, &len) < 0) - err_no_cleanup(stfu, EFAULT, "unterminated string initialisiert"); + err_exit(EFAULT, "unterminated string initialisiert"); printf("%s\n", s); return EXIT_SUCCESS; err_usage: - err_no_cleanup(stfu, EINVAL, + err_exit(EINVAL, "usage: %s [-d] [-p dir] [template]\n", getnvmprogname()); +} + +static void +exit_cleanup(void) +{ + return; }/* ( >:3 ) diff --git a/util/libreboot-utils/nvmutil.c b/util/libreboot-utils/nvmutil.c index d78ab0c8..bab1945d 100644 --- a/util/libreboot-utils/nvmutil.c +++ b/util/libreboot-utils/nvmutil.c @@ -12,39 +12,44 @@ #include <errno.h> #include <fcntl.h> #include <limits.h> +#include <stdarg.h> #include <stddef.h> #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <unistd.h> #include "include/common.h" +static void +exit_cleanup(void); + int main(int argc, char *argv[]) { struct xstate *x; - struct commands *cmd; struct xfile *f; - size_t c; + (void) errhook(exit_cleanup); + if (lbgetprogname(argv[0]) == NULL) - err_no_cleanup(0, errno, "could not set progname"); + err_exit(errno, "could not set progname"); xpledgex("stdio flock rpath wpath cpath unveil", NULL); xunveilx("/dev/urandom", "r"); #ifndef S_ISREG - err_no_cleanup(0, ECANCELED, + err_exit(ECANCELED, "Can't determine file types (S_ISREG undefined)"); #endif #if ((CHAR_BIT) != 8) - err_no_cleanup(0, ECANCELED, "Unsupported char size"); + err_exit(ECANCELED, "Unsupported char size"); #endif if ((x = xstart(argc, argv)) == NULL) - err_no_cleanup(0, ECANCELED, "NULL state on init"); + err_exit(ECANCELED, "NULL state on init"); /* parse user command */ /* TODO: CHECK ACCESSES VIA xstatus() */ @@ -64,15 +69,12 @@ main(int argc, char *argv[]) xpledgex("stdio flock rpath wpath cpath", NULL); if (cmd->run == NULL) - b0rk(errno, "Command not set"); + err_exit(errno, "Command not set"); sanitize_command_list(); - open_gbe_file(); - copy_gbe(); read_checksums(); - cmd->run(); for (c = 0; c < items(x->cmd); c++) @@ -81,13 +83,17 @@ main(int argc, char *argv[]) if ((cmd->flags & O_ACCMODE) == O_RDWR) write_to_gbe_bin(); - if (exit_cleanup() == -1) - b0rk(EIO, "%s: close", f->fname); - + exit_cleanup(); if (f->io_err_gbe_bin) - b0rk(EIO, "%s: error writing final file"); + err_exit(EIO, "%s: error writing final file"); free_and_set_null(&f->tname); return EXIT_SUCCESS; } + +static void +exit_cleanup(void) +{ + return; +} |
