summaryrefslogtreecommitdiff
path: root/util/nvmutil
diff options
context:
space:
mode:
Diffstat (limited to 'util/nvmutil')
-rw-r--r--util/nvmutil/nvmutil.c69
1 files changed, 44 insertions, 25 deletions
diff --git a/util/nvmutil/nvmutil.c b/util/nvmutil/nvmutil.c
index 85b6d4ed..34db6b92 100644
--- a/util/nvmutil/nvmutil.c
+++ b/util/nvmutil/nvmutil.c
@@ -330,15 +330,16 @@ static off_t gbe_x_offset(size_t part, const char *f_op,
static ssize_t rw_gbe_file_exact(int fd, u8 *mem, size_t nrw,
off_t off, int rw_type);
static ssize_t rw_file_exact(int fd, u8 *mem, size_t len,
- off_t off, int rw_type, int loop_eagain);
+ off_t off, int rw_type, int loop_eagain, int loop_eintr);
static ssize_t rw_file_once(int fd, u8 *mem, size_t len,
- off_t off, int rw_type, size_t rc, int loop_eagain);
+ off_t off, int rw_type, size_t rc, int loop_eagain,
+ int loop_eintr);
static ssize_t prw(int fd, void *mem, size_t nrw,
- off_t off, int rw_type, int loop_eagain);
+ off_t off, int rw_type, int loop_eagain, int loop_eintr);
static int rw_over_nrw(ssize_t r, size_t nrw);
static off_t lseek_eintr(int fd, off_t off,
- int whence, int loop_eagain);
-static int err_eagain(int loop_eagain);
+ int whence, int loop_eagain, int loop_eintr);
+static int err_eagain(int loop_err, int errval);
/*
* Error handling and cleanup
@@ -1153,7 +1154,7 @@ rhex(void)
if (!n) {
n = sizeof(rnum);
- if (rw_file_exact(urandom_fd, rnum, n, 0, IO_READ, 0) == -1)
+ if (rw_file_exact(urandom_fd, rnum, n, 0, IO_READ, 0, 1) == -1)
err(errno, "Randomisation failed");
}
@@ -1322,7 +1323,7 @@ static void
gbe_cat_buf(u8 *b)
{
if (rw_file_exact(STDOUT_FILENO, b,
- GBE_PART_SIZE, 0, IO_WRITE, 1) < 0)
+ GBE_PART_SIZE, 0, IO_WRITE, 1, 1) < 0)
err(errno, "stdout: cat");
}
@@ -1576,7 +1577,7 @@ rw_gbe_file_exact(int fd, u8 *mem, size_t nrw,
if (nrw > GBE_PART_SIZE)
goto err_rw_gbe_file_exact;
- return rw_file_exact(fd, mem, nrw, off, rw_type, 0);
+ return rw_file_exact(fd, mem, nrw, off, rw_type, 0, 1);
err_rw_gbe_file_exact:
errno = EIO;
@@ -1602,14 +1603,15 @@ err_rw_gbe_file_exact:
*/
static ssize_t
rw_file_exact(int fd, u8 *mem, size_t nrw,
- off_t off, int rw_type, int loop_eagain)
+ off_t off, int rw_type, int loop_eagain,
+ int loop_eintr)
{
ssize_t rv;
size_t rc;
for (rc = 0, rv = 0; rc < nrw; ) {
if ((rv = rw_file_once(fd, mem, nrw, off, rw_type, rc,
- loop_eagain)) <= 0)
+ loop_eagain, loop_eintr)) <= 0)
return -1;
rc += (size_t)rv;
@@ -1629,7 +1631,7 @@ rw_file_exact(int fd, u8 *mem, size_t nrw,
static ssize_t
rw_file_once(int fd, u8 *mem, size_t nrw,
off_t off, int rw_type, size_t rc,
- int loop_eagain)
+ int loop_eagain, int loop_eintr)
{
ssize_t rv;
size_t retries_on_zero = 0;
@@ -1639,7 +1641,8 @@ rw_file_once(int fd, u8 *mem, size_t nrw,
goto err_rw_file_once;
read_again:
- rv = prw(fd, mem + rc, nrw - rc, off + rc, rw_type, loop_eagain);
+ rv = prw(fd, mem + rc, nrw - rc, off + rc, rw_type,
+ loop_eagain, loop_eintr);
if (rv < 0)
return -1;
@@ -1672,10 +1675,21 @@ err_rw_file_once:
* A fallback is provided for regular read/write.
* rw_type can be IO_READ, IO_WRITE, IO_PREAD
* or IO_PWRITE
+ *
+ * loop_eagain does a retry loop on EAGAIN if set
+ * loop_eintr does a retry loop on EINTR if set
+ *
+ * Unlike the bare syscalls, prw() does security
+ * checks e.g. checks NULL strings, checks bounds,
+ * also mitigates a few theoretical libc bugs.
+ * It is designed for extremely safe single-threaded
+ * I/O on applications that need it.
*/
+
static ssize_t
prw(int fd, void *mem, size_t nrw,
- off_t off, int rw_type, int loop_eagain)
+ off_t off, int rw_type,
+ int loop_eagain, int loop_eintr)
{
off_t off_orig;
ssize_t r;
@@ -1708,8 +1722,8 @@ try_rw_again:
else if (rw_type == IO_READ)
r = read(fd, mem, nrw);
- if (r == -1 && (errno == EINTR
- || errno == err_eagain(loop_eagain)))
+ if (r == -1 && (errno == err_eagain(loop_eintr, EINTR)
+ || errno == err_eagain(loop_eagain, EAGAIN)))
goto try_rw_again;
return rw_over_nrw(r, nrw);
@@ -1729,9 +1743,10 @@ try_rw_again:
goto err_prw;
if ((off_orig = lseek_eintr(fd, (off_t)0, SEEK_CUR,
- loop_eagain)) == (off_t)-1)
+ loop_eagain, loop_eintr)) == (off_t)-1)
r = -1;
- else if (lseek_eintr(fd, off, SEEK_SET, loop_eagain) == (off_t)-1)
+ else if (lseek_eintr(fd, off, SEEK_SET,
+ loop_eagain, loop_eintr) == (off_t)-1)
r = -1;
do {
@@ -1741,12 +1756,13 @@ try_rw_again:
r = write(fd, mem, nrw);
r = rw_over_nrw(r, nrw);
- } while (r == -1 && (errno == EINTR
- || errno == err_eagain(loop_eagain)));
+ } while (r == -1 &&
+ (errno == err_eagain(loop_eintr, EINTR)
+ || errno == err_eagain(loop_eagain, EAGAIN)));
saved_errno = errno;
if (lseek_eintr(fd, off_orig, SEEK_SET,
- loop_eagain) == (off_t)-1) {
+ loop_eagain, loop_eintr) == (off_t)-1) {
if (r < 0)
errno = saved_errno;
return -1;
@@ -1803,23 +1819,26 @@ err_rw_over_nrw:
}
static off_t
-lseek_eintr(int fd, off_t off, int whence, int loop_eagain)
+lseek_eintr(int fd, off_t off, int whence,
+ int loop_eagain, int loop_eintr)
{
off_t old;
do {
old = lseek(fd, off, whence);
} while (old == (off_t)-1
- && (!(errno == EINTR || errno == err_eagain(loop_eagain))));
+ && (!(
+ errno == err_eagain(loop_eintr, EINTR) ||
+ errno == err_eagain(loop_eagain, EAGAIN))));
return old;
}
static int
-err_eagain(int loop_eagain)
+err_eagain(int loop_err, int errval)
{
- if (loop_eagain)
- return EAGAIN;
+ if (loop_err)
+ return errval;
/* errno is never negative,
so functions checking it