From 83c910778cc461dd72421b52d4fae7df7426bff6 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Tue, 9 Dec 2014 14:06:18 +0000 Subject: [PATCH] inspection: Not an installer if there are multiple partitions (RHBZ#1171666). Regular EFI disks have /EFI on the first (VFAT) partition, but they are not installers. Fix this by only considering something to be an installer if it has a single partition (or whole disks like ISOs). Implementing this is quite complex since when checking a filesystem, we don't have information about whether we are even looking at a partition, nor about whether it's the first partition out of how many. The majority of the commit is changing the code to collect that information. (cherry picked from commit bdf772db3286487adefa56b966435f2dd638e0a8) --- src/guestfs-internal.h | 1 + src/inspect-fs-unix.c | 31 ++++--------------------------- src/inspect-fs.c | 44 ++++++++++++++++++++++++++++++++++++++------ src/inspect.c | 22 ++++++++++++++++++++++ 4 files changed, 65 insertions(+), 33 deletions(-) diff --git a/src/guestfs-internal.h b/src/guestfs-internal.h index d9ccf5f..65f3388 100644 --- a/src/guestfs-internal.h +++ b/src/guestfs-internal.h @@ -751,6 +751,7 @@ extern int guestfs___set_backend (guestfs_h *g, const char *method); extern void guestfs___free_inspect_info (guestfs_h *g); extern char *guestfs___download_to_tmp (guestfs_h *g, struct inspect_fs *fs, const char *filename, const char *basename, uint64_t max_size); extern struct inspect_fs *guestfs___search_for_root (guestfs_h *g, const char *root); +extern int guestfs___is_partition (guestfs_h *g, const char *partition); /* inspect-fs.c */ extern int guestfs___is_file_nocase (guestfs_h *g, const char *); diff --git a/src/inspect-fs-unix.c b/src/inspect-fs-unix.c index fb5cc1a..8778e92 100644 --- a/src/inspect-fs-unix.c +++ b/src/inspect-fs-unix.c @@ -185,7 +185,6 @@ static int add_fstab_entry (guestfs_h *g, struct inspect_fs *fs, static char *resolve_fstab_device (guestfs_h *g, const char *spec, Hash_table *md_map); static int inspect_with_augeas (guestfs_h *g, struct inspect_fs *fs, const char **configfiles, int (*f) (guestfs_h *, struct inspect_fs *)); -static int is_partition (guestfs_h *g, const char *partition); /* Hash structure for uuid->path lookups */ typedef struct md_uuid { @@ -1436,7 +1435,7 @@ resolve_fstab_device_xdev (guestfs_h *g, const char *type, const char *disk, ITER_DRIVES (g, i, drv) { if (drv->name && STREQ (drv->name, name)) { device = safe_asprintf (g, "%s%s", devices[i], part); - if (!is_partition (g, device)) { + if (!guestfs___is_partition (g, device)) { free (device); return 0; } @@ -1463,7 +1462,7 @@ resolve_fstab_device_xdev (guestfs_h *g, const char *type, const char *disk, */ if (i < count) { device = safe_asprintf (g, "%s%s", devices[i], part); - if (!is_partition (g, device)) { + if (!guestfs___is_partition (g, device)) { free (device); return 0; } @@ -1496,7 +1495,7 @@ resolve_fstab_device_cciss (guestfs_h *g, const char *disk, const char *part, if (drv->name && STREQ (drv->name, disk)) { if (part) { device = safe_asprintf (g, "%s%s", devices[i], part); - if (!is_partition (g, device)) { + if (!guestfs___is_partition (g, device)) { free (device); return 0; } @@ -1541,7 +1540,7 @@ resolve_fstab_device_diskbyid (guestfs_h *g, const char *part, /* Make the partition name and check it exists. */ device = safe_asprintf (g, "/dev/sda%s", part); - if (!is_partition (g, device)) { + if (!guestfs___is_partition (g, device)) { free (device); return 0; } @@ -1753,25 +1752,3 @@ make_augeas_path_expression (guestfs_h *g, const char **configfiles) debug (g, "augeas pathexpr = %s", ret); return ret; } - -static int -is_partition (guestfs_h *g, const char *partition) -{ - CLEANUP_FREE char *device = NULL; - - guestfs_push_error_handler (g, NULL, NULL); - - if ((device = guestfs_part_to_dev (g, partition)) == NULL) { - guestfs_pop_error_handler (g); - return 0; - } - - if (guestfs_device_index (g, device) == -1) { - guestfs_pop_error_handler (g); - return 0; - } - - guestfs_pop_error_handler (g); - - return 1; -} diff --git a/src/inspect-fs.c b/src/inspect-fs.c index 539d814..686d1ae 100644 --- a/src/inspect-fs.c +++ b/src/inspect-fs.c @@ -83,6 +83,7 @@ static int check_filesystem (guestfs_h *g, const char *mountable, const struct guestfs_internal_mountable *m, int whole_device); static int extend_fses (guestfs_h *g); +static int get_partition_context (guestfs_h *g, const char *partition, int *partnum_ret, int *nr_partitions_ret); /* Find out if 'device' contains a filesystem. If it does, add * another entry in g->fses. @@ -175,17 +176,18 @@ check_filesystem (guestfs_h *g, const char *mountable, const struct guestfs_internal_mountable *m, int whole_device) { + int partnum = -1, nr_partitions = -1; /* Not CLEANUP_FREE, as it will be cleaned up with inspection info */ char *windows_systemroot = NULL; if (extend_fses (g) == -1) return -1; - int partnum = -1; - if (!whole_device && m->im_type == MOUNTABLE_DEVICE) { - guestfs_push_error_handler (g, NULL, NULL); - partnum = guestfs_part_to_partnum (g, m->im_device); - guestfs_pop_error_handler (g); + if (!whole_device && m->im_type == MOUNTABLE_DEVICE && + guestfs___is_partition (g, m->im_device)) { + if (get_partition_context (g, m->im_device, + &partnum, &nr_partitions) == -1) + return -1; } struct inspect_fs *fs = &g->fses[g->nr_fses-1]; @@ -324,7 +326,7 @@ check_filesystem (guestfs_h *g, const char *mountable, * Skip these checks if it's not a whole device (eg. CD) or the * first partition (eg. bootable USB key). */ - else if ((whole_device || partnum == 1) && + else if ((whole_device || (partnum == 1 && nr_partitions == 1)) && (guestfs_is_file (g, "/isolinux/isolinux.cfg") > 0 || guestfs_is_dir (g, "/EFI/BOOT") > 0 || guestfs_is_file (g, "/images/install.img") > 0 || @@ -369,6 +371,36 @@ extend_fses (guestfs_h *g) return 0; } +/* Given a partition (eg. /dev/sda2) then return the partition number + * (eg. 2) and the total number of other partitions. + */ +static int +get_partition_context (guestfs_h *g, const char *partition, + int *partnum_ret, int *nr_partitions_ret) +{ + int partnum, nr_partitions; + CLEANUP_FREE char *device = NULL; + CLEANUP_FREE_PARTITION_LIST struct guestfs_partition_list *partitions = NULL; + + partnum = guestfs_part_to_partnum (g, partition); + if (partnum == -1) + return -1; + + device = guestfs_part_to_dev (g, partition); + if (device == NULL) + return -1; + + partitions = guestfs_part_list (g, device); + if (partitions == NULL) + return -1; + + nr_partitions = partitions->len; + + *partnum_ret = partnum; + *nr_partitions_ret = nr_partitions; + return 0; +} + int guestfs___is_file_nocase (guestfs_h *g, const char *path) { diff --git a/src/inspect.c b/src/inspect.c index 9248b06..03d870f 100644 --- a/src/inspect.c +++ b/src/inspect.c @@ -590,3 +590,25 @@ guestfs___search_for_root (guestfs_h *g, const char *root) root); return NULL; } + +int +guestfs___is_partition (guestfs_h *g, const char *partition) +{ + CLEANUP_FREE char *device = NULL; + + guestfs_push_error_handler (g, NULL, NULL); + + if ((device = guestfs_part_to_dev (g, partition)) == NULL) { + guestfs_pop_error_handler (g); + return 0; + } + + if (guestfs_device_index (g, device) == -1) { + guestfs_pop_error_handler (g); + return 0; + } + + guestfs_pop_error_handler (g); + + return 1; +} -- 1.8.3.1