diff options
-rw-r--r-- | daemon/daemon.h | 2 | ||||
-rw-r--r-- | daemon/guestfsd.c | 46 | ||||
-rw-r--r-- | daemon/zero.c | 33 |
3 files changed, 51 insertions, 30 deletions
diff --git a/daemon/daemon.h b/daemon/daemon.h index b4790788..85eec455 100644 --- a/daemon/daemon.h +++ b/daemon/daemon.h @@ -112,6 +112,8 @@ extern int prog_exists (const char *prog); extern void udev_settle (void); +extern int random_name (char *template); + /* This just stops gcc from giving a warning about our custom printf * formatters %Q and %R. See guestfs(3)/EXTENDING LIBGUESTFS for more * info about these. diff --git a/daemon/guestfsd.c b/daemon/guestfsd.c index b09f74e1..2b0acf96 100644 --- a/daemon/guestfsd.c +++ b/daemon/guestfsd.c @@ -1190,6 +1190,52 @@ prog_exists (const char *prog) return 0; } +/* Pass a template such as "/sysroot/XXXXXXXX.XXX". This updates the + * template to contain a randomly named file. Any 'X' characters + * after the final '/' are replaced with random characters. + * + * Notes: You should probably use an 8.3 path, so it's compatible with + * all filesystems including basic FAT. Also this only substitutes + * lowercase ASCII letters and numbers, again for compatibility with + * lowest common denominator filesystems. + * + * This doesn't create a file or check whether or not the file exists + * (it would be extremely unlikely to exist as long as the RNG is + * working). + * + * If there is an error, -1 is returned. + */ +int +random_name (char *template) +{ + int fd; + unsigned char c; + char *p; + + fd = open ("/dev/urandom", O_RDONLY|O_CLOEXEC); + if (fd == -1) + return -1; + + p = strrchr (template, '/'); + if (p == NULL) + abort (); /* internal error - bad template */ + + while (*p) { + if (*p == 'X') { + if (read (fd, &c, 1) != 1) { + close (fd); + return -1; + } + *p = "0123456789abcdefghijklmnopqrstuvwxyz"[c % 36]; + } + + p++; + } + + close (fd); + return 0; +} + /* LVM and other commands aren't synchronous, especially when udev is * involved. eg. You can create or remove some device, but the /dev * device node won't appear until some time later. This means that diff --git a/daemon/zero.c b/daemon/zero.c index 3076a602..14aef75d 100644 --- a/daemon/zero.c +++ b/daemon/zero.c @@ -228,35 +228,6 @@ do_is_zero_device (const char *device) return 1; } -static int -random_name (char *p) -{ - int fd; - unsigned char c; - - fd = open ("/dev/urandom", O_RDONLY|O_CLOEXEC); - if (fd == -1) { - reply_with_perror ("/dev/urandom"); - return -1; - } - - while (*p) { - if (*p == 'X') { - if (read (fd, &c, 1) != 1) { - reply_with_perror ("read: /dev/urandom"); - close (fd); - return -1; - } - *p = "0123456789abcdefghijklmnopqrstuvwxyz"[c % 36]; - } - - p++; - } - - close (fd); - return 0; -} - /* Current implementation is to create a file of all zeroes, then * delete it. The description of this function is left open in order * to allow better implementations in future, including @@ -277,8 +248,10 @@ do_zero_free_space (const char *dir) * compatible with any filesystem type inc. FAT. */ snprintf (filename, sysroot_len+len+14, "%s%s/XXXXXXXX.XXX", sysroot, dir); - if (random_name (&filename[sysroot_len+len]) == -1) + if (random_name (filename) == -1) { + reply_with_perror ("random_name"); return -1; + } if (verbose) printf ("random filename: %s\n", filename); |