summaryrefslogtreecommitdiff
path: root/util/nvmutil
diff options
context:
space:
mode:
Diffstat (limited to 'util/nvmutil')
-rw-r--r--util/nvmutil/Makefile8
-rw-r--r--util/nvmutil/nvmutil.c1098
-rw-r--r--util/nvmutil/nvmutil.h54
3 files changed, 688 insertions, 472 deletions
diff --git a/util/nvmutil/Makefile b/util/nvmutil/Makefile
index f3f8d4c7..6488ca43 100644
--- a/util/nvmutil/Makefile
+++ b/util/nvmutil/Makefile
@@ -3,12 +3,16 @@
# Copyright (c) 2023 Riku Viitanen <riku.viitanen@protonmail.com>
CC?=cc
+HELLCC?=clang
+
CFLAGS?=
LDFLAGS?=
DESTDIR?=
PREFIX?=/usr/local
INSTALL?=install
+.SUFFIXES:
+
# maybe add -I. here when running make
# e.g. make LDIR=-I.
LDIR?=
@@ -32,9 +36,9 @@ warn: $(PROG).c
strict: $(PROG).c
$(CC) $(STRICT) $(PROG).c -o $(PROG) $(LDFLAGS)
-# clang strictness
+# clang-only extreme warnings (not portable)
hell: $(PROG).c
- $(CC) $(HELLFLAGS) $(PROG).c -o $(PROG) $(LDFLAGS)
+ $(HELLCC) $(HELLFLAGS) $(PROG).c -o $(PROG) $(LDFLAGS)
install: $(PROG)
$(INSTALL) -d $(DESTDIR)$(PREFIX)/bin
diff --git a/util/nvmutil/nvmutil.c b/util/nvmutil/nvmutil.c
index 2eee7a42..0df6ce89 100644
--- a/util/nvmutil/nvmutil.c
+++ b/util/nvmutil/nvmutil.c
@@ -79,12 +79,12 @@ new_xstate(void)
CHECKSUM_READ, SKIP_CHECKSUM_WRITE,
GBE_PART_SIZE, O_RDONLY
}, {
- CMD_CAT16, "cat16", cmd_helper_cat, ARGC_3,
+ CMD_CAT16, "cat16", cmd_helper_cat16, ARGC_3,
ARG_NOPART,
CHECKSUM_READ, SKIP_CHECKSUM_WRITE,
GBE_PART_SIZE, O_RDONLY
}, {
- CMD_CAT128, "cat128", cmd_helper_cat, ARGC_3,
+ CMD_CAT128, "cat128", cmd_helper_cat128, ARGC_3,
ARG_NOPART,
CHECKSUM_READ, SKIP_CHECKSUM_WRITE,
GBE_PART_SIZE, O_RDONLY
@@ -94,7 +94,7 @@ new_xstate(void)
/* ->mac */
{NULL, "xx:xx:xx:xx:xx:xx", {0, 0, 0}}, /* .str, .rmac, .mac_buf */
- /* .buf */
+ /* .f */
{0},
/* .argv0 (for our getprogname implementation) */
@@ -107,7 +107,10 @@ new_xstate(void)
1,
/* .xsize (size of the stuct will be stored here later) */
- 0
+ 0,
+
+ /* .cat (cat helpers set this) */
+ -1
};
@@ -144,15 +147,25 @@ new_xstate(void)
return xs_new;
}
-static struct xstate *nv = NULL;
+static struct xstate *x = NULL;
int
main(int argc, char *argv[])
{
struct commands *cmd;
struct xfile *f;
+ unsigned long i;
+
+ char *tmp_path;
+
+ struct stat st;
+ int fd;
- unsigned long *i;
+ tmp_path = NULL;
+
+#ifndef S_ISREG
+ err(ECANCELED, "Can't determine file types (S_ISREG undefined)");
+#endif
#ifndef CHAR_BIT
err(ECANCELED, "Unknown char size");
@@ -161,68 +174,74 @@ main(int argc, char *argv[])
err(EINVAL, "Unsupported char size");
#endif
- nv = new_xstate();
- if (nv == NULL)
- err(errno, NULL);
-
- nv->argv0 = argv[0];
if (argc < 3)
usage();
- if (nv->f.buf == NULL)
- err(EINVAL, "Work buffer not initialised");
-
- f = &nv->f;
-
- f->fname = argv[1];
-
#ifdef NVMUTIL_UNVEIL
/*
* if global tmp is a different filesystem,
* unveil would trap on final file rename
* and we can't know the path in advance
*/
- f->tname = new_tmpfile(&f->tmp_fd, 1, NULL);
+ tmp_path = new_tmpfile(&fd, 1, NULL);
#else
- f->tname = new_tmpfile(&f->tmp_fd, 0, NULL);
+ tmp_path = new_tmpfile(&fd, 0, NULL);
#endif
- if (f->tname == NULL)
+ if (tmp_path == NULL)
err(errno, "Can't create tmpfile");
#ifdef NVMUTIL_PLEDGE
#ifdef NVMUTIL_UNVEIL
if (pledge("stdio flock rpath wpath cpath unveil", NULL) == -1)
err(errno, "pledge, unveil");
- if (unveil("/dev/urandom", "r") == -1)
- err(errno, "unveil: /dev/urandom");
- if (unveil("/dev/random", "r") == -1)
- err(errno, "unveil: /dev/random");
+ if (unveil("/dev/null", "r") == -1)
+ err(errno, "unveil: /dev/null");
#else
if (pledge("stdio flock rpath wpath cpath", NULL) == -1)
err(errno, "pledge");
#endif
#endif
+ x = new_xstate();
+
+ if (x == NULL)
+ err(errno, NULL);
+ if (x->f.buf == NULL)
+ err(EINVAL, "Work buffer not initialised");
+
+ x->argv0 = argv[0];
+ f = &x->f;
+
+ f->fname = argv[1];
+ f->tname = tmp_path;
+ f->tmp_fd = fd;
+
+ if(fstat(fd, &st) < 0)
+ err(errno, "can't stat tmpfile");
+
+ f->tmp_dev = st.st_dev;
+ f->tmp_ino = st.st_ino;
+
sanitize_command_list();
set_cmd(argc, argv);
set_cmd_args(argc, argv);
- i = &nv->i;
- cmd = &nv->cmd[*i];
+ i = x->i;
+ cmd = &x->cmd[i];
#ifdef NVMUTIL_UNVEIL
- if (cmd->flags == O_RDONLY) {
- if (unveil(fname, "r") == -1)
- err(errno, "%s: unveil r", fname);
+ if ((cmd->flags & O_ACCMODE) == O_RDONLY) {
+ if (unveil(f->fname, "r") == -1)
+ err(errno, "%s: unveil r", f->fname);
} else {
- if (unveil(fname, "rwc") == -1)
- err(errno, "%s: unveil rw", fname);
+ if (unveil(f->tname, "rwc") == -1)
+ err(errno, "%s: unveil rw", f->tname);
}
- if (unveil(tname, "rwc") == -1)
- err(errno, "%s: unveil rwc", tname);
+ if (unveil(f->tname, "rwc") == -1)
+ err(errno, "%s: unveil rwc", f->tname);
if (unveil(NULL, NULL) == -1)
err(errno, "unveil block (rw)");
@@ -231,8 +250,6 @@ main(int argc, char *argv[])
err(errno, "pledge (kill unveil)");
#endif
- srand((unsigned int)(time(NULL) ^ getpid()));
-
open_gbe_file();
memset(f->buf, 0, GBE_BUF_SIZE);
@@ -244,7 +261,7 @@ main(int argc, char *argv[])
run_cmd();
- if (cmd->flags == O_RDWR)
+ if ((cmd->flags & O_ACCMODE) == O_RDWR)
write_to_gbe_bin();
if (exit_cleanup() == -1)
@@ -266,7 +283,11 @@ void
sanitize_command_list(void)
{
unsigned long c;
- unsigned long num_commands = items(nv->cmd);
+ unsigned long num_commands;
+
+ check_null_command("sanitize_command_list");
+
+ num_commands = items(x->cmd);
for (c = 0; c < num_commands; c++)
sanitize_command_index(c);
@@ -278,9 +299,14 @@ sanitize_command_list(void)
void
sanitize_command_index(unsigned long c)
{
+ struct commands *cmd;
+
+ int _flag;
unsigned long gbe_rw_size;
- struct commands *cmd = &nv->cmd[c];
+ check_null_command("sanitize_command_index");
+
+ cmd = &x->cmd[c];
check_command_num(c);
@@ -325,8 +351,10 @@ sanitize_command_index(unsigned long c)
err(EINVAL, "rw_size larger than GbE part: %lu",
(unsigned long)gbe_rw_size);
- if (cmd->flags != O_RDONLY &&
- cmd->flags != O_RDWR)
+ _flag = (cmd->flags & O_ACCMODE);
+
+ if (_flag != O_RDONLY &&
+ _flag != O_RDWR)
err(EINVAL, "invalid cmd.flags setting");
}
@@ -335,20 +363,22 @@ set_cmd(int argc, char *argv[])
{
const char *cmd;
- unsigned long i = 0;
+ unsigned long c;
+
+ check_null_command("set_cmd");
- for (i = 0; i < items(nv->cmd); i++) {
+ for (c = 0; c < items(x->cmd); c++) {
- cmd = nv->cmd[i].str;
+ cmd = x->cmd[c].str;
/* not the right command */
if (xstrxcmp(argv[2], cmd, MAX_CMD_LEN) != 0)
continue;
/* valid command found */
- if (argc >= nv->cmd[i].argc) {
- nv->no_cmd = 0;
- nv->i = i; /* set command */
+ if (argc >= x->cmd[c].argc) {
+ x->no_cmd = 0;
+ x->i = c; /* set command */
return;
}
@@ -357,48 +387,45 @@ set_cmd(int argc, char *argv[])
"Too few args on command '%s'", cmd);
}
- nv->no_cmd = 1;
+ x->no_cmd = 1;
}
void
set_cmd_args(int argc, char *argv[])
{
- unsigned char arg_part;
+ struct commands *cmd;
+ struct xfile *f;
unsigned long i;
- struct xfile *f;
- struct commands *cmd;
+ check_null_command("set_cmd_args");
- if (!valid_command(nv->i) || argc < 3)
- usage();
+ i = x->i;
+ cmd = &x->cmd[i];
+ f = &x->f;
- if (nv->no_cmd)
+ if (!valid_command(i) || argc < 3)
usage();
- i = nv->i;
- f = &nv->f;
-
- cmd = &nv->cmd[i];
-
- arg_part = cmd->arg_part;
+ if (x->no_cmd)
+ usage();
/* Maintainer bugs */
- if (arg_part && argc < 4)
+ if (cmd->arg_part && argc < 4)
err(EINVAL,
"arg_part set for command that needs argc4");
- if (arg_part && i == CMD_SETMAC)
+ if (cmd->arg_part && i == CMD_SETMAC)
err(EINVAL,
"arg_part set on CMD_SETMAC");
if (i == CMD_SETMAC) {
if (argc >= 4)
- nv->mac.str = argv[3];
+ x->mac.str = argv[3];
else
- nv->mac.str = nv->mac.rmac;
+ x->mac.str = x->mac.rmac;
- } else if (arg_part) {
+ } else if (cmd->arg_part) {
f->part = conv_argv_part_num(argv[3]);
}
@@ -436,6 +463,7 @@ xstrxcmp(const char *a, const char *b, unsigned long maxlen)
err(EINVAL, "Empty string in xstrxcmp");
for (i = 0; i < maxlen; i++) {
+
unsigned char ac = (unsigned char)a[i];
unsigned char bc = (unsigned char)b[i];
@@ -464,14 +492,16 @@ xstrxcmp(const char *a, const char *b, unsigned long maxlen)
void
open_gbe_file(void)
{
+ struct commands *cmd;
+ struct xfile *f;
+
struct stat _st;
int _flags;
- unsigned long *i = &nv->i;
-
- struct commands *cmd = &nv->cmd[*i];
+ check_null_command("open_gbe_file");
- struct xfile *f = &nv->f;
+ cmd = &x->cmd[x->i];
+ f = &x->f;
xopen(&f->gbe_fd, f->fname,
cmd->flags | O_BINARY |
@@ -513,19 +543,18 @@ open_gbe_file(void)
err(EINVAL, "File size must be 8KB, 16KB or 128KB");
}
- if (lock_file(f->gbe_fd) == -1)
+ if (lock_file(f->gbe_fd, cmd->flags) == -1)
err(errno, "%s: can't lock", f->fname);
}
int
-lock_file(int fd)
+lock_file(int fd, int flags)
{
struct flock fl;
- struct commands *cmd = &nv->cmd[nv->i];
memset(&fl, 0, sizeof(fl));
- if (cmd->flags == O_RDONLY)
+ if ((flags & O_ACCMODE) == O_RDONLY)
fl.l_type = F_RDLCK;
else
fl.l_type = F_WRLCK;
@@ -583,7 +612,11 @@ xopen(int *fd_ptr, const char *path, int flags, struct stat *st)
void
copy_gbe(void)
{
- struct xfile *f = &nv->f;
+ struct xfile *f;
+
+ check_null_command("copy_gbe");
+
+ f = &x->f;
read_file();
@@ -608,10 +641,14 @@ copy_gbe(void)
void
read_file(void)
{
- long _r;
+ struct xfile *f;
+
struct stat _st;
+ long _r;
+
+ check_null_command("read_file");
- struct xfile *f = &nv->f;
+ f = &x->f;
/* read main file */
_r = rw_file_exact(f->gbe_fd, f->buf, f->gbe_file_size,
@@ -666,13 +703,19 @@ read_file(void)
void
read_checksums(void)
{
+ struct commands *cmd;
+ struct xfile *f;
+
unsigned long _p;
unsigned long _skip_part;
+
unsigned char _num_invalid;
unsigned char _max_invalid;
- struct xfile *f = &nv->f;
- struct commands *cmd = &nv->cmd[nv->i];
+ check_null_command("read_checksums");
+
+ cmd = &x->cmd[x->i];
+ f = &x->f;
f->part_valid[0] = 0;
f->part_valid[1] = 0;
@@ -716,35 +759,51 @@ read_checksums(void)
int
good_checksum(unsigned long partnum)
{
- unsigned short expected_checksum =
+ unsigned short expected_checksum;
+ unsigned short actual_checksum;
+
+ check_null_command("good_checksum");
+
+ expected_checksum =
calculated_checksum(partnum);
- unsigned short current_checksum =
+ actual_checksum =
nvm_word(NVM_CHECKSUM_WORD, partnum);
- return current_checksum == expected_checksum;
+ if (expected_checksum == actual_checksum) {
+ return 1;
+ } else {
+ return 0;
+ }
}
void
run_cmd(void)
{
- unsigned long cmd_num;
- struct commands *cmd;
+ unsigned long i;
+ void (*run)(void);
- cmd_num = nv->i;
- cmd = &nv->cmd[cmd_num];
+ check_null_command("run_cmd");
- check_command_num(cmd_num);
+ i = x->i;
+ run = x->cmd[i].run;
- if (cmd->run == NULL)
- err(EINVAL, "Command %lu: null ptr", cmd_num);
+ check_command_num(i);
+
+ if (run == NULL)
+ err(EINVAL, "Command %lu: null ptr", i);
+
+ run();
- cmd->run();
+ for (i = 0; i < items(x->cmd); i++)
+ x->cmd[i].run = cmd_helper_err;
}
void
check_command_num(unsigned long c)
{
+ check_null_command("check_command_num");
+
if (!valid_command(c))
err(EINVAL, "Invalid run_cmd arg: %lu",
(unsigned long)c);
@@ -755,10 +814,12 @@ valid_command(unsigned long c)
{
struct commands *cmd;
- if (c >= items(nv->cmd))
+ check_null_command("valid_command");
+
+ if (c >= items(x->cmd))
return 0;
- cmd = &nv->cmd[c];
+ cmd = &x->cmd[c];
if (c != cmd->chk)
err(EINVAL,
@@ -772,7 +833,13 @@ void
cmd_helper_setmac(void)
{
unsigned long partnum;
- struct macaddr *mac = &nv->mac;
+ struct macaddr *mac;
+
+ check_null_command("cmd_helper_setmac");
+
+ mac = &x->mac;
+
+ check_cmd(cmd_helper_setmac, "setmac");
printf("MAC address to be written: %s\n", mac->str);
parse_mac_string();
@@ -784,11 +851,15 @@ cmd_helper_setmac(void)
void
parse_mac_string(void)
{
+ struct macaddr *mac;
+
unsigned long mac_byte;
- struct macaddr *mac = &nv->mac;
+ check_null_command("parse_mac_string");
- if (xstrxlen(nv->mac.str, 18) != 17)
+ mac = &x->mac;
+
+ if (xstrxlen(x->mac.str, 18) != 17)
err(EINVAL, "MAC address is the wrong length");
memset(mac->mac_buf, 0, sizeof(mac->mac_buf));
@@ -833,11 +904,18 @@ xstrxlen(const char *scmp, unsigned long maxlen)
void
set_mac_byte(unsigned long mac_byte_pos)
{
- unsigned long mac_str_pos = mac_byte_pos * 3;
- unsigned long mac_nib_pos;
+ struct macaddr *mac;
+
char separator;
- struct macaddr *mac = &nv->mac;
+ unsigned long mac_str_pos;
+ unsigned long mac_nib_pos;
+
+ check_null_command("set_mac_byte");
+
+ mac = &x->mac;
+
+ mac_str_pos = mac_byte_pos * 3;
if (mac_str_pos < 15) {
if ((separator = mac->str[mac_str_pos + 2]) != ':')
@@ -853,10 +931,14 @@ void
set_mac_nib(unsigned long mac_str_pos,
unsigned long mac_byte_pos, unsigned long mac_nib_pos)
{
+ struct macaddr *mac;
+
char mac_ch;
unsigned short hex_num;
- struct macaddr *mac = &nv->mac;
+ check_null_command("sanitize_command_list");
+
+ mac = &x->mac;
mac_ch = mac->str[mac_str_pos + mac_nib_pos];
@@ -884,7 +966,9 @@ set_mac_nib(unsigned long mac_str_pos,
unsigned short
hextonum(char ch_s)
{
- unsigned char ch = (unsigned char)ch_s;
+ unsigned char ch;
+
+ ch = (unsigned char)ch_s;
if ((unsigned int)(ch - '0') <= 9)
return ch - '0';
@@ -903,125 +987,60 @@ hextonum(char ch_s)
unsigned long
rlong(void)
{
- struct x_st_timeval tv;
- static unsigned long mix = 0;
- static unsigned long counter = 0;
+#if (defined(__OpenBSD__) && (OpenBSD) >= 201) || \
+ defined(__FreeBSD__) || \
+ defined(__NetBSD__) || defined(__APPLE__)
- static int fd = -1;
- unsigned long rval = 0;
- long nr = -1;
+ unsigned long rval;
+ arc4random_buf(&rval, sizeof(unsigned long));
- x_i_gettimeofday(&tv, NULL);
+ return rval;
+#else
+ int fd;
- mix ^= (unsigned long)tv.tv_sec
- ^ (unsigned long)tv.tv_usec
- ^ (unsigned long)getpid()
- ^ (unsigned long)&mix
- ^ counter++
- ^ entropy_jitter();
+ long nr;
- /*
- * Stack addresses can vary between
- * calls, thus increasing entropy.
- */
- mix ^= (unsigned long)&mix;
- mix ^= (unsigned long)&tv;
- mix ^= (unsigned long)&counter;
+ unsigned long rval;
- /*
- * Now, we won't use this mix
- * immediately. We'll try to
- * read urandom first, which is
- * likely safer, and pass that,
- * falling back to the mixture
- * if urandom fails.
- *
- * Since urandom is likely
- * reliable, the number of
- * times it will fail is
- * likely extremely random,
- * thus, building more than
- * sufficient entropy by the
- * time we do eventually use
- * the fallback code
- */
-
- if (fd < 0)
- fd = open("/dev/urandom", O_RDONLY | O_BINARY | O_NONBLOCK);
+ fd = open("/dev/urandom", O_RDONLY | O_BINARY);
-#if !(defined(__OpenBSD__) && defined(OpenBSD)) || \
- (defined(__OpenBSD__) && defined(OpenBSD) && \
- OpenBSD < 604)
+#ifdef __OpenBSD__
if (fd < 0) /* old openbsd */
- fd = open("/dev/arandom", O_RDONLY | O_BINARY | O_NONBLOCK);
+ fd = open("/dev/arandom", O_RDONLY | O_BINARY);
#endif
if (fd < 0)
- fd = open("/dev/random", O_RDONLY | O_BINARY | O_NONBLOCK);
+ fd = open("/dev/random", O_RDONLY | O_BINARY);
+
+ if (fd < 0)
+ err(errno, "can't open random device");
nr = rw_file_exact(fd, (unsigned char *)&rval,
sizeof(unsigned long), 0, IO_READ, LOOP_EAGAIN,
LOOP_EINTR, MAX_ZERO_RW_RETRY, OFF_ERR);
- if (nr == sizeof(unsigned long))
- return rval;
-
- return mix;
-}
-
-unsigned long
-entropy_jitter(void)
-{
- struct x_st_timeval a, b;
- unsigned long mix = 0;
- long mix_diff;
- int i;
-
- x_i_gettimeofday(&a, NULL);
+ if (x_i_close(fd) < 0)
+ err(errno, "Can't close randomness fd");
- for (i = 0; i < 32; i++) {
- getpid();
- x_i_gettimeofday(&b, NULL);
+ if (nr != sizeof(unsigned long))
+ err(errno, "Incomplete read from random device");
- /*
- * prevent negative numbers to prevent overflow,
- * which would bias rand to large numbers
- */
- mix_diff = (long)(b.tv_usec - a.tv_usec);
- if (mix_diff < 0)
- mix_diff = -mix_diff;
-
- mix ^= (unsigned long)(mix_diff);
- mix ^= (unsigned long)&mix;
- }
-
- return mix;
-}
-
-
-
-int
-x_i_gettimeofday(struct x_st_timeval *tv, void *tz)
-{
- time_t t;
-
- (void)tz;
-
- t = time(NULL);
-
- tv->tv_sec = t;
- tv->tv_usec = (long)((unsigned long)clock() % 1000000UL);
-
- return 0;
+ return rval;
+#endif
}
void
write_mac_part(unsigned long partnum)
{
+ struct xfile *f;
+ struct macaddr *mac;
+
unsigned long w;
- struct xfile *f = &nv->f;
- struct macaddr *mac = &nv->mac;
+ check_null_command("write_mac_part");
+
+ f = &x->f;
+ mac = &x->mac;
check_bin(partnum, "part number");
if (!f->part_valid[partnum])
@@ -1038,25 +1057,36 @@ write_mac_part(unsigned long partnum)
void
cmd_helper_dump(void)
{
- unsigned long partnum;
+ struct xfile *f;
+
+ unsigned long p;
- struct xfile *f = &nv->f;
+ check_null_command("cmd_helper_dump");
+
+ f = &x->f;
+
+ check_cmd(cmd_helper_dump, "dump");
f->part_valid[0] = good_checksum(0);
f->part_valid[1] = good_checksum(1);
- for (partnum = 0; partnum < 2; partnum++) {
- if (!f->part_valid[partnum])
+ for (p = 0; p < 2; p++) {
+
+ if (!f->part_valid[p]) {
+
fprintf(stderr,
"BAD checksum %04x in part %lu (expected %04x)\n",
- nvm_word(NVM_CHECKSUM_WORD, partnum),
- (unsigned long)partnum,
- calculated_checksum(partnum));
+ nvm_word(NVM_CHECKSUM_WORD, p),
+ (unsigned long)p,
+ calculated_checksum(p));
+ }
printf("MAC (part %lu): ",
- (unsigned long)partnum);
- print_mac_from_nvm(partnum);
- hexdump(partnum);
+ (unsigned long)p);
+
+ print_mac_from_nvm(p);
+
+ hexdump(p);
}
}
@@ -1066,6 +1096,8 @@ print_mac_from_nvm(unsigned long partnum)
unsigned long c;
unsigned short val16;
+ check_null_command("print_mac_from_nvm");
+
for (c = 0; c < 3; c++) {
val16 = nvm_word(c, partnum);
printf("%02x:%02x",
@@ -1085,16 +1117,26 @@ hexdump(unsigned long partnum)
unsigned long row;
unsigned short val16;
+ check_null_command("hexdump");
+
for (row = 0; row < 8; row++) {
- printf("%08lx ", (unsigned long)((unsigned long)row << 4));
+
+ printf("%08lx ",
+ (unsigned long)((unsigned long)row << 4));
+
for (c = 0; c < 8; c++) {
+
val16 = nvm_word((row << 3) + c, partnum);
+
if (c == 4)
printf(" ");
+
printf(" %02x %02x",
(unsigned int)(val16 & 0xff),
(unsigned int)(val16 >> 8));
+
}
+
printf("\n");
}
}
@@ -1102,7 +1144,13 @@ hexdump(unsigned long partnum)
void
cmd_helper_swap(void)
{
- struct xfile *f = &nv->f;
+ struct xfile *f;
+
+ check_null_command("cmd_helper_swap");
+
+ check_cmd(cmd_helper_swap, "swap");
+
+ f = &x->f;
x_v_memcpy(
f->buf + (unsigned long)GBE_WORK_SIZE,
@@ -1126,7 +1174,13 @@ cmd_helper_swap(void)
void
cmd_helper_copy(void)
{
- struct xfile *f = &nv->f;
+ struct xfile *f;
+
+ check_null_command("cmd_helper_copy");
+
+ check_cmd(cmd_helper_copy, "copy");
+
+ f = &x->f;
x_v_memcpy(
f->buf + (unsigned long)((f->part ^ 1) * GBE_PART_SIZE),
@@ -1139,44 +1193,110 @@ cmd_helper_copy(void)
void
cmd_helper_cat(void)
{
- struct xfile *f = &nv->f;
+ check_null_command("cmd_helper_cat");
- unsigned long p = 0;
- unsigned long ff = 0;
- unsigned long nff = 0;
+ check_cmd(cmd_helper_cat, "cat");
- unsigned long cmd_num = nv->i;
+ x->cat = 0;
+ cat(0);
+}
- fflush(NULL);
+void
+cmd_helper_cat16(void)
+{
+ check_null_command("cmd_helper_cat16");
- memset(f->pad, 0xff, GBE_PART_SIZE);
+ check_cmd(cmd_helper_cat16, "cat16");
- switch (cmd_num) {
- case CMD_CAT:
- nff = 0;
- break;
- case CMD_CAT16:
- nff = 1;
- break;
- case CMD_CAT128:
- nff = 15;
- break;
- default:
- err(EINVAL, "erroneous call to cat");
+ x->cat = 1;
+ cat(1);
+}
+
+void
+cmd_helper_cat128(void)
+{
+ check_null_command("cmd_helper_cat128");
+
+ check_cmd(cmd_helper_cat128, "cat128");
+
+ x->cat = 15;
+ cat(15);
+}
+
+void
+check_cmd(void (*fn)(void),
+ const char *name)
+{
+ unsigned long i;
+
+ check_null_command("check_cmd");
+
+ if (x->cmd[x->i].run != fn)
+ err(ECANCELED, "Running %s, but cmd %s is set",
+ name, x->cmd[x->i].str);
+
+ /*
+ * In addition to making sure we ran
+ * the right command, we now disable
+ * all commands from running again
+ *
+ * the _nop function will just call
+ * err() immediately
+ */
+
+ for (i = 0; i < items(x->cmd); i++)
+ x->cmd[i].run = cmd_helper_err;
+}
+
+void
+cmd_helper_err(void)
+{
+ err(ECANCELED,
+ "Erroneously running command twice");
+}
+
+void
+cat(unsigned long nff)
+{
+ struct xfile *f;
+
+ unsigned long p;
+ unsigned long ff;
+
+ check_null_command("cat");
+
+ f = &x->f;
+
+ p = 0;
+ ff = 0;
+
+ if ((unsigned long)x->cat != nff) {
+
+ err(ECANCELED, "erroneous call to cat");
}
+ fflush(NULL);
+
+ memset(f->pad, 0xff, GBE_PART_SIZE);
+
for (p = 0; p < 2; p++) {
+
cat_buf(f->bufcmp +
(unsigned long)(p * (f->gbe_file_size >> 1)));
- for (ff = 0; ff < nff; ff++)
+ for (ff = 0; ff < nff; ff++) {
+
cat_buf(f->pad);
+ }
}
}
void
cat_buf(unsigned char *b)
{
+ if (b == NULL)
+ err(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)
@@ -1186,16 +1306,21 @@ cat_buf(unsigned char *b)
void
write_gbe_file(void)
{
+ struct commands *cmd;
+ struct xfile *f;
+
struct stat _gbe_st;
struct stat _tmp_st;
unsigned long p;
unsigned char update_checksum;
- struct commands *cmd = &nv->cmd[nv->i];
- struct xfile *f = &nv->f;
+ check_null_command("write_gbe_file");
+
+ cmd = &x->cmd[x->i];
+ f = &x->f;
- if (cmd->flags == O_RDONLY)
+ if ((cmd->flags & O_ACCMODE) == O_RDONLY)
return;
if (fstat(f->gbe_fd, &_gbe_st) == -1)
@@ -1232,6 +1357,8 @@ write_gbe_file(void)
void
set_checksum(unsigned long p)
{
+ check_null_command("set_checksum");
+
check_bin(p, "part number");
set_nvm_word(NVM_CHECKSUM_WORD, p, calculated_checksum(p));
}
@@ -1240,7 +1367,11 @@ unsigned short
calculated_checksum(unsigned long p)
{
unsigned long c;
- unsigned int val16 = 0;
+ unsigned int val16;
+
+ check_null_command("calculated_checksum");
+
+ val16 = 0;
for (c = 0; c < NVM_CHECKSUM_WORD; c++)
val16 += (unsigned int)nvm_word(c, p);
@@ -1259,10 +1390,14 @@ calculated_checksum(unsigned long p)
unsigned short
nvm_word(unsigned long pos16, unsigned long p)
{
- struct xfile *f = &nv->f;
+ struct xfile *f;
unsigned long pos;
+ check_null_command("nvm_word");
+
+ f = &x->f;
+
check_nvm_bound(pos16, p);
pos = (pos16 << 1) + (p * GBE_PART_SIZE);
@@ -1273,9 +1408,14 @@ nvm_word(unsigned long pos16, unsigned long p)
void
set_nvm_word(unsigned long pos16, unsigned long p, unsigned short val16)
{
- struct xfile *f = &nv->f;
+ struct xfile *f;
+
unsigned long pos;
+ check_null_command("set_nvm_word");
+
+ f = &x->f;
+
check_nvm_bound(pos16, p);
pos = (pos16 << 1) + (p * GBE_PART_SIZE);
@@ -1288,7 +1428,11 @@ set_nvm_word(unsigned long pos16, unsigned long p, unsigned short val16)
void
set_part_modified(unsigned long p)
{
- struct xfile *f = &nv->f;
+ struct xfile *f;
+
+ check_null_command("set_part_modified");
+
+ f = &x->f;
check_bin(p, "part number");
f->part_modified[p] = 1;
@@ -1303,6 +1447,8 @@ check_nvm_bound(unsigned long c, unsigned long p)
* ever modified the NVM area.
*/
+ check_null_command("check_nvm_bound");
+
check_bin(p, "part number");
if (c >= NVM_WORDS)
@@ -1322,15 +1468,20 @@ void
rw_gbe_file_part(unsigned long p, int rw_type,
const char *rw_type_str)
{
- struct xfile *f = &nv->f;
- struct commands *cmd = &nv->cmd[nv->i];
+ struct commands *cmd;
+ struct xfile *f;
- long r;
- unsigned long gbe_rw_size;
+ long rval;
+
+ off_t file_offset;
+ unsigned long gbe_rw_size;
unsigned char *mem_offset;
- off_t file_offset;
+ check_null_command("rw_gbe_file_part");
+
+ cmd = &x->cmd[x->i];
+ f = &x->f;
gbe_rw_size = cmd->rw_size;
@@ -1341,14 +1492,14 @@ rw_gbe_file_part(unsigned long p, int rw_type,
mem_offset = gbe_mem_offset(p, rw_type_str);
file_offset = (off_t)gbe_file_offset(p, rw_type_str);
- r = rw_gbe_file_exact(f->tmp_fd, mem_offset,
+ rval = rw_gbe_file_exact(f->tmp_fd, mem_offset,
gbe_rw_size, file_offset, rw_type);
- if (r == -1)
+ if (rval == -1)
err(errno, "%s: %s: part %lu",
f->fname, rw_type_str, (unsigned long)p);
- if ((unsigned long)r != gbe_rw_size)
+ if ((unsigned long)rval != gbe_rw_size)
err(EIO, "%s: partial %s: part %lu",
f->fname, rw_type_str, (unsigned long)p);
}
@@ -1356,14 +1507,18 @@ rw_gbe_file_part(unsigned long p, int rw_type,
void
write_to_gbe_bin(void)
{
- struct xfile *f = &nv->f;
+ struct commands *cmd;
+ struct xfile *f;
int saved_errno;
int mv;
- struct commands *cmd = &nv->cmd[nv->i];
+ check_null_command("write_to_gbe_bin");
- if (cmd->flags != O_RDWR)
+ cmd = &x->cmd[x->i];
+ f = &x->f;
+
+ if ((cmd->flags & O_ACCMODE) != O_RDWR)
return;
write_gbe_file();
@@ -1448,16 +1603,23 @@ write_to_gbe_bin(void)
void
check_written_part(unsigned long p)
{
- struct commands *cmd = &nv->cmd[nv->i];
- struct xfile *f = &nv->f;
+ struct commands *cmd;
+ struct xfile *f;
+
+ long rval;
unsigned long gbe_rw_size;
- unsigned char *mem_offset;
+
off_t file_offset;
- unsigned char *buf_restore;
+ unsigned char *mem_offset;
+
struct stat st;
+ unsigned char *buf_restore;
- long r;
+ check_null_command("check_written_part");
+
+ cmd = &x->cmd[x->i];
+ f = &x->f;
if (!f->part_modified[p])
return;
@@ -1479,12 +1641,12 @@ check_written_part(unsigned long p)
if (st.st_dev != f->tmp_dev || st.st_ino != f->tmp_ino)
err(EIO, "%s: file changed during write", f->tname);
- r = rw_gbe_file_exact(f->tmp_fd, f->pad,
+ rval = rw_gbe_file_exact(f->tmp_fd, f->pad,
gbe_rw_size, file_offset, IO_PREAD);
- if (r == -1)
+ if (rval == -1)
f->rw_check_err_read[p] = f->io_err_gbe = 1;
- else if ((unsigned long)r != gbe_rw_size)
+ else if ((unsigned long)rval != gbe_rw_size)
f->rw_check_partial_read[p] = f->io_err_gbe = 1;
else if (x_i_memcmp(mem_offset, f->pad, gbe_rw_size) != 0)
f->rw_check_bad_part[p] = f->io_err_gbe = 1;
@@ -1499,18 +1661,30 @@ check_written_part(unsigned long p)
* That's why we hardcode good_checksum(0).
*/
buf_restore = f->buf;
+
+ /*
+ * good_checksum works on f->buf
+ * so let's change f->buf for now
+ */
f->buf = f->pad;
- f->post_rw_checksum[p] = good_checksum(0);
+
+ if (good_checksum(0))
+ f->post_rw_checksum[p] = 1;
+
f->buf = buf_restore;
}
void
report_io_err_rw(void)
{
- struct xfile *f = &nv->f;
+ struct xfile *f;
unsigned long p;
+ check_null_command("report_io_err_rw");
+
+ f = &x->f;
+
if (!f->io_err_gbe)
return;
@@ -1562,20 +1736,31 @@ report_io_err_rw(void)
int
gbe_mv(void)
{
- struct xfile *f = &nv->f;
+ struct xfile *f;
+
+ int rval;
- int r;
int saved_errno;
- int tmp_gbe_bin_exists = 1;
+ int tmp_gbe_bin_exists;
+
+ char *dest_tmp;
+ int dest_fd;
+
+ check_null_command("gbe_mv");
- char *dest_tmp = NULL;
- int dest_fd = -1;
+ f = &x->f;
+
+ /* will be set 0 if it doesn't */
+ tmp_gbe_bin_exists = 1;
+
+ dest_tmp = NULL;
+ dest_fd = -1;
saved_errno = errno;
- r = rename(f->tname, f->fname);
+ rval = rename(f->tname, f->fname);
- if (r > -1) {
+ if (rval > -1) {
/*
* same filesystem
*/
@@ -1584,7 +1769,7 @@ gbe_mv(void)
if (fsync_dir(f->fname) < 0) {
f->io_err_gbe_bin = 1;
- r = -1;
+ rval = -1;
}
goto ret_gbe_mv;
@@ -1595,7 +1780,7 @@ gbe_mv(void)
/* cross-filesystem rename */
- if ((r = f->tmp_fd = open(f->tname,
+ if ((rval = f->tmp_fd = open(f->tname,
O_RDONLY | O_BINARY)) == -1)
goto ret_gbe_mv;
@@ -1606,20 +1791,20 @@ gbe_mv(void)
/* copy data */
- r = rw_file_exact(f->tmp_fd, f->bufcmp,
+ 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 (r < 0)
+ if (rval < 0)
goto ret_gbe_mv;
- r = rw_file_exact(dest_fd, f->bufcmp,
+ 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 (r < 0)
+ if (rval < 0)
goto ret_gbe_mv;
if (x_i_fsync(dest_fd) == -1)
@@ -1643,17 +1828,17 @@ ret_gbe_mv:
if (f->gbe_fd > -1) {
if (x_i_close(f->gbe_fd) < 0)
- r = -1;
+ rval = -1;
if (fsync_dir(f->fname) < 0) {
f->io_err_gbe_bin = 1;
- r = -1;
+ rval = -1;
}
f->gbe_fd = -1;
}
if (f->tmp_fd > -1) {
if (x_i_close(f->tmp_fd) < 0)
- r = -1;
+ rval = -1;
f->tmp_fd = -1;
}
@@ -1664,12 +1849,12 @@ ret_gbe_mv:
*/
if (tmp_gbe_bin_exists) {
if (unlink(f->tname) < 0)
- r = -1;
+ rval = -1;
else
tmp_gbe_bin_exists = 0;
}
- if (r < 0) {
+ if (rval < 0) {
/*
* if nothing set errno,
* we assume EIO, or we
@@ -1681,7 +1866,7 @@ ret_gbe_mv:
errno = saved_errno;
}
- return r;
+ return rval;
}
/*
@@ -1691,21 +1876,27 @@ ret_gbe_mv:
int
fsync_dir(const char *path)
{
-#if defined(PATH_LEN) && \
- (PATH_LEN) >= 256
- unsigned long maxlen = PATH_LEN;
-#else
- unsigned long maxlen = 1024;
-#endif
+ int saved_errno = errno;
+
unsigned long pathlen;
-/* char dirbuf[maxlen]; */
- char *dirbuf = NULL;
+ unsigned long maxlen;
+
+ char *dirbuf;
+ int dirfd;
+
char *slash;
- int dfd = -1;
struct stat st;
- int saved_errno = errno;
+#if defined(PATH_LEN) && \
+ (PATH_LEN) >= 256
+ maxlen = PATH_LEN;
+#else
+ maxlen = 1024;
+#endif
+
+ dirbuf = NULL;
+ dirfd = -1;
pathlen = xstrxlen(path, maxlen);
@@ -1738,7 +1929,7 @@ fsync_dir(const char *path)
dirbuf[1] = '\0';
}
- dfd = open(dirbuf, O_RDONLY
+ dirfd = open(dirbuf, O_RDONLY
#ifdef O_DIRECTORY
| O_DIRECTORY
#endif
@@ -1746,10 +1937,10 @@ fsync_dir(const char *path)
| O_NOFOLLOW
#endif
);
- if (dfd == -1)
+ if (dirfd == -1)
goto err_fsync_dir;
- if (fstat(dfd, &st) < 0)
+ if (fstat(dirfd, &st) < 0)
goto err_fsync_dir;
if (!S_ISDIR(st.st_mode)) {
@@ -1758,10 +1949,10 @@ fsync_dir(const char *path)
}
/* sync file on disk */
- if (x_i_fsync(dfd) == -1)
+ if (x_i_fsync(dirfd) == -1)
goto err_fsync_dir;
- if (x_i_close(dfd) == -1)
+ if (x_i_close(dirfd) == -1)
goto err_fsync_dir;
if (dirbuf != NULL)
@@ -1780,8 +1971,8 @@ err_fsync_dir:
if (dirbuf != NULL)
free(dirbuf);
- if (dfd > -1)
- x_i_close(dfd);
+ if (dirfd > -1)
+ x_i_close(dirfd);
errno = saved_errno;
@@ -1796,12 +1987,19 @@ err_fsync_dir:
unsigned char *
gbe_mem_offset(unsigned long p, const char *f_op)
{
- struct xfile *f = &nv->f;
+ struct xfile *f;
+
+ off_t gbe_off;
- off_t gbe_off = gbe_x_offset(p, f_op, "mem",
+ check_null_command("gbe_mem_offset");
+
+ f = &x->f;
+
+ gbe_off = gbe_x_offset(p, f_op, "mem",
GBE_PART_SIZE, GBE_WORK_SIZE);
- return (unsigned char *)(f->buf + (unsigned long)gbe_off);
+ return (unsigned char *)
+ (f->buf + (unsigned long)gbe_off);
}
/*
@@ -1814,9 +2012,15 @@ gbe_mem_offset(unsigned long p, const char *f_op)
off_t
gbe_file_offset(unsigned long p, const char *f_op)
{
- struct xfile *f = &nv->f;
+ struct xfile *f;
- off_t gbe_file_half_size = f->gbe_file_size >> 1;
+ off_t gbe_file_half_size;
+
+ check_null_command("gbe_file_offset");
+
+ f = &x->f;
+
+ gbe_file_half_size = f->gbe_file_size >> 1;
return gbe_x_offset(p, f_op, "file",
gbe_file_half_size, f->gbe_file_size);
@@ -1826,12 +2030,16 @@ off_t
gbe_x_offset(unsigned long p, const char *f_op, const char *d_type,
off_t nsize, off_t ncmp)
{
- struct xfile *f = &nv->f;
+ struct xfile *f;
off_t off;
+ check_null_command("gbe_x_offset");
+
check_bin(p, "part number");
+ f = &x->f;
+
off = ((off_t)p) * (off_t)nsize;
if (off > ncmp - GBE_PART_SIZE)
@@ -1849,10 +2057,14 @@ long
rw_gbe_file_exact(int fd, unsigned char *mem, unsigned long nrw,
off_t off, int rw_type)
{
- struct xfile *f = &nv->f;
+ struct xfile *f;
long r;
+ check_null_command("rw_gbe_file_exact");
+
+ f = &x->f;
+
if (io_args(fd, mem, nrw, off, rw_type) == -1)
return -1;
@@ -1884,6 +2096,26 @@ err_rw_gbe_file_exact:
return -1;
}
+void
+check_null_command(const char *c)
+{
+ char msg[] = "undefined function name";
+ char *func_name = msg;
+
+ if (c != NULL) {
+
+ if (*c != '\0') {
+
+ func_name = (char *)c;
+ }
+ }
+
+ if (x == NULL) {
+
+ err(ECANCELED, "%s: x ptr is null", func_name);
+ }
+}
+
/*
* Safe I/O functions wrapping around
* read(), write() and providing a portable
@@ -1920,23 +2152,31 @@ rw_file_exact(int fd, unsigned char *mem, unsigned long nrw,
int loop_eintr, unsigned long max_retries,
int off_reset)
{
- long rv = 0;
- long rc = 0;
- unsigned long retries_on_zero = 0;
- off_t off_cur;
+ long rval;
+ long rc;
+
unsigned long nrw_cur;
+
+ off_t off_cur;
void *mem_cur;
+ unsigned long retries_on_zero;
+
+ rval = 0;
+
+ rc = 0;
+ retries_on_zero = 0;
+
if (io_args(fd, mem, nrw, off, rw_type) == -1)
return -1;
while (1) {
/* Prevent theoretical overflow */
- if (rv >= 0 && (unsigned long)rv > (nrw - rc))
+ if (rval >= 0 && (unsigned long)rval > (nrw - rc))
goto err_rw_file_exact;
- rc += rv;
+ rc += rval;
if ((unsigned long)rc >= nrw)
break;
@@ -1946,14 +2186,14 @@ rw_file_exact(int fd, unsigned char *mem, unsigned long nrw,
goto err_rw_file_exact;
off_cur = off + (off_t)rc;
- rv = prw(fd, mem_cur, nrw_cur, off_cur,
+ rval = prw(fd, mem_cur, nrw_cur, off_cur,
rw_type, loop_eagain, loop_eintr,
off_reset);
- if (rv < 0)
+ if (rval < 0)
return -1;
- if (rv == 0) {
+ if (rval == 0) {
if (retries_on_zero++ < max_retries)
continue;
goto err_rw_file_exact;
@@ -2020,6 +2260,12 @@ prw(int fd, void *mem, unsigned long nrw,
int loop_eagain, int loop_eintr,
int off_reset)
{
+#ifndef MAX_EAGAIN_RETRIES
+ unsigned long retries = 100000;
+#else
+ unsigned long retries = MAX_EAGAIN_RETRIES;
+#endif
+
long r;
int positional_rw;
struct stat st;
@@ -2031,8 +2277,10 @@ prw(int fd, void *mem, unsigned long nrw,
off_t off_last;
#endif
- if (io_args(fd, mem, nrw, off, rw_type) == -1)
+ if (io_args(fd, mem, nrw, off, rw_type)
+ == -1) {
return -1;
+ }
r = -1;
@@ -2145,8 +2393,9 @@ real_pread_pwrite:
}
} while (r == -1 &&
- (errno == try_err(loop_eintr, EINTR)
- || errno == try_err(loop_eagain, EAGAIN)));
+ (errno == try_err(loop_eintr, EINTR) ||
+ errno == try_err(loop_eagain, EAGAIN)) &&
+ retries++ < MAX_EAGAIN_RETRIES);
}
saved_errno = errno;
@@ -2243,7 +2492,9 @@ rw_over_nrw(long r, unsigned long nrw)
if (r == -1)
return r;
- if ((unsigned long)r > X_LONG_MAX) {
+ if ((unsigned long)
+ r > X_LONG_MAX) {
+
/*
* Theoretical buggy libc
* check. Extremely academic.
@@ -2286,7 +2537,9 @@ off_t
lseek_loop(int fd, off_t off, int whence,
int loop_eagain, int loop_eintr)
{
- off_t old = -1;
+ off_t old;
+
+ old = -1;
do {
old = lseek(fd, off, whence);
@@ -2319,7 +2572,9 @@ try_err(int loop_err, int errval)
void
usage(void)
{
- const char *util = getnvmprogname();
+ const char *util;
+
+ util = getnvmprogname();
fprintf(stderr,
"Modify Intel GbE NVM images e.g. set MAC\n"
@@ -2340,8 +2595,6 @@ usage(void)
void
err(int nvm_errval, const char *msg, ...)
{
- struct xfile *f = &nv->f;
-
va_list args;
if (errno == 0)
@@ -2351,18 +2604,14 @@ err(int nvm_errval, const char *msg, ...)
(void)exit_cleanup();
- fprintf(stderr, "%s: ", getnvmprogname());
+ if (x != NULL)
+ fprintf(stderr, "%s: ", getnvmprogname());
va_start(args, msg);
vfprintf(stderr, msg, args);
va_end(args);
- fprintf(stderr, ": %s", strerror(errno));
-
- fprintf(stderr, "\n");
-
- if (f->tname != NULL)
- free(f->tname);
+ fprintf(stderr, ": %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
@@ -2370,28 +2619,35 @@ err(int nvm_errval, const char *msg, ...)
int
exit_cleanup(void)
{
- struct xfile *f = &nv->f;
+ struct xfile *f;
- int close_err = 0;
- int saved_errno = errno;
+ int close_err;
+ int saved_errno;
- if (f->gbe_fd > -1) {
- if (x_i_close(f->gbe_fd) == -1)
- close_err = 1;
- f->gbe_fd = -1;
- }
+ close_err = 0;
+ saved_errno = errno;
- if (f->tmp_fd > -1) {
- if (x_i_close(f->tmp_fd) == -1)
- close_err = 1;
- }
+ if (x != NULL) {
+ f = &x->f;
- if (f->tname != NULL) {
- if (unlink(f->tname) == -1)
- close_err = 1;
- }
+ if (f->gbe_fd > -1) {
+ if (x_i_close(f->gbe_fd) == -1)
+ close_err = 1;
+ f->gbe_fd = -1;
+ }
- f->tmp_fd = -1;
+ if (f->tmp_fd > -1) {
+ if (x_i_close(f->tmp_fd) == -1)
+ close_err = 1;
+ }
+
+ if (f->tname != NULL) {
+ if (unlink(f->tname) == -1)
+ close_err = 1;
+ }
+
+ f->tmp_fd = -1;
+ }
if (saved_errno)
errno = saved_errno;
@@ -2406,16 +2662,23 @@ const char *
getnvmprogname(void)
{
const char *p;
+ static char fallback[] = "nvmutil";
+
+ char *rval = fallback;
- if (nv->argv0 == NULL || *nv->argv0 == '\0')
- return "";
+ if (x != NULL) {
+ if (x->argv0 == NULL || *x->argv0 == '\0')
+ return "";
- p = x_c_strrchr(nv->argv0, '/');
+ rval = x->argv0;
+ }
+
+ p = x_c_strrchr(rval, '/');
if (p)
return p + 1;
else
- return nv->argv0;
+ return rval;
}
/*
@@ -2445,8 +2708,6 @@ getnvmprogname(void)
char *
new_tmpfile(int *fd, int local, const char *path)
{
- struct xfile *f = &nv->f;
-
unsigned long maxlen;
struct stat st;
@@ -2508,7 +2769,7 @@ new_tmpfile(int *fd, int local, const char *path)
/*
* appended to filename for tmp:
*/
- tmpdir_len = sizeof(default_tmpname);
+ tmpdir_len = xstrxlen(default_tmpname, maxlen);
} else {
base = x_c_tmpdir();
@@ -2560,10 +2821,23 @@ new_tmpfile(int *fd, int local, const char *path)
if (fd_tmp == -1)
goto err_new_tmpfile;
- if (x_i_fchmod(fd_tmp, 0600) == -1)
+ if (fchmod(fd_tmp, 0600) == -1)
goto err_new_tmpfile;
- if (lock_file(fd_tmp) == -1)
+ flags = fcntl(fd_tmp, F_GETFL);
+
+ if (flags == -1)
+ goto err_new_tmpfile;
+
+ /*
+ * O_APPEND would permit offsets
+ * to be ignored, which breaks
+ * positional read/write
+ */
+ if (flags & O_APPEND)
+ goto err_new_tmpfile;
+
+ if (lock_file(fd_tmp, flags) == -1)
goto err_new_tmpfile;
if (fstat(fd_tmp, &st) == -1)
@@ -2582,10 +2856,6 @@ new_tmpfile(int *fd, int local, const char *path)
if (lseek(fd_tmp, 0, SEEK_CUR) == (off_t)-1)
goto err_new_tmpfile;
- /* inode will be checked later on write */
- f->tmp_dev = st.st_dev;
- f->tmp_ino = st.st_ino;
-
/* tmpfile has >1 hardlinks */
if (st.st_nlink > 1)
goto err_new_tmpfile;
@@ -2594,19 +2864,6 @@ new_tmpfile(int *fd, int local, const char *path)
if (st.st_nlink == 0)
goto err_new_tmpfile;
- flags = fcntl(fd_tmp, F_GETFL);
-
- if (flags == -1)
- goto err_new_tmpfile;
-
- /*
- * O_APPEND would permit offsets
- * to be ignored, which breaks
- * positional read/write
- */
- if (flags & O_APPEND)
- goto err_new_tmpfile;
-
*fd = fd_tmp;
return dest;
@@ -2633,7 +2890,9 @@ x_i_mkstemp(char *template)
unsigned long len;
char *p;
- char ch[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+ char ch[] =
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+
unsigned long r;
len = xstrxlen(template, PATH_LEN);
@@ -2648,7 +2907,7 @@ x_i_mkstemp(char *template)
for (j = 0; j < 6; j++) {
r = rlong();
- p[j] = ch[r % (sizeof(ch) - 1)];
+ p[j] = ch[(unsigned long)(r >> 1) % (sizeof(ch) - 1)];
}
fd = open(template, O_RDWR | O_CREAT | O_EXCL, 0600);
@@ -2692,7 +2951,7 @@ x_c_strrchr(const char *s, int c)
int
x_i_rename(const char *src, const char *dst)
{
- int sfd, dfd;
+ int sfd, dirfd;
ssize_t r;
char buf[8192];
@@ -2700,31 +2959,31 @@ x_i_rename(const char *src, const char *dst)
if (sfd < 0)
return -1;
- dfd = open(dst, O_WRONLY | O_CREAT | O_TRUNC, 0600);
- if (dfd < 0) {
+ dirfd = open(dst, O_WRONLY | O_CREAT | O_TRUNC, 0600);
+ if (dirfd < 0) {
x_i_close(sfd);
return -1;
}
while ((r = read(sfd, buf, sizeof(buf))) > 0) {
- ssize_t w = write(dfd, buf, r);
+ ssize_t w = write(dirfd, buf, r);
if (w != r) {
x_i_close(sfd);
- x_i_close(dfd);
+ x_i_close(dirfd);
return -1;
}
}
if (r < 0) {
x_i_close(sfd);
- x_i_close(dfd);
+ x_i_close(dirfd);
return -1;
}
- x_i_fsync(dfd);
+ x_i_fsync(dirfd);
x_i_close(sfd);
- x_i_close(dfd);
+ x_i_close(dirfd);
if (unlink(src) < 0)
return -1;
@@ -2740,9 +2999,13 @@ x_c_tmpdir(void)
struct stat st;
t = getenv("TMPDIR");
+ t = getenv("TMPDIR");
if (t && *t) {
- if (stat(t, &st) == 0 && S_ISDIR(st.st_mode))
+ if (stat(t, &st) == 0 && S_ISDIR(st.st_mode)) {
+ if ((st.st_mode & S_IWOTH) && !(st.st_mode & S_ISVTX))
+ return NULL;
return t;
+ }
}
if (stat("/tmp", &st) == 0 && S_ISDIR(st.st_mode))
@@ -2758,11 +3021,15 @@ int
x_i_close(int fd)
{
int r;
+ int saved_errno = errno;
do {
r = close(fd);
} while (r == -1 && errno == EINTR);
+ if (r > -1)
+ errno = saved_errno;
+
return r;
}
@@ -2784,90 +3051,13 @@ x_i_memcmp(const void *a, const void *b, unsigned long n)
const unsigned char *pa = (const unsigned char *)a;
const unsigned char *pb = (const unsigned char *)b;
- while (n--) {
+ for ( ; n--; ++pa, ++pb)
if (*pa != *pb)
return *pa - *pb;
- pa++;
- pb++;
- }
return 0;
}
-/*
- * emulate fchmod() using file descriptor
- * paths, for old unix portability. should
- * work on e.g. BSD/MacOS (/dev/fd/N),
- * Linux (/proc/self/fd/N) and others
- */
-int
-x_i_fchmod(int fd, mode_t mode)
-{
- if (x_try_fdpath("/dev/fd/", fd, mode) == 0)
- return 0;
-
- if (x_try_fdpath("/proc/self/fd/", fd, mode) == 0)
- return 0;
-
- errno = ENOSYS;
- return -1;
-}
-
-int
-x_try_fdpath(const char *prefix, int fd, mode_t mode)
-{
- char path[PATH_LEN];
-
- unsigned long i = 0;
- unsigned long j;
-
- struct stat st;
-
- while (prefix[i]) {
- if (i >= PATH_LEN - 1)
- return -1;
- path[i] = prefix[i];
- i++;
- }
-
- j = x_conv_fd(path + i, (unsigned long)fd);
-
- if (i + j >= PATH_LEN)
- return -1;
-
- i += j;
- path[i] = '\0';
-
- if (stat(path, &st) < 0)
- return -1;
-
- return chmod(path, mode);
-}
-
-unsigned long
-x_conv_fd(char *buf, unsigned long n)
-{
- char tmp[256];
-
- unsigned long i = 0;
- unsigned long j = 0;
-
- if (n == 0) {
- buf[0] = '0';
- return 1;
- }
-
- while (n > 0) {
- tmp[i++] = (char)('0' + (n % 10));
- n /= 10;
- }
-
- while (i > 0)
- buf[j++] = tmp[--i];
-
- return j;
-}
-
int
x_i_fsync(int fd)
{
diff --git a/util/nvmutil/nvmutil.h b/util/nvmutil/nvmutil.h
index 831c161a..4d8c3ab2 100644
--- a/util/nvmutil/nvmutil.h
+++ b/util/nvmutil/nvmutil.h
@@ -4,6 +4,16 @@
* Copyright (c) 2022-2026 Leah Rowe <leah@libreboot.org>
*/
+/* Use this shorthand in cmd helpers. e.g.
+ in cmd_setmac function:
+ check_cmd(cmd_helper_cat);
+*/
+
+/*
+ * system prototypes
+ */
+int fchmod(int fd, mode_t mode);
+
#ifndef NVMUTIL_H
#define NVMUTIL_H
@@ -18,6 +28,14 @@
#define OFF_RESET 1
#endif
+#ifndef S_ISVTX
+#define S_ISVTX 01000
+#endif
+
+#if defined(S_IFMT) && ((S_ISVTX & S_IFMT) != 0)
+#error "Unexpected bit layout"
+#endif
+
#ifndef MAX_ZERO_RW_RETRY
#define MAX_ZERO_RW_RETRY 5
#endif
@@ -26,6 +44,10 @@
#define HAVE_REAL_PREAD_PWRITE 0
#endif
+#ifndef MAX_EAGAIN_RETRIES
+#define MAX_EAGAIN_RETRIES 100000
+#endif
+
#ifndef LOOP_EAGAIN
#define LOOP_EAGAIN 1
#endif
@@ -66,6 +88,10 @@
#define EXIT_SUCCESS 0
#endif
+#ifndef O_ACCMODE
+#define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
+#endif
+
#ifndef O_BINARY
#define O_BINARY 0
#endif
@@ -206,14 +232,6 @@
#define SKIP_CHECKSUM_WRITE 0
#define CHECKSUM_WRITE 1
-/*
- * portable timeval
- */
-struct x_st_timeval {
- long tv_sec;
- long tv_usec;
-};
-
struct commands {
unsigned long chk;
char *str;
@@ -286,6 +304,10 @@ struct xstate {
/* store size of a struct here.
(can be used to copy old state) */
unsigned long xsize;
+
+ /* Cat commands set this.
+ the cat cmd helpers check it */
+ int cat;
};
@@ -311,7 +333,7 @@ int xstrxcmp(const char *a, const char *b, unsigned long maxlen);
* Prep files for reading
*/
void open_gbe_file(void);
-int lock_file(int fd);
+int lock_file(int fd, int flags);
void xopen(int *fd, const char *path, int flags, struct stat *st);
/*
@@ -344,8 +366,6 @@ void set_mac_nib(unsigned long mac_str_pos,
unsigned long mac_byte_pos, unsigned long mac_nib_pos);
unsigned short hextonum(char ch_s);
unsigned long rlong(void);
-unsigned long entropy_jitter(void);
-int x_i_gettimeofday(struct x_st_timeval *tv, void *tz);
void write_mac_part(unsigned long partnum);
/*
@@ -370,8 +390,14 @@ void cmd_helper_copy(void);
* cat, cat16 and cat128
*/
void cmd_helper_cat(void);
+void cmd_helper_cat16(void);
+void cmd_helper_cat128(void);
+void cat(unsigned long nff);
void cat_buf(unsigned char *b);
+void check_cmd(void (*fn)(void), const char *name);
+void cmd_helper_err(void);
+
/*
* After command processing, write
* the modified GbE file back.
@@ -411,6 +437,7 @@ off_t gbe_x_offset(unsigned long part, const char *f_op,
const char *d_type, off_t nsize, off_t ncmp);
long rw_gbe_file_exact(int fd, unsigned char *mem, unsigned long nrw,
off_t off, int rw_type);
+void check_null_command(const char *c);
long rw_file_exact(int fd, unsigned char *mem, unsigned long len,
off_t off, int rw_type, int loop_eagain, int loop_eintr,
unsigned long max_retries, int off_reset);
@@ -455,11 +482,6 @@ void *x_v_memcpy(void *dst,
const void *src, unsigned long n);
int x_i_memcmp(const void *a,
const void *b, unsigned long n);
-int x_i_fchmod(int fd, mode_t mode);
-int x_try_fdpath(const char *prefix,
- int fd, mode_t mode);
-unsigned long x_conv_fd(char *buf,
- unsigned long n);
int x_i_fsync(int fd);