diff --git a/Makefile.am b/Makefile.am index 7a0a091c1..4e476ea92 100644 --- a/Makefile.am +++ b/Makefile.am @@ -51,6 +51,7 @@ SUBDIRS += tests/mount-local SUBDIRS += tests/9p SUBDIRS += tests/rsync SUBDIRS += tests/bigdirs +SUBDIRS += tests/disk-labels SUBDIRS += tests/regressions endif diff --git a/appliance/99-guestfs-serial.rules b/appliance/99-guestfs-serial.rules new file mode 100644 index 000000000..2438958b4 --- /dev/null +++ b/appliance/99-guestfs-serial.rules @@ -0,0 +1,17 @@ +# For libguestfs, create /dev/disk/guestfs/ +# and /dev/disk/guestfs/ + +KERNEL=="sd*[!0-9]", ENV{DEVTYPE}=="disk", ENV{ID_SCSI_SERIAL}=="?*", \ + SYMLINK+="disk/guestfs/$env{ID_SCSI_SERIAL}" +KERNEL=="sd*", ENV{DEVTYPE}=="partition", ENV{ID_SCSI_SERIAL}=="?*", \ + SYMLINK+="disk/guestfs/$env{ID_SCSI_SERIAL}%n" + +# As written, it's likely the above only works with virtio-scsi +# because ID_SCSI_SERIAL is specific to the output of the 'scsi_id' +# program. The following will not work because ID_SERIAL contains +# some unwanted text. + +#KERNEL=="vd*[!0-9]", ATTRS{serial}=="?*", ENV{ID_SERIAL}="$attr{serial}", \ +# SYMLINK+="disk/guestfs/$env{ID_SERIAL}" +#KERNEL=="vd*[0-9]", ATTRS{serial}=="?*", ENV{ID_SERIAL}="$attr{serial}", \ +# SYMLINK+="disk/guestfs/$env{ID_SERIAL}%n" diff --git a/appliance/Makefile.am b/appliance/Makefile.am index 6d8b74a01..848153451 100644 --- a/appliance/Makefile.am +++ b/appliance/Makefile.am @@ -37,7 +37,8 @@ superminfs_DATA = \ supermin.d/base.img \ supermin.d/daemon.img \ supermin.d/init.img \ - supermin.d/hostfiles + supermin.d/hostfiles \ + supermin.d/udev-rules.img # This used to be a configure-generated file (as is update.sh still). # However config.status always touches the destination file, which @@ -91,6 +92,25 @@ supermin.d/init.img: init echo "init" | cpio --quiet -o -H newc > $@-t mv $@-t $@ +# We should put this file in /lib/udev/rules.d, but put it in /etc so +# we don't have to deal with all the UsrMove crap in Fedora. +supermin.d/udev-rules.img: 99-guestfs-serial.rules + mkdir -p supermin.d + rm -f $@ $@-t + rm -rf tmp-u + mkdir -p tmp-u/etc/udev/rules.d + for f in $^; do ln $$f tmp-u/etc/udev/rules.d/$$f; done + ( cd tmp-u && find | cpio --quiet -o -H newc ) > $@-t + rm -rf tmp-u + mv $@-t $@ + +# If installing the daemon, install the udev rules too. + +if INSTALL_DAEMON +udevrulesdir = /lib/udev/rules.d +udevrules_DATA = 99-guestfs-serial.rules +endif + # libguestfs-make-fixed-appliance script and man page. sbin_SCRIPTS = libguestfs-make-fixed-appliance diff --git a/configure.ac b/configure.ac index 7e580b3f7..0422bcb40 100644 --- a/configure.ac +++ b/configure.ac @@ -1376,6 +1376,7 @@ AC_CONFIG_FILES([Makefile tests/charsets/Makefile tests/data/Makefile tests/disks/Makefile + tests/disk-labels/Makefile tests/extra/Makefile tests/guests/Makefile tests/luks/Makefile diff --git a/daemon/devsparts.c b/daemon/devsparts.c index 8f6c5078b..7e319cbee 100644 --- a/daemon/devsparts.c +++ b/daemon/devsparts.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include "c-ctype.h" @@ -282,3 +283,78 @@ do_nr_devices (void) return (int) i; } + +#define GUESTFSDIR "/dev/disk/guestfs" + +char ** +do_list_disk_labels (void) +{ + DIR *dir = NULL; + struct dirent *d; + char *path = NULL, *rawdev = NULL; + DECLARE_STRINGSBUF (ret); + + dir = opendir (GUESTFSDIR); + if (!dir) { + reply_with_perror ("opendir: %s", GUESTFSDIR); + return NULL; + } + + errno = 0; + while ((d = readdir (dir)) != NULL) { + if (d->d_name[0] == '.') + continue; + + if (asprintf (&path, "%s/%s", GUESTFSDIR, d->d_name) == -1) { + reply_with_perror ("asprintf"); + free_stringslen (ret.argv, ret.size); + goto error; + } + + rawdev = realpath (path, NULL); + if (rawdev == NULL) { + reply_with_perror ("realpath: %s", path); + free_stringslen (ret.argv, ret.size); + goto error; + } + + free (path); + path = NULL; + + if (add_string (&ret, d->d_name) == -1) + goto error; + + if (add_string_nodup (&ret, rawdev) == -1) + goto error; + rawdev = NULL; /* buffer now owned by the stringsbuf */ + } + + /* Check readdir didn't fail */ + if (errno != 0) { + reply_with_perror ("readdir: %s", GUESTFSDIR); + free_stringslen (ret.argv, ret.size); + goto error; + } + + /* Close the directory handle */ + if (closedir (dir) == -1) { + reply_with_perror ("closedir: %s", GUESTFSDIR); + free_stringslen (ret.argv, ret.size); + dir = NULL; + goto error; + } + + dir = NULL; + + if (end_stringsbuf (&ret) == -1) + goto error; + + return ret.argv; /* caller frees */ + + error: + if (dir) + closedir (dir); + free (path); + free (rawdev); + return NULL; +} diff --git a/generator/actions.ml b/generator/actions.ml index 713c71629..25d28098f 100644 --- a/generator/actions.ml +++ b/generator/actions.ml @@ -1184,7 +1184,7 @@ not all belong to a single logical operating system { defaults with name = "add_drive"; - style = RErr, [String "filename"], [OBool "readonly"; OString "format"; OString "iface"; OString "name"]; + style = RErr, [String "filename"], [OBool "readonly"; OString "format"; OString "iface"; OString "name"; OString "label"]; once_had_no_optargs = true; fish_alias = ["add"]; config_only = true; shortdesc = "add an image to examine or modify"; @@ -1238,6 +1238,15 @@ The name the drive had in the original guest, e.g. C. This is used as a hint to the guest inspection process if it is available. +=item C