summaryrefslogtreecommitdiff
path: root/util/nvmutil/nvmutil.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/nvmutil/nvmutil.c')
-rw-r--r--util/nvmutil/nvmutil.c436
1 files changed, 245 insertions, 191 deletions
diff --git a/util/nvmutil/nvmutil.c b/util/nvmutil/nvmutil.c
index f39cd65f..b6e28cfa 100644
--- a/util/nvmutil/nvmutil.c
+++ b/util/nvmutil/nvmutil.c
@@ -22,53 +22,56 @@
#if defined(__OpenBSD__) || defined(__FreeBSD__) || \
defined(__NetBSD__) || defined(__APPLE__) || \
defined(__DragonFly__)
-#ifndef HAVE_ARC4RANDOM
-#define HAVE_ARC4RANDOM
+#ifndef HAVE_ARC4RANDOM_BUF
+#define HAVE_ARC4RANDOM_BUF
#endif
#endif
-static void reset_global_state(void);
-static void set_cmd(int, char **);
-static void check_cmd_args(int, char **);
-static void set_io_flags(int, char **);
+static void set_cmd(int argc, char *argv[]);
+static void check_cmd_args(int argc, char *argv[]);
+static size_t conv_argv_part_num(const char *part_str);
+static void set_io_flags(int argc, char *argv[]);
static void open_gbe_file(void);
-#ifndef HAVE_ARC4RANDOM
+#ifndef HAVE_ARC4RANDOM_BUF
static void open_dev_urandom(void);
#endif
-static void xopen(int *, const char *, int, struct stat *);
-static void read_gbe(void);
-static void read_gbe_part(size_t, unsigned char);
+static void xopen(int *fd, const char *path, int flags, struct stat *st);
+static void read_gbe_file(void);
+static void read_gbe_file_part(size_t part, uint8_t invert);
static void cmd_setmac(void);
static void parse_mac_string(void);
-static void set_mac_byte(size_t);
-static void check_mac_separator(size_t);
-static void set_mac_nib(size_t, size_t);
-static uint8_t hextonum(char);
-static uint8_t rhex(void);
-static void read_file_exact(int, void *, size_t,
- off_t, const char *, const char *);
-static int write_mac_part(size_t);
+static void set_mac_byte(size_t mac_byte_pos);
+static void set_mac_nib(size_t mac_str_pos,
+ size_t mac_byte_pos, size_t mac_nib_pos);
+static uint16_t hextonum(char ch_s);
+static uint16_t rhex(void);
+static void read_file_exact(int fd, void *buf, size_t len,
+ off_t off, const char *path, const char *op);
+static int write_mac_part(size_t partnum);
static void cmd_dump(void);
-static void print_mac_address(size_t);
-static void hexdump(size_t);
+static void print_mac_address(size_t partnum);
+static void hexdump(size_t partnum);
static void cmd_setchecksum(void);
-static void set_checksum(size_t);
+static void set_checksum(size_t part);
static void cmd_brick(void);
static void cmd_copy(void);
static void cmd_swap(void);
-static int good_checksum(size_t);
-static uint16_t word(size_t, size_t);
-static void set_word(size_t, size_t, uint16_t);
-static void check_bound(size_t, size_t);
-static void write_gbe(void);
-static void write_gbe_part(size_t);
-static off_t gbe_file_offset(size_t, const char *);
-static void *gbe_mem_offset(size_t, const char *);
-static off_t gbe_x_offset(size_t, const char *, const char *, off_t, off_t);
+static int good_checksum(size_t partnum);
+static uint16_t word(size_t pos16, size_t part);
+static void set_word(size_t pos16, size_t part, uint16_t val16);
+static void check_nvm_bound(size_t pos16, size_t part);
+static void write_gbe_file(void);
+static void write_gbe_file_part(size_t part);
+static off_t gbe_file_offset(size_t part, const char *f_op);
+static void *gbe_mem_offset(size_t part, const char *f_op);
+static off_t gbe_x_offset(size_t part, const char *f_op,
+ const char *d_type, off_t nsize, off_t ncmp);
+static void set_part_modified(size_t p);
+static void check_part_num(size_t p);
static void usage(void);
-static void err(int, const char *, ...);
+static void err(int nvm_errval, const char *msg, ...);
static const char *getnvmprogname(void);
-static void set_err(int);
+static void set_err(int errval);
/*
* Sizes in bytes:
@@ -105,34 +108,43 @@ static void set_err(int);
#define MAX_RETRY_READ 30
/*
- * Portably macro based on BSD nitems.
+ * Portable macro based on BSD nitems.
* Used to count the number of commands (see below).
*/
#define items(x) (sizeof((x)) / sizeof((x)[0]))
static const char newrandom[] = "/dev/urandom";
static const char oldrandom[] = "/dev/random"; /* fallback on OLD unix */
-#ifndef HAVE_ARC4RANDOM
+#ifndef HAVE_ARC4RANDOM_BUF
static const char *rname = NULL;
#endif
-static uint8_t buf[GBE_FILE_SIZE]; /* 8KB */
+/*
+ * GbE files can be 8KB, 16KB or 128KB,
+ * but we only need the two 4KB parts
+ * from offset zero and offset 64KB in
+ * a 128KB file, or zero and 8KB in a 16KB
+ * file, or zero and 4KB in an 8KB file.
+ *
+ * The code will handle this properly.
+ */
+static uint8_t buf[GBE_FILE_SIZE];
+
static uint16_t mac_buf[3];
-static off_t partsize;
+static off_t gbe_file_size;
-static int flags;
-#ifndef HAVE_ARC4RANDOM
-static int rfd = -1;
+static int gbe_flags;
+#ifndef HAVE_ARC4RANDOM_BUF
+static int urandom_fd = -1;
#endif
-static int fd = -1;
-static struct stat st;
+static int gbe_fd = -1;
static size_t part;
-static unsigned char invert;
-static unsigned char part_modified[2];
+static uint8_t invert;
+static uint8_t part_modified[2];
-static const char *mac_str = NULL;
+static const char *mac_str;
static const char rmac[] = "xx:xx:xx:xx:xx:xx";
-static const char *fname = "";
+static const char *fname;
static const char *argv0;
struct commands {
@@ -158,7 +170,6 @@ main(int argc, char *argv[])
if (argc < 2)
usage();
- reset_global_state();
fname = argv[1];
#ifdef __OpenBSD__
@@ -187,7 +198,7 @@ main(int argc, char *argv[])
set_io_flags(argc, argv);
#ifdef __OpenBSD__
- if (flags == O_RDONLY) {
+ if (gbe_flags == O_RDONLY) {
if (unveil(fname, "r") == -1)
err(ECANCELED, "unveil ro '%s'", fname);
if (unveil(NULL, NULL) == -1)
@@ -204,7 +215,7 @@ main(int argc, char *argv[])
}
#endif
-#ifndef HAVE_ARC4RANDOM
+#ifndef HAVE_ARC4RANDOM_BUF
open_dev_urandom();
#endif
open_gbe_file();
@@ -214,17 +225,30 @@ main(int argc, char *argv[])
err(ECANCELED, "pledge stdio (main)");
#endif
- read_gbe();
+ read_gbe_file();
(*cmd)();
- write_gbe();
+ write_gbe_file();
- if (close(fd) == -1)
+ if (close(gbe_fd) == -1)
err(ECANCELED, "close '%s'", fname);
-#ifndef HAVE_ARC4RANDOM
- if (close(rfd) == -1)
+#ifndef HAVE_ARC4RANDOM_BUF
+ if (close(urandom_fd) == -1)
err(ECANCELED, "close '%s'", rname);
#endif
+ /*
+ * We still exit with non-zero status if
+ * errno is set, but we don't need to print
+ * the error on dump commands, because they
+ * already print errors.
+ *
+ * If both parts have bad checksums, then
+ * cmd_dump will cause non-zero exit. If at
+ * least one part is valid, it resets errno.
+ *
+ * However, if we're not using cmd_dump, then
+ * we have a bug somewhere in the code.
+ */
if (cmd != cmd_dump) {
if (errno)
err(ECANCELED, "Unhandled error on exit");
@@ -236,42 +260,24 @@ main(int argc, char *argv[])
return EXIT_SUCCESS;
}
-/*
- * Currently redundant, because the program only runs
- * once, but I plan to expand this tool so that it can
- * work on multiple files, using getop switches as args.
- */
-static void
-reset_global_state(void)
-{
- errno = 0;
-
- mac_str = NULL;
- invert = 0;
- part_modified[0] = 0;
- part_modified[1] = 0;
- fname = "";
- cmd = NULL;
- fd = -1;
-#ifndef HAVE_ARC4RANDOM
- rfd = -1;
-#endif
- part = 0;
-
- memset(mac_buf, 0, sizeof(mac_buf));
- memset(buf, 0, sizeof(buf));
-}
-
static void
set_cmd(int argc, char *argv[])
{
size_t i;
+ /*
+ * No extra args: ./nvmutil gbe.bin
+ * Equivalent: ./nvmutil gbe.bin setmac xx:xx:xx:xx:xx:xx
+ */
if (argc == 2) {
cmd = cmd_setmac;
return;
}
+ /*
+ * Three or more args.
+ * Example: ./nvmutil gbe.bin copy 0
+ */
for (i = 0; i < items(command); i++) {
if (strcmp(argv[2], command[i].str) != 0)
continue;
@@ -287,85 +293,124 @@ set_cmd(int argc, char *argv[])
static void
check_cmd_args(int argc, char *argv[])
{
- if (cmd == NULL && argc > 2) { /* nvm gbe [MAC] */
+ if (cmd == NULL && argc > 2) {
+ /*
+ * Example: ./nvmutil gbe.bin xx:1f:16:xx:xx:xx
+ * Equivalent ./nvmutil gbe.bin setmac xx:1f:16:xx:xx:xx
+ */
mac_str = argv[2];
cmd = cmd_setmac;
- } else if (cmd == cmd_setmac) { /* nvm gbe setmac [MAC] */
+ } else if (cmd == cmd_setmac) {
+ /*
+ * Example: ./nvmutil gbe.bin setmac xx:1f:16:xx:xx:xx
+ */
mac_str = rmac; /* random MAC */
if (argc > 3)
mac_str = argv[3];
} else if (cmd != NULL && argc > 3) { /* user-supplied partnum */
- part = argv[3][0] - '0';
- if (!((part == 0 || part == 1) && argv[3][1] == '\0'))
- err(EINVAL, "Bad partnum: %s", argv[3]);
+ /*
+ * Example: ./nvmutil gbe.bin copy 0
+ */
+ part = conv_argv_part_num(argv[3]);
}
if (cmd == NULL)
err(EINVAL, "Bad command");
}
+static size_t
+conv_argv_part_num(const char *part_str)
+{
+ unsigned char ch;
+
+ /*
+ * Because char signedness is implementation-defined,
+ * we cast to unsigned char before arithmetic.
+ */
+
+ if (part_str[0] == '\0' || part_str[1] != '\0')
+ err(EINVAL, "Partnum string '%s' wrong length", part_str);
+
+ ch = (unsigned char)part_str[0];
+
+ if (ch < '0' || ch > '1')
+ err(EINVAL, "Bad part number (%c)", ch);
+
+ return (size_t)(ch - '0');
+}
+
static void
set_io_flags(int argc, char *argv[])
{
- flags = O_RDWR;
+ gbe_flags = O_RDWR;
if (argc < 3)
return;
if (strcmp(argv[2], "dump") == 0)
- flags = O_RDONLY;
+ gbe_flags = O_RDONLY;
}
-#ifndef HAVE_ARC4RANDOM
+#ifndef HAVE_ARC4RANDOM_BUF
static void
open_dev_urandom(void)
{
- struct stat st_rfd;
+ struct stat st_urandom_fd;
+ /*
+ * Try /dev/urandom first
+ */
rname = newrandom;
+ if ((urandom_fd = open(rname, O_RDONLY)) != -1)
+ return;
- if ((rfd = open(rname, O_RDONLY)) == -1) {
- /*
- * Fall back to /dev/random on old platforms
- * where /dev/urandom does not exist.
- */
- rname = oldrandom;
- xopen(&rfd, rname, O_RDONLY, &st_rfd);
- }
+ /*
+ * Fall back to /dev/random on old platforms
+ * where /dev/urandom does not exist.
+ *
+ * We must reset the error condition first,
+ * to prevent stale error status later.
+ */
+ errno = 0;
+
+ rname = oldrandom;
+ xopen(&urandom_fd, rname, O_RDONLY, &st_urandom_fd);
}
#endif
static void
open_gbe_file(void)
{
- xopen(&fd, fname, flags, &st);
+ struct stat gbe_st;
+
+ xopen(&gbe_fd, fname, gbe_flags, &gbe_st);
+
+ gbe_file_size = gbe_st.st_size;
- switch(st.st_size) {
+ switch (gbe_file_size) {
case SIZE_8KB:
case SIZE_16KB:
case SIZE_128KB:
- partsize = st.st_size >> 1;
break;
default:
err(ECANCELED, "File size must be 8KB, 16KB or 128KB");
- break;
}
}
static void
-xopen(int *f, const char *l, int p, struct stat *st)
+xopen(int *fd_ptr, const char *path, int flags, struct stat *st)
{
- if ((*f = open(l, p)) == -1)
- err(ECANCELED, "%s", l);
- if (fstat(*f, st) == -1)
- err(ECANCELED, "%s", l);
+ if ((*fd_ptr = open(path, flags)) == -1)
+ err(ECANCELED, "%s", path);
+ if (fstat(*fd_ptr, st) == -1)
+ err(ECANCELED, "%s", path);
}
static void
-read_gbe(void)
+read_gbe_file(void)
{
size_t p;
- unsigned char do_read[2] = {1, 1};
+ uint8_t do_read[2] = {1, 1};
/*
* The copy, brick and setchecksum commands need
@@ -373,7 +418,9 @@ read_gbe(void)
*
* We can skip reading the other part, thus:
*/
- if (cmd == cmd_copy || cmd == cmd_brick || cmd == cmd_setchecksum)
+ if (cmd == cmd_copy ||
+ cmd == cmd_brick ||
+ cmd == cmd_setchecksum)
do_read[part ^ 1] = 0;
/*
@@ -384,23 +431,23 @@ read_gbe(void)
*
* NOTE:
*
- * write_gbe() will not use this, but the copy/setchecksum commands
- * will directly manipulate part_modified[], telling write_gbe()
- * to also write in reverse, as in read_gbe().
+ * write_gbe_file() will not use this, but copy/setchecksum commands
+ * will directly manipulate part_modified[], telling write_gbe_file()
+ * to also write in reverse, as in read_gbe_file().
*/
if (cmd == cmd_copy || cmd == cmd_swap)
invert = 1;
for (p = 0; p < 2; p++) {
if (do_read[p])
- read_gbe_part(p, invert);
+ read_gbe_file_part(p, invert);
}
}
static void
-read_gbe_part(size_t p, unsigned char invert)
+read_gbe_file_part(size_t p, uint8_t invert)
{
- read_file_exact(fd, gbe_mem_offset(p ^ invert, "pread"),
+ read_file_exact(gbe_fd, gbe_mem_offset(p ^ invert, "pread"),
GBE_PART_SIZE, gbe_file_offset(p, "pread"), fname, "pread");
}
@@ -408,7 +455,7 @@ static void
cmd_setmac(void)
{
size_t partnum;
- unsigned char mac_updated = 0;
+ uint8_t mac_updated = 0;
parse_mac_string();
printf("MAC address to be written: %s\n", mac_str);
@@ -423,13 +470,15 @@ cmd_setmac(void)
static void
parse_mac_string(void)
{
- size_t mac_str_pos;
+ size_t mac_byte;
if (strlen(mac_str) != 17)
err(EINVAL, "MAC address is the wrong length");
- for (mac_str_pos = 0; mac_str_pos < 16; mac_str_pos += 3)
- set_mac_byte(mac_str_pos);
+ memset(mac_buf, 0, sizeof(mac_buf));
+
+ for (mac_byte = 0; mac_byte < 6; mac_byte++)
+ set_mac_byte(mac_byte);
if ((mac_buf[0] | mac_buf[1] | mac_buf[2]) == 0)
err(EINVAL, "Must not specify all-zeroes MAC address");
@@ -439,49 +488,40 @@ parse_mac_string(void)
}
static void
-set_mac_byte(size_t mac_str_pos)
+set_mac_byte(size_t mac_byte_pos)
{
+ size_t mac_str_pos = mac_byte_pos * 3;
size_t mac_nib_pos;
-
- check_mac_separator(mac_str_pos);
-
- for (mac_nib_pos = 0; mac_nib_pos < 2; mac_nib_pos++)
- set_mac_nib(mac_str_pos, mac_nib_pos);
-}
-
-static void
-check_mac_separator(size_t mac_str_pos)
-{
char separator;
- if (mac_str_pos == 15)
- return;
- if ((separator = mac_str[mac_str_pos + 2]) == ':')
- return;
+ if (mac_str_pos < 15) {
+ if ((separator = mac_str[mac_str_pos + 2]) != ':')
+ err(EINVAL, "Invalid MAC address separator '%c'",
+ separator);
+ }
- err(EINVAL, "Invalid MAC address separator '%c'", separator);
+ for (mac_nib_pos = 0; mac_nib_pos < 2; mac_nib_pos++)
+ set_mac_nib(mac_str_pos, mac_byte_pos, mac_nib_pos);
}
static void
-set_mac_nib(size_t mac_str_pos, size_t mac_nib_pos)
+set_mac_nib(size_t mac_str_pos,
+ size_t mac_byte_pos, size_t mac_nib_pos)
{
- uint8_t mac_ch;
+ char mac_ch;
+ uint16_t hex_num;
- size_t mac_byte_pos;
- size_t mac_word_left_shift;
+ mac_ch = mac_str[mac_str_pos + mac_nib_pos];
- if ((mac_ch = hextonum(mac_str[mac_str_pos + mac_nib_pos])) > 15)
+ if ((hex_num = hextonum(mac_ch)) > 15)
err(EINVAL, "Invalid character '%c'",
mac_str[mac_str_pos + mac_nib_pos]);
- mac_byte_pos = mac_str_pos / 3;
-
/* If random, ensure that local/unicast bits are set */
if ((mac_byte_pos == 0) && (mac_nib_pos == 1) &&
- ((mac_str[mac_str_pos + mac_nib_pos] == '?') ||
- (mac_str[mac_str_pos + mac_nib_pos] == 'x') ||
- (mac_str[mac_str_pos + mac_nib_pos] == 'X'))) /* random */
- mac_ch = (mac_ch & 0xE) | 2; /* local, unicast */
+ ((mac_ch | 0x20) == 'x' ||
+ (mac_ch == '?')))
+ hex_num = (hex_num & 0xE) | 2; /* local, unicast */
/*
* Words other than the MAC address are stored little
@@ -493,34 +533,36 @@ set_mac_nib(size_t mac_str_pos, size_t mac_nib_pos)
*
* Later code using the MAC string will handle this.
*/
- mac_word_left_shift =
- ((mac_byte_pos & 1) << 3) /* left or right byte? */
- | ((mac_nib_pos ^ 1) << 2); /* left or right nib? */
- /*
- * Now we can shift properly, OR'ing the result:
- */
- mac_buf[mac_byte_pos >> 1] |=
- (uint16_t)mac_ch << mac_word_left_shift;
+ mac_buf[mac_byte_pos >> 1] |= hex_num <<
+ (((mac_byte_pos & 1) << 3) /* left or right byte? */
+ | ((mac_nib_pos ^ 1) << 2)); /* left or right nib? */
}
-static uint8_t
-hextonum(char mac_ch)
+static uint16_t
+hextonum(char ch_s)
{
- if ((unsigned)(mac_ch - '0') <= 9)
- return mac_ch - '0';
+ /*
+ * We assume char is signed, hence ch_s.
+ * We explicitly cast to unsigned:
+ */
+ unsigned char ch = (unsigned char)ch_s;
- mac_ch |= 0x20;
+ if ((unsigned)(ch - '0') <= 9)
+ return ch - '0';
- if ((unsigned)(mac_ch - 'a') <= 5)
- return mac_ch - 'a' + 10;
- else if (mac_ch == '?' || mac_ch == 'x')
+ ch |= 0x20;
+
+ if ((unsigned)(ch - 'a') <= 5)
+ return ch - 'a' + 10;
+
+ if (ch == '?' || ch == 'x')
return rhex(); /* random character */
- else
- return 16; /* invalid character */
+
+ return 16; /* invalid character */
}
-static uint8_t
+static uint16_t
rhex(void)
{
static size_t n = 0;
@@ -528,14 +570,14 @@ rhex(void)
if (!n) {
n = sizeof(rnum);
-#ifdef HAVE_ARC4RANDOM
+#ifdef HAVE_ARC4RANDOM_BUF
arc4random_buf(rnum, n);
#else
- read_file_exact(rfd, rnum, n, 0, rname, NULL);
+ read_file_exact(urandom_fd, rnum, n, 0, rname, NULL);
#endif
}
- return rnum[--n] & 0xf;
+ return (uint16_t)(rnum[--n] & 0xf);
}
static void
@@ -655,8 +697,7 @@ set_checksum(size_t p)
size_t c;
uint16_t val16 = 0;
- if (p > 1)
- err(ECANCELED, "Bad part num %zu (must be 0 or 1)", p);
+ check_part_num(p);
for (c = 0; c < NVM_CHECKSUM_WORD; c++)
val16 += word(c, p);
@@ -692,11 +733,11 @@ cmd_copy(void)
/*
* SPEED HACK:
*
- * read_gbe() already performed the copy,
+ * read_gbe_file() already performed the copy,
* by virtue of inverted read. We need
* only set the other part as changed.
*/
- part_modified[part ^ 1] = 1;
+ set_part_modified(part ^ 1);
}
static void
@@ -714,11 +755,12 @@ cmd_swap(void)
/*
* SPEED HACK:
*
- * read_gbe() already performed the swap,
+ * read_gbe_file() already performed the swap,
* by virtue of inverted read. We need
* only set both parts as changed.
*/
- part_modified[1] = part_modified[0] = 1;
+ set_part_modified(0);
+ set_part_modified(1);
}
static int
@@ -750,7 +792,7 @@ word(size_t pos16, size_t p)
{
size_t pos;
- check_bound(pos16, p);
+ check_nvm_bound(pos16, p);
pos = (pos16 << 1) + (p * GBE_PART_SIZE);
return buf[pos] | (buf[pos + 1] << 8);
@@ -761,17 +803,17 @@ set_word(size_t pos16, size_t p, uint16_t val16)
{
size_t pos;
- check_bound(pos16, p);
+ check_nvm_bound(pos16, p);
pos = (pos16 << 1) + (p * GBE_PART_SIZE);
buf[pos] = (uint8_t)(val16 & 0xff);
buf[pos + 1] = (uint8_t)(val16 >> 8);
- part_modified[p] = 1;
+ set_part_modified(p);
}
static void
-check_bound(size_t c, size_t p)
+check_nvm_bound(size_t c, size_t p)
{
/*
* NVM_SIZE assumed as the limit, because the
@@ -780,37 +822,37 @@ check_bound(size_t c, size_t p)
*
* The only exception is copy/swap, but these
* do not use word/set_word and therefore do
- * not cause check_bound() to be called.
+ * not cause check_nvm_bound() to be called.
*
* TODO:
* This should be adjusted in the future, if
* we ever wish to work on the extented area.
*/
- if (p != 0 && p != 1)
- err(EINVAL, "check_bound: invalid partnum %zu", p);
+ check_part_num(p);
+
if (c >= NVM_WORDS)
- err(EINVAL, "check_bound: out of bounds %zu", c);
+ err(EINVAL, "check_nvm_bound: out of bounds %zu", c);
}
static void
-write_gbe(void)
+write_gbe_file(void)
{
size_t p;
- if (flags == O_RDONLY)
+ if (gbe_flags == O_RDONLY)
return;
for (p = 0; p < 2; p++) {
if (part_modified[p])
- write_gbe_part(p);
+ write_gbe_file_part(p);
}
}
static void
-write_gbe_part(size_t p)
+write_gbe_file_part(size_t p)
{
- ssize_t rval = pwrite(fd, gbe_mem_offset(p, "pwrite"),
+ ssize_t rval = pwrite(gbe_fd, gbe_mem_offset(p, "pwrite"),
GBE_PART_SIZE, gbe_file_offset(p, "pwrite"));
if (rval == -1)
@@ -823,7 +865,7 @@ write_gbe_part(size_t p)
}
/*
- * Reads to GbE from write_gbe_part and read_gbe_part
+ * Reads to GbE from write_gbe_file_part and read_gbe_file_part
* are filtered through here. These operations must
* only write from the 0th position or the half position
* within the GbE file, and write 4KB of data.
@@ -834,7 +876,7 @@ static off_t
gbe_file_offset(size_t p, const char *f_op)
{
return gbe_x_offset(p, f_op, "file",
- partsize, st.st_size);
+ gbe_file_size >> 1, gbe_file_size);
}
/*
@@ -857,9 +899,7 @@ gbe_x_offset(size_t p, const char *f_op, const char *d_type,
{
off_t off;
- if (p > 1)
- err(ECANCELED, "GbE %s %s invalid partnum: %s",
- d_type, f_op, fname);
+ check_part_num(p);
off = (off_t)p * nsize;
@@ -875,6 +915,20 @@ gbe_x_offset(size_t p, const char *f_op, const char *d_type,
}
static void
+set_part_modified(size_t p)
+{
+ check_part_num(p);
+ part_modified[p] = 1;
+}
+
+static void
+check_part_num(size_t p)
+{
+ if (p > 1)
+ err(EINVAL, "Bad part number (%zu)", p);
+}
+
+static void
usage(void)
{
const char *util = getnvmprogname();