summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--util/nvmutil/nvmutil.c158
1 files changed, 100 insertions, 58 deletions
diff --git a/util/nvmutil/nvmutil.c b/util/nvmutil/nvmutil.c
index 2182348a..b40a0910 100644
--- a/util/nvmutil/nvmutil.c
+++ b/util/nvmutil/nvmutil.c
@@ -373,8 +373,7 @@ void set_mac_byte(unsigned long mac_byte_pos);
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 short rhex(void);
-unsigned short read_urandom(void);
+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);
@@ -472,7 +471,13 @@ const char *getnvmprogname(void);
char *new_tmpfile(int *fd, int local, const char *path);
int x_i_mkstemp(char *template);
char *x_c_strrchr(const char *s, int c);
+/* x_i_rename not suitable
+ * for atomic writes. kept
+ * commentted for use in a
+ * library in the future */
+/*
int x_i_rename(const char *src, const char *dst);
+*/
char *x_c_tmpdir(void);
int x_i_close(int fd);
void *x_v_memcpy(void *dst,
@@ -709,11 +714,25 @@ ino_t tmp_ino;
int tmp_fd = -1;
char *tname = NULL;
+/*
+ * Used for checking whether.
+ * a file is a file via stat().
+ *
+ * Portable macro for compatibility
+ * with older unix e.g. v7 unix (has S_IFREG),
+ * 4.2bsd (has S_IFMT) or POSIX (has S_ISREG)
+ *
+ * Fallback works where S_IFREG == 0100000
+ * (classic unix bitmask)
+ */
+
#ifndef S_ISREG
-#ifdef S_IFMT
-#define S_ISREG(m) (((m) & (S_IFMT)) == (S_IFREG))
+#if defined(S_IFMT) && defined(S_IFREG)
+#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+#elif defined(S_IFREG)
+#define S_ISREG(m) (((m) & S_IFREG) != 0)
#else
-#define S_ISREG(m) (((m) & (S_IFREG)) == (S_IFREG))
+#error "can't determine types with stat()"
#endif
#endif
@@ -1358,30 +1377,25 @@ hextonum(char ch_s)
return ch - 'a' + 10;
if (ch == '?' || ch == 'x')
- return rhex(); /* random character */
+ return (unsigned short)rlong() & 0xf;
return 16; /* invalid character */
}
-unsigned short
-rhex(void)
+unsigned long
+rlong(void)
{
struct x_st_timeval tv;
- unsigned long mix;
+ static unsigned long mix = 0;
static unsigned long counter = 0;
- unsigned short r;
-
- /* Read /dev/urandom
- * if possible */
- r = read_urandom();
- if (r < 16)
- return r;
- /* Fallback */
+ static int fd = -1;
+ unsigned long rval = 0;
+ long nr = -1;
x_i_gettimeofday(&tv, NULL);
- mix = (unsigned long)tv.tv_sec
+ mix ^= (unsigned long)tv.tv_sec
^ (unsigned long)tv.tv_usec
^ (unsigned long)getpid()
^ (unsigned long)&mix
@@ -1396,45 +1410,45 @@ rhex(void)
mix ^= (unsigned long)&tv;
mix ^= (unsigned long)&counter;
- return (unsigned short)(mix & 0xf);
-}
-
-unsigned short
-read_urandom(void)
-{
- static int fd = -1;
- static long n = -1;
-
- static unsigned char r[256];
+ /*
+ * 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) {
+ if (fd < 0)
+ fd = open("/dev/urandom", O_RDONLY | O_BINARY | O_NONBLOCK);
- fd = open("/dev/urandom", O_RDONLY | O_NONBLOCK);
-#ifndef NVMUTIL_UNVEIL
- if (fd < 0) /* older openbsd */
- fd = open("/dev/arandom", O_RDONLY | O_NONBLOCK);
+#if !(defined(__OpenBSD__) && defined(OpenBSD)) || \
+ (defined(__OpenBSD__) && defined(OpenBSD) && \
+ OpenBSD < 604)
+ if (fd < 0) /* old openbsd */
+ fd = open("/dev/arandom", O_RDONLY | O_BINARY | O_NONBLOCK);
#endif
- if (fd < 0) /* super old unix (could block) */
- fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
-
- if (fd < 0)
- return 16;
- }
- if (n < 0) {
-
- n = rw_file_exact(fd, r, 256, 0, IO_READ,
- LOOP_EAGAIN, LOOP_EINTR, 2, OFF_ERR);
+ if (fd < 0)
+ fd = open("/dev/random", O_RDONLY | O_BINARY | O_NONBLOCK);
- if (n == 0)
- n = -1;
- if (n < 0)
- return 16;
+ nr = rw_file_exact(fd, (unsigned char *)&rval,
+ sizeof(unsigned long), 0, IO_READ, LOOP_EAGAIN,
+ LOOP_EINTR, MAX_ZERO_RW_RETRY, OFF_ERR);
- --n;
- }
+ if (nr == sizeof(unsigned long))
+ return rval;
- return r[n--] & 0xf;
+ return mix;
}
unsigned long
@@ -1445,8 +1459,9 @@ entropy_jitter(void)
long mix_diff;
int i;
+ x_i_gettimeofday(&a, NULL);
+
for (i = 0; i < 8; i++) {
- x_i_gettimeofday(&a, NULL);
getpid();
x_i_gettimeofday(&b, NULL);
@@ -1477,7 +1492,7 @@ x_i_gettimeofday(struct x_st_timeval *tv, void *tz)
t = time(NULL);
tv->tv_sec = t;
- tv->tv_usec = (long)clock() % 1000000;
+ tv->tv_usec = (long)((unsigned long)clock() % 1000000UL);
return 0;
}
@@ -1999,7 +2014,7 @@ gbe_mv(void)
saved_errno = errno;
- r = x_i_rename(tname, fname);
+ r = rename(tname, fname);
if (r > -1) {
/*
@@ -2052,7 +2067,7 @@ gbe_mv(void)
if (x_i_close(dest_fd) == -1)
goto ret_gbe_mv;
- if (x_i_rename(dest_tmp, fname) == -1)
+ if (rename(dest_tmp, fname) == -1)
goto ret_gbe_mv;
if (fsync_dir(fname) < 0)
@@ -2105,7 +2120,7 @@ ret_gbe_mv:
}
/*
- * Ensure x_i_rename() is durable by syncing the
+ * Ensure rename() is durable by syncing the
* directory containing the target file.
*/
int
@@ -2134,6 +2149,12 @@ fsync_dir(const char *path)
goto err_fsync_dir;
}
+ if (pathlen == 0)
+ {
+ errno = EINVAL;
+ goto err_fsync_dir;
+ }
+
dirbuf = malloc(pathlen + 1);
if (dirbuf == NULL)
goto err_fsync_dir;
@@ -2149,7 +2170,14 @@ fsync_dir(const char *path)
strcpy(dirbuf, ".");
}
- dfd = open(dirbuf, O_RDONLY);
+ dfd = open(dirbuf, O_RDONLY
+#ifdef O_DIRECTORY
+ | O_DIRECTORY
+#endif
+#ifdef O_NOFOLLOW
+ | O_NOFOLLOW
+#endif
+ );
if (dfd == -1)
goto err_fsync_dir;
@@ -3025,6 +3053,7 @@ x_i_mkstemp(char *template)
char *p;
char ch[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+ unsigned long r = rlong();
len = xstrxlen(template, PATH_LEN);
@@ -3037,7 +3066,7 @@ x_i_mkstemp(char *template)
for (i = 0; i < 100; i++) {
for (j = 0; j < 6; j++)
- p[j] = ch[rhex() & 31];
+ p[j] = ch[r % (sizeof(ch) - 1)];
fd = open(template, O_RDWR | O_CREAT | O_EXCL, 0600);
@@ -3069,6 +3098,7 @@ x_c_strrchr(const char *s, int c)
return (char *)p;
}
+/*
int
x_i_rename(const char *src, const char *dst)
{
@@ -3111,6 +3141,7 @@ x_i_rename(const char *src, const char *dst)
return 0;
}
+*/
char *
x_c_tmpdir(void)
@@ -3173,6 +3204,12 @@ x_i_memcmp(const void *a, const void *b, unsigned long n)
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)
{
@@ -3195,13 +3232,18 @@ x_try_fdpath(const char *prefix, int fd, mode_t mode)
unsigned long j;
while (prefix[i]) {
+ if (i >= PATH_LEN - 1)
+ return -1;
path[i] = prefix[i];
i++;
}
j = x_conv_fd(path + i, (unsigned long)fd);
- i += j;
+ if (i + j >= PATH_LEN)
+ return -1;
+
+ i += j;
path[i] = '\0';
return chmod(path, mode);