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
><fs> run
><fs> 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.
This commit is contained in:
Richard Jones
2010-09-15 17:22:29 +01:00
parent ffd4820ffe
commit 000c4a82fb
2 changed files with 180 additions and 4 deletions

View File

@@ -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<guestfs(3)/INSPECTION> for more details.");
Please read L<guestfs(3)/INSPECTION> for more details.
See also C<guestfs_list_filesystems>.");
("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<guestfs_mount> and C<guestfs_umount>, 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<guestfs_inspect_os> to look for OSes).");
]
(* daemon_functions are any functions which cause some action
@@ -1064,7 +1099,9 @@ should probably use C<guestfs_readdir> instead.");
"\
List all the block devices.
The full block device names are returned, eg. C</dev/sda>");
The full block device names are returned, eg. C</dev/sda>.
See also C<guestfs_list_filesystems>.");
("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</dev/sda1>
This does not return logical volumes. For that you will need to
call C<guestfs_lvs>.");
call C<guestfs_lvs>.
See also C<guestfs_list_filesystems>.");
("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
[InitBasicFSonLVM, Always, TestOutputListOfDevices (
@@ -1143,7 +1182,7 @@ of the L<lvs(8)> command.
This returns a list of the logical volume device names
(eg. C</dev/VolGroup00/LogVol00>).
See also C<guestfs_lvs_full>.");
See also C<guestfs_lvs_full>, C<guestfs_list_filesystems>.");
("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
[], (* XXX how to test? *)

View File

@@ -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;
}