From a9d9b7d3cf9fa9928498273974830e9ba2002e5f Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Fri, 24 Jun 2016 14:45:05 +0100 Subject: [PATCH] p2v: Refactor into get_blockdev_size and get_blockdev_model functions. This is just refactoring, but it reveals and fixes a bug too. The size_gb field was left as NULL when the --test-disk option was used. Apparently passing NULL to gtk_list_store_set is fine, but just in case I replaced it with "". (cherry picked from commit 68ff3ffd1de7b72255ee5098c0bfef90e6236cb5) --- p2v/gui.c | 40 ++++++++----------------------------- p2v/p2v.h | 2 ++ p2v/utils.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 32 deletions(-) diff --git a/p2v/gui.c b/p2v/gui.c index 7414037..1bae4d8 100644 --- a/p2v/gui.c +++ b/p2v/gui.c @@ -869,47 +869,23 @@ populate_disks (GtkTreeView *disks_list) G_TYPE_STRING, G_TYPE_STRING); if (all_disks != NULL) { for (i = 0; all_disks[i] != NULL; ++i) { - CLEANUP_FREE char *size_filename = NULL; - CLEANUP_FREE char *model_filename = NULL; - CLEANUP_FREE char *size_str = NULL; + uint64_t size; CLEANUP_FREE char *size_gb = NULL; CLEANUP_FREE char *model = NULL; - uint64_t size; - if (asprintf (&size_filename, "/sys/block/%s/size", - all_disks[i]) == -1) { - perror ("asprintf"); - exit (EXIT_FAILURE); - } - if (g_file_get_contents (size_filename, &size_str, NULL, NULL) && - sscanf (size_str, "%" SCNu64, &size) == 1) { - size /= 2*1024*1024; /* size from kernel is given in sectors? */ - if (asprintf (&size_gb, "%" PRIu64, size) == -1) { - perror ("asprintf"); - exit (EXIT_FAILURE); - } - } - - if (asprintf (&model_filename, "/sys/block/%s/device/model", - all_disks[i]) == -1) { - perror ("asprintf"); - exit (EXIT_FAILURE); - } - if (g_file_get_contents (model_filename, &model, NULL, NULL)) { - /* Need to chomp trailing \n from the content. */ - size_t len = strlen (model); - if (len > 0 && model[len-1] == '\n') - model[len-1] = '\0'; - } else { - model = strdup (""); + if (all_disks[i][0] != '/') { /* not using --test-disk */ + size = get_blockdev_size (all_disks[i]); + if (asprintf (&size_gb, "%" PRIu64, size) == -1) + error (EXIT_FAILURE, errno, "asprintf"); + model = get_blockdev_model (all_disks[i]); } gtk_list_store_append (disks_store, &iter); gtk_list_store_set (disks_store, &iter, DISKS_COL_CONVERT, TRUE, DISKS_COL_DEVICE, all_disks[i], - DISKS_COL_SIZE, size_gb, - DISKS_COL_MODEL, model, + DISKS_COL_SIZE, size_gb ? size_gb : "", + DISKS_COL_MODEL, model ? model : "", -1); } } diff --git a/p2v/p2v.h b/p2v/p2v.h index 49c97b6..40b05b8 100644 --- a/p2v/p2v.h +++ b/p2v/p2v.h @@ -131,6 +131,8 @@ extern mexp_h *start_remote_connection (struct config *, const char *remote_dir, extern const char *get_ssh_error (void); /* utils.c */ +extern uint64_t get_blockdev_size (const char *dev); +extern char *get_blockdev_model (const char *dev); extern char *get_if_addr (const char *if_name); extern char *get_if_vendor (const char *if_name, int truncate); extern void wait_network_online (const struct config *); diff --git a/p2v/utils.c b/p2v/utils.c index 3781a8d..18c2b7c 100644 --- a/p2v/utils.c +++ b/p2v/utils.c @@ -20,9 +20,12 @@ #include #include +#include #include #include #include +#include +#include #include #include @@ -38,6 +41,68 @@ } \ } while (0) +/** + * Return size of a block device, from F/size>. + * + * This function always succeeds, or else exits (since we expect + * C to always be valid and the C file to always exist). + */ +uint64_t +get_blockdev_size (const char *dev) +{ + CLEANUP_FCLOSE FILE *fp = NULL; + CLEANUP_FREE char *path = NULL; + CLEANUP_FREE char *size_str = NULL; + size_t len; + uint64_t size; + + if (asprintf (&path, "/sys/block/%s/size", dev) == -1) + error (EXIT_FAILURE, errno, "asprintf"); + + fp = fopen (path, "r"); + if (fp == NULL) + error (EXIT_FAILURE, errno, "fopen: %s", path); + if (getline (&size_str, &len, fp) == -1) + error (EXIT_FAILURE, errno, "getline: %s", path); + + if (sscanf (size_str, "%" SCNu64, &size) != 1) + error (EXIT_FAILURE, 0, "cannot parse %s: %s", path, size_str); + + size /= 2*1024*1024; /* size from kernel is given in sectors? */ + return size; +} + +/** + * Return model of a block device, from F/device/model>. + * + * Returns C if the file was not found. The caller must + * free the returned string. + */ +char * +get_blockdev_model (const char *dev) +{ + CLEANUP_FCLOSE FILE *fp = NULL; + CLEANUP_FREE char *path = NULL; + char *model = NULL; + size_t len = 0; + ssize_t n; + + if (asprintf (&path, "/sys/block/%s/device/model", dev) == -1) + error (EXIT_FAILURE, errno, "asprintf"); + fp = fopen (path, "r"); + if (fp == NULL) { + perror (path); + return NULL; + } + if ((n = getline (&model, &len, fp)) == -1) { + perror (path); + free (model); + return NULL; + } + CHOMP (model, n); + return model; +} + /* Return contents of /sys/class/net//address (if found). */ char * get_if_addr (const char *if_name) -- 1.8.3.1