summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--util/libreboot-utils/include/common.h10
-rw-r--r--util/libreboot-utils/lib/file.c117
-rw-r--r--util/libreboot-utils/lib/mkhtemp.c33
-rw-r--r--util/libreboot-utils/lib/num.c21
-rw-r--r--util/libreboot-utils/lib/rand.c3
-rw-r--r--util/libreboot-utils/lib/state.c4
-rw-r--r--util/libreboot-utils/lib/string.c65
-rw-r--r--util/libreboot-utils/lottery.c10
-rw-r--r--util/libreboot-utils/mkhtemp.c3
-rw-r--r--util/libreboot-utils/nvmutil.c22
10 files changed, 208 insertions, 80 deletions
diff --git a/util/libreboot-utils/include/common.h b/util/libreboot-utils/include/common.h
index 4b736808..0ccc02aa 100644
--- a/util/libreboot-utils/include/common.h
+++ b/util/libreboot-utils/include/common.h
@@ -301,8 +301,6 @@ struct xstate {
struct macaddr mac;
struct xfile f;
- char *argv0;
-
size_t i; /* index to cmd[] for current command */
int no_cmd;
@@ -484,6 +482,14 @@ ssize_t rw_over_nrw(ssize_t r, size_t nrw);
off_t lseek_on_eintr(int fd, off_t off,
int whence, int loop_eagain, int loop_eintr);
int try_err(int loop_err, int errval);
+ssize_t read_on_eintr(int fd,
+ void *buf, size_t count);
+ssize_t write_on_eintr(int fd,
+ void *buf, size_t count);
+ssize_t pread_on_eintr(int fd,
+ void *buf, size_t count, off_t off);
+ssize_t pwrite_on_eintr(int fd,
+ void *buf, size_t count, off_t off);
/* Error handling and cleanup
*/
diff --git a/util/libreboot-utils/lib/file.c b/util/libreboot-utils/lib/file.c
index 48eb37ed..f35d9749 100644
--- a/util/libreboot-utils/lib/file.c
+++ b/util/libreboot-utils/lib/file.c
@@ -323,15 +323,15 @@ try_rw_again:
real_pread_pwrite:
#endif
if (rw_type == IO_WRITE)
- r = write(fd, mem, nrw);
+ r = write_on_eintr(fd, mem, nrw);
else if (rw_type == IO_READ)
- r = read(fd, mem, nrw);
+ r = read_on_eintr(fd, mem, nrw);
#if defined(REAL_POS_IO) && \
REAL_POS_IO > 0
else if (rw_type == IO_PWRITE)
- r = pwrite(fd, mem, nrw, off);
+ r = pwrite_on_eintr(fd, mem, nrw, off);
else if (rw_type == IO_PREAD)
- r = pread(fd, mem, nrw, off);
+ r = pread_on_eintr(fd, mem, nrw, off);
#endif
if (r == -1 && (errno == try_err(loop_eintr, EINTR)
@@ -386,9 +386,9 @@ real_pread_pwrite:
}
if (rw_type == IO_PREAD)
- r = read(fd, mem, nrw);
+ r = read_on_eintr(fd, mem, nrw);
else if (rw_type == IO_PWRITE)
- r = write(fd, mem, nrw);
+ r = write_on_eintr(fd, mem, nrw);
if (rw_over_nrw(r, nrw) == -1)
break;
@@ -955,13 +955,118 @@ retry:
return rval;
}
+ssize_t
+read_on_eintr(int fd,
+ void *buf, size_t count)
+{
+ int saved_errno = errno;
+ int rval;
+ if (if_err(buf == NULL, EFAULT) ||
+ if_err(fd < 0, EBADF) ||
+ if_err(count == 0, EINVAL))
+ goto err;
+retry:
+ errno = 0;
+ if ((rval = read(fd, buf, count)) == -1 && (
+ errno == EINTR ||
+ errno == EAGAIN ||
+ errno == EWOULDBLOCK ||
+ errno == ETXTBSY))
+ goto retry;
+ errno = saved_errno;
+ return rval;
+err:
+ return set_errno(saved_errno, EIO);
+}
+ssize_t
+pread_on_eintr(int fd,
+ void *buf, size_t count,
+ off_t off)
+{
+ int saved_errno = errno;
+ int rval;
+ if (if_err(buf == NULL, EFAULT) ||
+ if_err(fd < 0, EBADF) ||
+ if_err(off < 0, EFAULT) ||
+ if_err(count == 0, EINVAL))
+ goto err;
+retry:
+ errno = 0;
+ if ((rval = pread(fd, buf, count, off)) == -1 && (
+ errno == EINTR ||
+ errno == EAGAIN ||
+ errno == EWOULDBLOCK ||
+ errno == ETXTBSY))
+ goto retry;
+ errno = saved_errno;
+ return rval;
+err:
+ return set_errno(saved_errno, EIO);
+}
+
+ssize_t
+write_on_eintr(int fd,
+ void *buf, size_t count)
+{
+ int saved_errno = errno;
+ int rval;
+ if (if_err(buf == NULL, EFAULT) ||
+ if_err(fd < 0, EBADF) ||
+ if_err(count == 0, EINVAL))
+ goto err;
+
+retry:
+ errno = 0;
+
+ if ((rval = write(fd, buf, count)) == -1 && (
+ errno == EINTR ||
+ errno == EAGAIN ||
+ errno == EWOULDBLOCK ||
+ errno == ETXTBSY))
+ goto retry;
+
+ errno = saved_errno;
+ return rval;
+err:
+ return set_errno(saved_errno, EIO);
+}
+
+ssize_t
+pwrite_on_eintr(int fd,
+ void *buf, size_t count,
+ off_t off)
+{
+ int saved_errno = errno;
+ int rval;
+
+ if (if_err(buf == NULL, EFAULT) ||
+ if_err(fd < 0, EBADF) ||
+ if_err(off < 0, EFAULT) ||
+ if_err(count == 0, EINVAL))
+ goto err;
+
+retry:
+ errno = 0;
+
+ if ((rval = pwrite(fd, buf, count, off)) == -1 && (
+ errno == EINTR ||
+ errno == EAGAIN ||
+ errno == EWOULDBLOCK ||
+ errno == ETXTBSY))
+ goto retry;
+
+ errno = saved_errno;
+ return rval;
+err:
+ return set_errno(saved_errno, EIO);
+}
diff --git a/util/libreboot-utils/lib/mkhtemp.c b/util/libreboot-utils/lib/mkhtemp.c
index 72942868..bba8a7ca 100644
--- a/util/libreboot-utils/lib/mkhtemp.c
+++ b/util/libreboot-utils/lib/mkhtemp.c
@@ -135,19 +135,12 @@ new_tmp_common(int *fd, char **path, int type,
if (slen(templatestr, maxlen, &templatestr_len) < 0)
goto err;
- /* sizeof adds an extra byte, useful
- * because we also want '.' or '/'
- */
+ /* may as well calculate in advance */
destlen = dirlen + 1 + templatestr_len;
- if (destlen > maxlen - 1) {
- errno = EOVERFLOW;
+ /* full path: */
+ if (scatn(3, (const char *[]) { tmpdir, "/", templatestr },
+ maxlen, &dest) < 0)
goto err;
- }
-
- memcpy(smalloc(&dest, destlen + 1), tmpdir, dirlen);
- *(dest + dirlen) = '/';
- memcpy(dest + dirlen + 1, templatestr, templatestr_len);
- *(dest + destlen) = '\0';
fname = dest + dirlen + 1;
@@ -533,7 +526,7 @@ mkhtemp(int *fd,
struct stat *st_dir_initial,
int type)
{
- size_t len = 0;
+ size_t template_len = 0;
size_t xc = 0;
size_t fname_len = 0;
@@ -559,28 +552,28 @@ mkhtemp(int *fd,
if_err(*fd >= 0, EEXIST) ||
if_err(dirfd < 0, EBADF)
||
- if_err_sys(slen(template, max_len, &len) < 0) ||
- if_err(len >= max_len, EMSGSIZE)
+ if_err_sys(slen(template, max_len, &template_len) < 0) ||
+ if_err(template_len >= max_len, EMSGSIZE)
||
if_err_sys(slen(fname, max_len, &fname_len) < 0) ||
if_err(fname == NULL, EINVAL) ||
if_err(strrchr(fname, '/') != NULL, EINVAL))
return -1;
- for (end = template + len; /* count X */
+ for (end = template + template_len; /* count X */
end > template && *--end == 'X'; xc++);
- if (if_err(xc < 3 || xc > len, EINVAL) ||
- if_err(fname_len > len, EOVERFLOW))
+ if (if_err(xc < 3 || xc > template_len, EINVAL) ||
+ if_err(fname_len > template_len, EOVERFLOW))
return -1;
- if (if_err(memcmp(fname, template + len - fname_len,
+ if (if_err(memcmp(fname, template + template_len - fname_len,
fname_len) != 0, EINVAL))
return -1;
/* fname_copy = templatestr region only; p points to trailing XXXXXX */
memcpy(smalloc(&fname_copy, fname_len + 1),
- template + len - fname_len,
+ template + template_len - fname_len,
fname_len + 1);
p = fname_copy + fname_len - xc;
@@ -596,7 +589,7 @@ mkhtemp(int *fd,
goto err;
/* success: copy final name back */
- memcpy(template + len - fname_len,
+ memcpy(template + template_len - fname_len,
fname_copy, fname_len);
errno = saved_errno;
diff --git a/util/libreboot-utils/lib/num.c b/util/libreboot-utils/lib/num.c
index e4d0ce6b..e13a8853 100644
--- a/util/libreboot-utils/lib/num.c
+++ b/util/libreboot-utils/lib/num.c
@@ -50,6 +50,22 @@ hextonum(char ch_s)
}
/* basically hexdump -C */
+/*
+ TODO: optimise this
+ write a full util for hexdump
+ how to optimise:
+ don't call print tens of thousands of times!
+ convert the numbers manually, and cache everything
+ in a BUFSIZ sized buffer, with everything properly
+ aligned. i worked out that i could fit 79 rows
+ in a 8KB buffer (1264 bytes of numbers represented
+ as strings in hex)
+ this depends on the OS, and would be calculated at
+ runtime.
+ then:
+ don't use printf. just write it to stdout (basically
+ a simple cat implementation)
+*/
void
spew_hex(const void *data, size_t len)
{
@@ -64,7 +80,10 @@ spew_hex(const void *data, size_t len)
for (i = 0; i < len; i += 16) {
- printf("%08zx ", i);
+ if (len <= 4294967296) /* below 4GB */
+ printf("%08zx ", i);
+ else
+ printf("%0*zx ", sizeof(size_t) * 2, i);
for (j = 0; j < 16; j++) {
diff --git a/util/libreboot-utils/lib/rand.c b/util/libreboot-utils/lib/rand.c
index 2aa0de3a..9da8d9eb 100644
--- a/util/libreboot-utils/lib/rand.c
+++ b/util/libreboot-utils/lib/rand.c
@@ -150,7 +150,8 @@ rset(void *buf, size_t n)
int fd = -1;
open_on_eintr("/dev/urandom", &fd, O_RDONLY, 0400, NULL);
retry_rand:
- if ((rc = read(fd, (unsigned char *)buf + off, n - off)) < 0) {
+ if ((rc = read_on_eintr(fd,
+ (unsigned char *)buf + off, n - off)) < 0) {
#elif defined(__linux__)
retry_rand:
if ((rc = (ssize_t)syscall(SYS_getrandom,
diff --git a/util/libreboot-utils/lib/state.c b/util/libreboot-utils/lib/state.c
index a3cd5b1f..bcf2ccbc 100644
--- a/util/libreboot-utils/lib/state.c
+++ b/util/libreboot-utils/lib/state.c
@@ -77,9 +77,6 @@ xstart(int argc, char *argv[])
/* .f */
{0},
- /* .argv0 (for our getprogname implementation) */
- NULL,
-
/* ->i (index to cmd[]) */
0,
@@ -103,7 +100,6 @@ xstart(int argc, char *argv[])
us.f.buf = us.f.real_buf;
- us.argv0 = argv[0];
us.f.fname = argv[1];
us.f.tmp_fd = -1;
diff --git a/util/libreboot-utils/lib/string.c b/util/libreboot-utils/lib/string.c
index c3cf4519..39b31cb0 100644
--- a/util/libreboot-utils/lib/string.c
+++ b/util/libreboot-utils/lib/string.c
@@ -174,49 +174,46 @@ sdup(const char *s,
}
/* concatenate N number of strings */
-/* slen already checks null/termination */
int
scatn(ssize_t sc, const char **sv,
size_t max, char **rval)
{
- ssize_t i = 0;
-
- size_t ts = 0;
- size_t *size = NULL;
-
- char *ct = NULL;
int saved_errno = errno;
-
- if (if_err(sc <= 0, EINVAL) ||
- if_err(sc > SIZE_MAX / sizeof(size_t), EOVERFLOW) ||
- if_err(sv == NULL, EINVAL))
+ char *final = NULL;
+ char *rcur = NULL;
+ char *rtmp = NULL;
+ size_t i;
+
+ if (if_err(sc < 2, EINVAL) ||
+ if_err(sv == NULL, EFAULT) ||
+ if_err(rval == NULL || *rval != NULL, EFAULT))
goto err;
- vmalloc((void **)&size, sizeof(size_t) * sc);
+ for (i = 0; i < sc; i++) {
- for (i = 0; i < sc; i++, ts += size[i])
- if (if_err(sv[i] == NULL, EINVAL) ||
- slen(sv[i], max, &size[i]) < 0 ||
- if_err(size[i] > max - 1, EOVERFLOW) ||
- if_err((size[i] + ts) < ts, EOVERFLOW))
+ if (if_err(sv[i] == NULL, EFAULT))
goto err;
+ else if (i == 0) {
+ if (sdup(sv[0], max, &final) < 0)
+ goto err;
+ continue;
+ }
- if (if_err(ts > SIZE_MAX - 1, EOVERFLOW) ||
- if_err(ts > max - 1, EOVERFLOW))
- goto err;
-
- smalloc(&ct, ts + 1);
- for (ts = i = 0; i < sc; i++, ts += size[i])
- memcpy(ct + ts, sv[i], size[i]);
+ rtmp = NULL;
+ if (scat(final, sv[i], max, &rtmp) < 0)
+ goto err;
- *(ct + ts) = '\0';
- *rval = ct;
+ free_and_set_null(&final);
+ final = rtmp;
+ rtmp = NULL;
+ }
- errno = saved_errno;
+ *rval = final;
return 0;
err:
- free_and_set_null(&ct);
- free_and_set_null((char **)&size);
+ free_and_set_null(&rcur);
+ free_and_set_null(&rtmp);
+ free_and_set_null(&final);
return set_errno(saved_errno, EFAULT);
}
@@ -230,7 +227,7 @@ scat(const char *s1, const char *s2,
size_t size2;
char *rval = NULL;
- if (dest == NULL ||
+ if (if_err(dest == NULL || *dest != NULL, EFAULT) ||
slen(s1, n, &size1) < 0 ||
slen(s2, n, &size2) < 0 ||
if_err(size1 > SIZE_MAX - size2 - 1, EOVERFLOW)) {
@@ -324,17 +321,13 @@ err_exit(int nvm_errval, const char *msg, ...)
if (!errno)
saved_errno = errno = ECANCELED;
- if ((p = lbgetprogname()) != NULL)
- fprintf(stderr, "%s: ", p);
+ fprintf(stderr, "%s: ", lbgetprogname());
va_start(args, msg);
vfprintf(stderr, msg, args);
va_end(args);
- if (p != NULL)
- fprintf(stderr, ": %s\n", strerror(errno));
- else
- fprintf(stderr, "%s\n", strerror(errno));
+ fprintf(stderr, ": %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
diff --git a/util/libreboot-utils/lottery.c b/util/libreboot-utils/lottery.c
index 48565c87..fd39c68c 100644
--- a/util/libreboot-utils/lottery.c
+++ b/util/libreboot-utils/lottery.c
@@ -18,21 +18,21 @@ main(int argc, char **argv)
{
int same = 0;
char *buf;
+ size_t size = 8589934592;
(void) argc, (void) argv;
(void) errhook(exit_cleanup);
- if (lbsetprogname(argv[0]) == NULL)
- err_exit(errno, "could not set progname");
+ (void) lbsetprogname(argv[0]);
/* https://man.openbsd.org/pledge.2 */
xpledgex("stdio", NULL);
- buf = rmalloc(BUFSIZ);
- if (!memcmp(buf, buf + (BUFSIZ >> 1), BUFSIZ >> 1))
+ buf = rmalloc(size);
+ if (!memcmp(buf, buf + (size >> 1), size >> 1))
same = 1;
if (argc < 2) /* no spew */
- spew_hex(buf, BUFSIZ);
+ spew_hex(buf, size);
free_and_set_null(&buf);
fprintf(stderr, "\n%s\n", same ? "You win!" : "You lose!");
diff --git a/util/libreboot-utils/mkhtemp.c b/util/libreboot-utils/mkhtemp.c
index 04ce1993..de86a2bf 100644
--- a/util/libreboot-utils/mkhtemp.c
+++ b/util/libreboot-utils/mkhtemp.c
@@ -62,8 +62,7 @@ main(int argc, char *argv[])
int type = MKHTEMP_FILE;
(void) errhook(exit_cleanup);
- if (lbsetprogname(argv[0]) == NULL)
- err_exit(errno, "could not set progname");
+ (void) lbsetprogname(argv[0]);
/* https://man.openbsd.org/pledge.2 */
xpledgex("stdio flock rpath wpath cpath", NULL);
diff --git a/util/libreboot-utils/nvmutil.c b/util/libreboot-utils/nvmutil.c
index 49d81a01..ec41371f 100644
--- a/util/libreboot-utils/nvmutil.c
+++ b/util/libreboot-utils/nvmutil.c
@@ -33,8 +33,7 @@ main(int argc, char *argv[])
size_t c;
(void) errhook(exit_cleanup);
- if (lbsetprogname(argv[0]) == NULL)
- err_exit(errno, "could not set progname");
+ (void) lbsetprogname(argv[0]);
/* https://man.openbsd.org/pledge.2 */
/* https://man.openbsd.org/unveil.2 */
@@ -96,5 +95,22 @@ main(int argc, char *argv[])
static void
exit_cleanup(void)
{
- return;
+ struct xstate *x;
+ struct xfile *f;
+
+ x = xstatus();
+ if (x == NULL)
+ return;
+
+ f = &x->f;
+
+ /* close fds if still open */
+ close_on_eintr(&f->tmp_fd);
+ close_on_eintr(&f->gbe_fd);
+
+ /* unlink tmpfile if it exists */
+ if (f->tname != NULL) {
+ (void) unlink(f->tname);
+ free_and_set_null(&f->tname);
+ }
}