diff options
Diffstat (limited to 'util')
| -rw-r--r-- | util/nvmutil/nvmutil.c | 51 |
1 files changed, 44 insertions, 7 deletions
diff --git a/util/nvmutil/nvmutil.c b/util/nvmutil/nvmutil.c index fb25af73..10cb1f45 100644 --- a/util/nvmutil/nvmutil.c +++ b/util/nvmutil/nvmutil.c @@ -27,6 +27,8 @@ static void check_mac_separator(int); static void set_mac_nib(int, int, uint8_t *); static uint8_t hextonum(char); static uint8_t rhex(void); +static void read_urandom(uint8_t *, ssize_t); +static int valid_read(const char *, ssize_t, ssize_t, int); static int write_mac_part(int); static void cmd_dump(void); static void print_mac_address(int); @@ -57,6 +59,8 @@ static void set_err(int); #define SIZE_16KB 0x4000 #define SIZE_128KB 0x20000 +#define MAX_RETRY_READ 200 + #define items(x) (sizeof((x)) / sizeof((x)[0])) static uint8_t buf[SIZE_8KB]; @@ -241,10 +245,17 @@ read_gbe(void) static void read_gbe_part(int p, int invert) { - if (pread(fd, buf + (SIZE_4KB * (p ^ invert)), SIZE_4KB, p * partsize) - != (ssize_t) SIZE_4KB) - err(ECANCELED, - "Can't read %d b from '%s' p%d", SIZE_4KB, fname, p); + int retry; + ssize_t rval; + + for (retry = 0; retry < (int) MAX_RETRY_READ; retry++) { + rval = pread(fd, buf + (SIZE_4KB * (p ^ invert)), + SIZE_4KB, p * partsize); + + if (valid_read(fname, rval, (ssize_t) SIZE_4KB, retry)) + break; + } + swap(p ^ invert); /* handle big-endian host CPU */ } @@ -349,14 +360,40 @@ rhex(void) if (!n) { n = sizeof(rnum) - 1; - if (read(rfd, (uint8_t *) &rnum, sizeof(rnum)) - != (ssize_t) (sizeof(rnum))) - err(ECANCELED, "Could not read from /dev/urandom"); + read_urandom((uint8_t *) rnum, sizeof(rnum)); } return rnum[n--] & 0xf; } +static void +read_urandom(uint8_t *rnum, ssize_t rsize) +{ + int retry = 0; + ssize_t rval; + + for (retry = 0; retry < (int) MAX_RETRY_READ; retry++) { + rval = read(rfd, (uint8_t *) rnum, rsize); + if (valid_read("/dev/urandom", rval, rsize, retry)) + break; + } +} + +static int +valid_read(const char *rpath, ssize_t rval, ssize_t rsize, int retry) +{ + if (rval == (ssize_t) rsize) + return 1; + if (rval != -1) + err(ECANCELED, "Short read, %lld: %s", rval, rpath); + if (errno != EINTR) + err(ECANCELED, "read '%s'", rpath); + if (retry == MAX_RETRY_READ - 1) + err(EINTR, "read: max retries exceeded: %s", rpath); + + return (errno = 0); +} + static int write_mac_part(int partnum) { |
