From: Richard Jones Date: Wed, 15 Sep 2010 16:22:29 +0000 (+0100) Subject: New API: list-filesystems: list filesystems X-Git-Tag: 1.5.15~1 X-Git-Url: http://git.annexia.org/?a=commitdiff_plain;h=000c4a82fbd78667849551114b6d08f391324796;p=libguestfs.git New API: list-filesystems: list filesystems This API is a simpler replacement for the guestfish commands list-devices / list-partitions / lvs, in the case where you are just examining a guest by hand to see what it contains. Typical usage and output in guestfish is like this: $ guestfish --ro -a /dev/vg_trick/F13x64 > run > list-filesystems /dev/vda1: ext4 /dev/vg_f13x64/lv_root: ext4 /dev/vg_f13x64/lv_swap: swap It can also be used to replace programs that try to mount devices to determine if they are mountable filesystems. --- diff --git a/generator/generator_actions.ml b/generator/generator_actions.ml index 52c2b7f..2e01507 100644 --- a/generator/generator_actions.ml +++ b/generator/generator_actions.ml @@ -747,7 +747,9 @@ This function cannot decrypt encrypted disks. The caller must do that first (supplying the necessary keys) if the disk is encrypted. -Please read L for more details."); +Please read L for more details. + +See also C."); ("inspect_get_type", (RString "name", [Device "root"]), -1, [], [], @@ -955,6 +957,39 @@ it has no effect."); "\ This returns the enable network flag."); + ("list_filesystems", (RHashtable "fses", []), -1, [], + [], + "list filesystems", + "\ +This inspection command looks for filesystems on partitions, +block devices and logical volumes, returning a list of devices +containing filesystems and their type. + +The return value is a hash, where the keys are the devices +containing filesystems, and the values are the filesystem types. +For example: + + \"/dev/sda1\" => \"ntfs\" + \"/dev/sda2\" => \"ext2\" + \"/dev/vg_guest/lv_root\" => \"ext4\" + \"/dev/vg_guest/lv_swap\" => \"swap\" + +The value can have the special value \"unknown\", meaning the +content of the device is undetermined or empty. +\"swap\" means a Linux swap partition. + +This command runs other libguestfs commands, which might include +C and C, and therefore you should +use this soon after launch and only when nothing is mounted. + +Not all of the filesystems returned will be mountable. In +particular, swap partitions are returned in the list. Also +this command does not check that each filesystem +found is valid and mountable, and some filesystems might +be mountable but require special options. Filesystems may +not all belong to a single logical operating system +(use C to look for OSes)."); + ] (* daemon_functions are any functions which cause some action @@ -1064,7 +1099,9 @@ should probably use C instead."); "\ List all the block devices. -The full block device names are returned, eg. C"); +The full block device names are returned, eg. C. + +See also C."); ("list_partitions", (RStringList "partitions", []), 8, [], [InitBasicFS, Always, TestOutputListOfDevices ( @@ -1079,7 +1116,9 @@ List all the partitions detected on all block devices. The full partition device names are returned, eg. C This does not return logical volumes. For that you will need to -call C."); +call C. + +See also C."); ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"], [InitBasicFSonLVM, Always, TestOutputListOfDevices ( @@ -1143,7 +1182,7 @@ of the L command. This returns a list of the logical volume device names (eg. C). -See also C."); +See also C, C."); ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"], [], (* XXX how to test? *) diff --git a/src/inspect.c b/src/inspect.c index 74ae29f..11a5374 100644 --- a/src/inspect.c +++ b/src/inspect.c @@ -1295,3 +1295,140 @@ guestfs__inspect_get_filesystems (guestfs_h *g, const char *root) return ret; } + +/* List filesystems. + * + * The current implementation just uses guestfs_vfs_type and doesn't + * try mounting anything, but we reserve the right in future to try + * mounting filesystems. + */ + +static void remove_from_list (char **list, const char *item); +static void check_with_vfs_type (guestfs_h *g, const char *dev, char ***ret, size_t *ret_size); + +char ** +guestfs__list_filesystems (guestfs_h *g) +{ + size_t i; + char **ret; + size_t ret_size; + + ret = safe_malloc (g, sizeof (char *)); + ret[0] = NULL; + ret_size = 0; + + /* Look to see if any devices directly contain filesystems + * (RHBZ#590167). However vfs-type will fail to tell us anything + * useful about devices which just contain partitions, so we also + * get the list of partitions and exclude the corresponding devices + * by using part-to-dev. + */ + char **devices; + devices = guestfs_list_devices (g); + if (devices == NULL) { + free_string_list (ret); + return NULL; + } + char **partitions; + partitions = guestfs_list_partitions (g); + if (partitions == NULL) { + free_string_list (devices); + free_string_list (ret); + return NULL; + } + + for (i = 0; partitions[i] != NULL; ++i) { + char *dev = guestfs_part_to_dev (g, partitions[i]); + if (dev) + remove_from_list (devices, dev); + free (dev); + } + + /* Use vfs-type to check for filesystems on devices. */ + for (i = 0; devices[i] != NULL; ++i) + check_with_vfs_type (g, devices[i], &ret, &ret_size); + free_string_list (devices); + + /* Use vfs-type to check for filesystems on partitions. */ + for (i = 0; partitions[i] != NULL; ++i) + check_with_vfs_type (g, partitions[i], &ret, &ret_size); + free_string_list (partitions); + + if (feature_available (g, "lvm2")) { + /* Use vfs-type to check for filesystems on LVs. */ + char **lvs; + lvs = guestfs_lvs (g); + if (lvs == NULL) { + free_string_list (ret); + return NULL; + } + + for (i = 0; lvs[i] != NULL; ++i) + check_with_vfs_type (g, lvs[i], &ret, &ret_size); + free_string_list (lvs); + } + + return ret; +} + +/* If 'item' occurs in 'list', remove and free it. */ +static void +remove_from_list (char **list, const char *item) +{ + size_t i; + + for (i = 0; list[i] != NULL; ++i) + if (STREQ (list[i], item)) { + free (list[i]); + for (; list[i+1] != NULL; ++i) + list[i] = list[i+1]; + list[i] = NULL; + return; + } +} + +/* Use vfs-type to look for a filesystem of some sort on 'dev'. + * Apart from some types which we ignore, add the result to the + * 'ret' string list. + */ +static void +check_with_vfs_type (guestfs_h *g, const char *device, + char ***ret, size_t *ret_size) +{ + char *v; + + guestfs_error_handler_cb old_error_cb = g->error_cb; + g->error_cb = NULL; + char *vfs_type = guestfs_vfs_type (g, device); + g->error_cb = old_error_cb; + + if (!vfs_type) + v = safe_strdup (g, "unknown"); + else { + /* Ignore all "*_member" strings. In libblkid these are returned + * for things which are members of some RAID or LVM set, most + * importantly "LVM2_member" which is a PV. + */ + size_t n = strlen (vfs_type); + if (n >= 7 && STREQ (&vfs_type[n-7], "_member")) { + free (vfs_type); + return; + } + + /* Ignore LUKS-encrypted partitions. These are also containers. */ + if (STREQ (vfs_type, "crypto_LUKS")) { + free (vfs_type); + return; + } + + v = vfs_type; + } + + /* Extend the return array. */ + size_t i = *ret_size; + *ret_size += 2; + *ret = safe_realloc (g, *ret, (*ret_size + 1) * sizeof (char *)); + (*ret)[i] = safe_strdup (g, device); + (*ret)[i+1] = v; + (*ret)[i+2] = NULL; +}