Give find_all_disks() external linkage, moving it to a new source file called "disks.c". Move the helpers called solely by find_all_disks() as well, such as device_contains() and partition_parent(). Move the global variables "all_disks" and "all_removable" too. compare_strings() is now referenced from "main.c" and "disks.c". No functional changes.
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2124538 Signed-off-by: Laszlo Ersek <ler...@redhat.com> --- Makefile.am | 1 + p2v.h | 16 +- disks.c | 185 ++++++++++++++++++++ main.c | 157 ----------------- 4 files changed, 198 insertions(+), 161 deletions(-) diff --git a/Makefile.am b/Makefile.am index 19c5f04c2fab..4a47a97251e9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -108,6 +108,7 @@ virt_p2v_SOURCES = \ libguestfs/libxml2-writer-macros.h \ conversion.c \ cpuid.c \ + disks.c \ gui.c \ gui-gtk2-compat.h \ gui-gtk3-compat.h \ diff --git a/p2v.h b/p2v.h index e91c47c36428..e7f0b9e467fd 100644 --- a/p2v.h +++ b/p2v.h @@ -40,11 +40,9 @@ # define P2V_GCC_VERSION 0 #endif -/* All disks / removable media / network interfaces discovered - * when the program started. Do not change these. +/* All network interfaces discovered when the program started. Do not change + * this. */ -extern char **all_disks; -extern char **all_removable; extern char **all_interfaces; /* True if running inside the virt-p2v ISO environment. Various @@ -68,6 +66,16 @@ struct cpu_topo { extern void get_cpu_topology (struct cpu_topo *topo); extern void get_cpu_config (struct cpu_config *); +/* disks.c + * + * All disks / removable media discovered (possibly with one call to + * find_all_disks()) when the program started. Do not change these, or call + * find_all_disks() more than once. + */ +extern char **all_disks; +extern char **all_removable; +extern void find_all_disks (void); + /* rtc.c */ extern void get_rtc_config (struct rtc_config *); diff --git a/disks.c b/disks.c new file mode 100644 index 000000000000..4f94719787ac --- /dev/null +++ b/disks.c @@ -0,0 +1,185 @@ +/* virt-p2v + * Copyright (C) 2009-2022 Red Hat Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <config.h> + +#include <dirent.h> +#include <errno.h> +#include <error.h> +#include <inttypes.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/types.h> + +#if MAJOR_IN_MKDEV +#include <sys/mkdev.h> +#elif MAJOR_IN_SYSMACROS +#include <sys/sysmacros.h> +/* else it's in sys/types.h, included above */ +#endif + +#include "p2v.h" + +char **all_disks; +char **all_removable; + +/** + * Get parent device of a partition. + * + * Returns C<0> if no parent device could be found. + */ +static dev_t +partition_parent (dev_t part_dev) +{ + CLEANUP_FCLOSE FILE *fp = NULL; + CLEANUP_FREE char *path = NULL, *content = NULL; + size_t len = 0; + unsigned parent_major, parent_minor; + + if (asprintf (&path, "/sys/dev/block/%ju:%ju/../dev", + (uintmax_t) major (part_dev), + (uintmax_t) minor (part_dev)) == -1) + error (EXIT_FAILURE, errno, "asprintf"); + + fp = fopen (path, "r"); + if (fp == NULL) + return 0; + + if (getline (&content, &len, fp) == -1) + error (EXIT_FAILURE, errno, "getline"); + + if (sscanf (content, "%u:%u", &parent_major, &parent_minor) != 2) + return 0; + + return makedev (parent_major, parent_minor); +} + +/** + * Return true if the named device (eg. C<dev == "sda">) contains the + * root filesystem. C<root_device> is the major:minor of the root + * filesystem (eg. C<8:1> if the root filesystem was F</dev/sda1>). + * + * This doesn't work for LVs and so on. However we only really care + * if this test works on the P2V ISO where the root device is a + * regular partition. + */ +static int +device_contains (const char *dev, dev_t root_device) +{ + struct stat statbuf; + CLEANUP_FREE char *dev_name = NULL; + dev_t root_device_parent; + + if (asprintf (&dev_name, "/dev/%s", dev) == -1) + error (EXIT_FAILURE, errno, "asprintf"); + + if (stat (dev_name, &statbuf) == -1) + return 0; + + /* See if dev is the root_device. */ + if (statbuf.st_rdev == root_device) + return 1; + + /* See if dev is the parent device of the root_device. */ + root_device_parent = partition_parent (root_device); + if (root_device_parent == 0) + return 0; + if (statbuf.st_rdev == root_device_parent) + return 1; + + return 0; +} + +/** + * Enumerate all disks in F</sys/block> and add them to the global + * C<all_disks> and C<all_removable> arrays. + */ +void +find_all_disks (void) +{ + DIR *dir; + struct dirent *d; + size_t nr_disks = 0, nr_removable = 0; + dev_t root_device = 0; + struct stat statbuf; + + if (stat ("/", &statbuf) == 0) + root_device = statbuf.st_dev; + + /* The default list of disks is everything in /sys/block which + * matches the common patterns for disk names. + */ + dir = opendir ("/sys/block"); + if (!dir) + error (EXIT_FAILURE, errno, "opendir"); + + for (;;) { + errno = 0; + d = readdir (dir); + if (!d) break; + + if (STRPREFIX (d->d_name, "cciss!") || + STRPREFIX (d->d_name, "hd") || + STRPREFIX (d->d_name, "nvme") || + STRPREFIX (d->d_name, "sd") || + STRPREFIX (d->d_name, "ubd") || + STRPREFIX (d->d_name, "vd")) { + char *p; + + /* Skip the device containing the root filesystem. */ + if (device_contains (d->d_name, root_device)) + continue; + + nr_disks++; + all_disks = realloc (all_disks, sizeof (char *) * (nr_disks + 1)); + if (!all_disks) + error (EXIT_FAILURE, errno, "realloc"); + + all_disks[nr_disks-1] = strdup (d->d_name); + + /* cciss device /dev/cciss/c0d0 will be /sys/block/cciss!c0d0 */ + p = strchr (all_disks[nr_disks-1], '!'); + if (p) *p = '/'; + + all_disks[nr_disks] = NULL; + } + else if (STRPREFIX (d->d_name, "sr")) { + nr_removable++; + all_removable = realloc (all_removable, + sizeof (char *) * (nr_removable + 1)); + if (!all_removable) + error (EXIT_FAILURE, errno, "realloc"); + all_removable[nr_removable-1] = strdup (d->d_name); + all_removable[nr_removable] = NULL; + } + } + + /* Check readdir didn't fail */ + if (errno != 0) + error (EXIT_FAILURE, errno, "readdir: %s", "/sys/block"); + + /* Close the directory handle */ + if (closedir (dir) == -1) + error (EXIT_FAILURE, errno, "closedir: %s", "/sys/block"); + + if (all_disks) + qsort (all_disks, nr_disks, sizeof (char *), compare_strings); + if (all_removable) + qsort (all_removable, nr_removable, sizeof (char *), compare_strings); +} diff --git a/main.c b/main.c index ef191e9e34be..a83de71b7c73 100644 --- a/main.c +++ b/main.c @@ -20,7 +20,6 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <inttypes.h> #include <unistd.h> #include <getopt.h> #include <fcntl.h> @@ -30,14 +29,6 @@ #include <locale.h> #include <libintl.h> #include <sys/types.h> -#include <sys/stat.h> - -#if MAJOR_IN_MKDEV -#include <sys/mkdev.h> -#elif MAJOR_IN_SYSMACROS -#include <sys/sysmacros.h> -/* else it's in sys/types.h, included above */ -#endif /* errors in <gtk.h> */ #pragma GCC diagnostic push @@ -51,8 +42,6 @@ #include "ignore-value.h" #include "p2v.h" -char **all_disks; -char **all_removable; char **all_interfaces; int is_iso_environment = 0; int feature_colours_option = 0; @@ -61,7 +50,6 @@ static const char *test_disk = NULL; static void udevadm_settle (void); static void set_config_defaults (struct config *config); -static void find_all_disks (void); static void find_all_interfaces (void); enum { HELP_OPTION = CHAR_MAX + 1 }; @@ -372,151 +360,6 @@ set_config_defaults (struct config *config) config->output.storage = strdup ("/var/tmp"); } -/** - * Get parent device of a partition. - * - * Returns C<0> if no parent device could be found. - */ -static dev_t -partition_parent (dev_t part_dev) -{ - CLEANUP_FCLOSE FILE *fp = NULL; - CLEANUP_FREE char *path = NULL, *content = NULL; - size_t len = 0; - unsigned parent_major, parent_minor; - - if (asprintf (&path, "/sys/dev/block/%ju:%ju/../dev", - (uintmax_t) major (part_dev), - (uintmax_t) minor (part_dev)) == -1) - error (EXIT_FAILURE, errno, "asprintf"); - - fp = fopen (path, "r"); - if (fp == NULL) - return 0; - - if (getline (&content, &len, fp) == -1) - error (EXIT_FAILURE, errno, "getline"); - - if (sscanf (content, "%u:%u", &parent_major, &parent_minor) != 2) - return 0; - - return makedev (parent_major, parent_minor); -} - -/** - * Return true if the named device (eg. C<dev == "sda">) contains the - * root filesystem. C<root_device> is the major:minor of the root - * filesystem (eg. C<8:1> if the root filesystem was F</dev/sda1>). - * - * This doesn't work for LVs and so on. However we only really care - * if this test works on the P2V ISO where the root device is a - * regular partition. - */ -static int -device_contains (const char *dev, dev_t root_device) -{ - struct stat statbuf; - CLEANUP_FREE char *dev_name = NULL; - dev_t root_device_parent; - - if (asprintf (&dev_name, "/dev/%s", dev) == -1) - error (EXIT_FAILURE, errno, "asprintf"); - - if (stat (dev_name, &statbuf) == -1) - return 0; - - /* See if dev is the root_device. */ - if (statbuf.st_rdev == root_device) - return 1; - - /* See if dev is the parent device of the root_device. */ - root_device_parent = partition_parent (root_device); - if (root_device_parent == 0) - return 0; - if (statbuf.st_rdev == root_device_parent) - return 1; - - return 0; -} - -/** - * Enumerate all disks in F</sys/block> and add them to the global - * C<all_disks> and C<all_removable> arrays. - */ -static void -find_all_disks (void) -{ - DIR *dir; - struct dirent *d; - size_t nr_disks = 0, nr_removable = 0; - dev_t root_device = 0; - struct stat statbuf; - - if (stat ("/", &statbuf) == 0) - root_device = statbuf.st_dev; - - /* The default list of disks is everything in /sys/block which - * matches the common patterns for disk names. - */ - dir = opendir ("/sys/block"); - if (!dir) - error (EXIT_FAILURE, errno, "opendir"); - - for (;;) { - errno = 0; - d = readdir (dir); - if (!d) break; - - if (STRPREFIX (d->d_name, "cciss!") || - STRPREFIX (d->d_name, "hd") || - STRPREFIX (d->d_name, "nvme") || - STRPREFIX (d->d_name, "sd") || - STRPREFIX (d->d_name, "ubd") || - STRPREFIX (d->d_name, "vd")) { - char *p; - - /* Skip the device containing the root filesystem. */ - if (device_contains (d->d_name, root_device)) - continue; - - nr_disks++; - all_disks = realloc (all_disks, sizeof (char *) * (nr_disks + 1)); - if (!all_disks) - error (EXIT_FAILURE, errno, "realloc"); - - all_disks[nr_disks-1] = strdup (d->d_name); - - /* cciss device /dev/cciss/c0d0 will be /sys/block/cciss!c0d0 */ - p = strchr (all_disks[nr_disks-1], '!'); - if (p) *p = '/'; - - all_disks[nr_disks] = NULL; - } - else if (STRPREFIX (d->d_name, "sr")) { - nr_removable++; - all_removable = realloc (all_removable, - sizeof (char *) * (nr_removable + 1)); - if (!all_removable) - error (EXIT_FAILURE, errno, "realloc"); - all_removable[nr_removable-1] = strdup (d->d_name); - all_removable[nr_removable] = NULL; - } - } - - /* Check readdir didn't fail */ - if (errno != 0) - error (EXIT_FAILURE, errno, "readdir: %s", "/sys/block"); - - /* Close the directory handle */ - if (closedir (dir) == -1) - error (EXIT_FAILURE, errno, "closedir: %s", "/sys/block"); - - if (all_disks) - qsort (all_disks, nr_disks, sizeof (char *), compare_strings); - if (all_removable) - qsort (all_removable, nr_removable, sizeof (char *), compare_strings); -} - /** * Enumerate all network interfaces in F</sys/class/net> and add them * to the global C<all_interfaces> array. _______________________________________________ Libguestfs mailing list Libguestfs@redhat.com https://listman.redhat.com/mailman/listinfo/libguestfs