/* Simple implementation of decryption: look for any crypto_LUKS * partitions and decrypt them, then rescan for VGs. This only works * for Fedora whole-disk encryption. WIP to make this work for other * encryption schemes. */ void inspect_do_decrypt (void) { CLEANUP_FREE_STRING_LIST char **partitions = guestfs_list_partitions (g); if (partitions == NULL) exit (EXIT_FAILURE); int need_rescan = 0; size_t i; for (i = 0; partitions[i] != NULL; ++i) { CLEANUP_FREE char *type = guestfs_vfs_type (g, partitions[i]); if (type && STREQ (type, "crypto_LUKS")) { char mapname[32]; make_mapname (partitions[i], mapname, sizeof mapname); CLEANUP_FREE char *key = read_key (partitions[i]); /* XXX Should we call guestfs_luks_open_ro if readonly flag * is set? This might break 'mount_ro'. */ if (guestfs_luks_open (g, partitions[i], key, mapname) == -1) exit (EXIT_FAILURE); need_rescan = 1; } } if (need_rescan) { if (guestfs_vgscan (g) == -1) exit (EXIT_FAILURE); if (guestfs_vg_activate_all (g, 1) == -1) exit (EXIT_FAILURE); } }
static void do_output_partitions (void) { size_t i; CLEANUP_FREE_STRING_LIST char **parts = guestfs_list_partitions (g); if (parts == NULL) exit (EXIT_FAILURE); for (i = 0; parts[i] != NULL; ++i) { CLEANUP_FREE char *dev = NULL, *parent_name = NULL, *canonical_name = NULL; const char *parents[2]; int64_t size = -1; int mbr_id = -1; dev = guestfs_canonical_device_name (g, parts[i]); if (!dev) exit (EXIT_FAILURE); if ((columns & COLUMN_SIZE)) { size = guestfs_blockdev_getsize64 (g, parts[i]); if (size == -1) exit (EXIT_FAILURE); } if ((columns & COLUMN_PARENTS)) { parent_name = guestfs_part_to_dev (g, parts[i]); if (parent_name == NULL) exit (EXIT_FAILURE); if ((columns & COLUMN_MBR)) mbr_id = get_mbr_id (parts[i], parent_name); canonical_name = guestfs_canonical_device_name (g, parent_name); if (!canonical_name) exit (EXIT_FAILURE); parents[0] = canonical_name; parents[1] = NULL; } write_row (dev, "partition", NULL, NULL, mbr_id, size, (char **) parents, NULL); } }
/* Matches Windows registry HKLM\SYSYTEM\MountedDevices\DosDevices blob to * to libguestfs GPT partition device. For GPT disks, the blob is made of * "DMIO:ID:" prefix followed by the GPT partition GUID. */ static char * map_registry_disk_blob_gpt (guestfs_h *g, const void *blob) { CLEANUP_FREE_STRING_LIST char **parts = NULL; CLEANUP_FREE char *blob_guid = extract_guid_from_registry_blob (g, blob); size_t i; parts = guestfs_list_partitions (g); if (parts == NULL) return NULL; for (i = 0; parts[i] != NULL; ++i) { CLEANUP_FREE char *fs_guid = NULL; int partnum; CLEANUP_FREE char *device = NULL; CLEANUP_FREE char *type = NULL; partnum = guestfs_part_to_partnum (g, parts[i]); if (partnum == -1) continue; device = guestfs_part_to_dev (g, parts[i]); if (device == NULL) continue; type = guestfs_part_get_parttype (g, device); if (type == NULL) continue; if (STRCASENEQ (type, "gpt")) continue; /* get the GPT parition GUID from the partition block device */ fs_guid = guestfs_part_get_gpt_guid (g, device, partnum); if (fs_guid == NULL) continue; /* if both GUIDs match, we have found the mapping for our device */ if (STRCASEEQ (fs_guid, blob_guid)) return safe_strdup (g, parts[i]); } return NULL; }
char * complete_dest_paths_generator (const char *text, int state) { #ifdef HAVE_LIBREADLINE static size_t len, index; static struct word *words = NULL; static size_t nr_words = 0; guestfs_error_handler_cb old_error_cb; void *old_error_cb_data; /* Temporarily replace the error handler so that messages don't * get printed to stderr while we are issuing commands. */ #define SAVE_ERROR_CB \ old_error_cb = guestfs_get_error_handler (g, &old_error_cb_data); \ guestfs_set_error_handler (g, NULL, NULL); /* Restore error handler. */ #define RESTORE_ERROR_CB \ guestfs_set_error_handler (g, old_error_cb, old_error_cb_data); if (!state) { char **strs; len = strlen (text); index = 0; if (words) free_words (words, nr_words); words = NULL; nr_words = 0; SAVE_ERROR_CB /* Silently do nothing if an allocation fails */ #define APPEND_STRS_AND_FREE \ do { \ if (strs) { \ size_t i; \ size_t n = count_strings (strs); \ \ if ( n > 0 && ! xalloc_oversized (nr_words + n, sizeof (struct word))) { \ struct word *w; \ w = realloc (words, sizeof (struct word) * (nr_words + n)); \ \ if (w == NULL) { \ free_words (words, nr_words); \ words = NULL; \ nr_words = 0; \ } else { \ words = w; \ for (i = 0; i < n; ++i) { \ words[nr_words].name = strs[i]; \ words[nr_words].is_dir = 0; \ nr_words++; \ } \ } \ } \ free (strs); \ } \ } while (0) /* Is it a device? */ if (len < 5 || STREQLEN (text, "/dev/", 5)) { /* Get a list of everything that can possibly begin with /dev/ */ strs = guestfs_list_devices (g); APPEND_STRS_AND_FREE; strs = guestfs_list_partitions (g); APPEND_STRS_AND_FREE; strs = guestfs_lvs (g); APPEND_STRS_AND_FREE; strs = guestfs_list_dm_devices (g); APPEND_STRS_AND_FREE; strs = guestfs_list_md_devices (g); APPEND_STRS_AND_FREE; } if (len < 1 || text[0] == '/') { /* If we've got a partial path already, we need to list everything * in that directory, otherwise list everything in / */ char *p, *dir; struct guestfs_dirent_list *dirents; p = strrchr (text, '/'); dir = p && p > text ? strndup (text, p - text) : strdup ("/"); if (dir) { dirents = guestfs_readdir (g, dir); /* Prepend directory to names before adding them to the list * of words. */ if (dirents) { size_t i; for (i = 0; i < dirents->len; ++i) { int err; if (STRNEQ (dirents->val[i].name, ".") && STRNEQ (dirents->val[i].name, "..")) { if (STREQ (dir, "/")) err = asprintf (&p, "/%s", dirents->val[i].name); else err = asprintf (&p, "%s/%s", dir, dirents->val[i].name); if (err >= 0) { if (!xalloc_oversized (nr_words+1, sizeof (struct word))) { struct word *w; w = realloc (words, sizeof (struct word) * (nr_words+1)); if (w == NULL) { free_words (words, nr_words); words = NULL; nr_words = 0; } else { words = w; words[nr_words].name = p; words[nr_words].is_dir = dirents->val[i].ftyp == 'd'; nr_words++; } } } } } guestfs_free_dirent_list (dirents); } } } /* else ... In theory we could complete other things here such as VG * names. At the moment we don't do that. */ RESTORE_ERROR_CB }
char * complete_dest_paths_generator (const char *text, int state) { #ifdef HAVE_LIBREADLINE static size_t len, index; static struct word *words = NULL; static size_t nr_words = 0; if (!state) { char **strs; len = strlen (text); index = 0; if (words) free_words (words, nr_words); words = NULL; nr_words = 0; guestfs_push_error_handler (g, NULL, NULL); /* Silently do nothing if an allocation fails */ #define APPEND_STRS_AND_FREE \ do { \ if (strs) { \ size_t i; \ size_t n = count_strings (strs); \ \ if ( n > 0 && ! xalloc_oversized (nr_words + n, sizeof (struct word))) { \ struct word *w; \ w = realloc (words, sizeof (struct word) * (nr_words + n)); \ \ if (w == NULL) { \ free_words (words, nr_words); \ words = NULL; \ nr_words = 0; \ } else { \ words = w; \ for (i = 0; i < n; ++i) { \ words[nr_words].name = strs[i]; \ words[nr_words].is_dir = 0; \ nr_words++; \ } \ } \ } \ free (strs); \ } \ } while (0) /* Is it a device? */ if (len < 5 || STREQLEN (text, "/dev/", 5)) { /* Get a list of everything that can possibly begin with /dev/ */ strs = guestfs_list_devices (g); APPEND_STRS_AND_FREE; strs = guestfs_list_partitions (g); APPEND_STRS_AND_FREE; strs = guestfs_lvs (g); APPEND_STRS_AND_FREE; strs = guestfs_list_dm_devices (g); APPEND_STRS_AND_FREE; strs = guestfs_list_md_devices (g); APPEND_STRS_AND_FREE; } if (len < 1 || text[0] == '/') { /* If we've got a partial path already, we need to list everything * in that directory, otherwise list everything in / */ char *p, *dir; struct guestfs_dirent_list *dirents; p = strrchr (text, '/'); dir = p && p > text ? strndup (text, p - text) : strdup ("/"); if (dir) { dirents = guestfs_readdir (g, dir); /* Prepend directory to names before adding them to the list * of words. */ if (dirents) { size_t i; for (i = 0; i < dirents->len; ++i) { int err; if (STRNEQ (dirents->val[i].name, ".") && STRNEQ (dirents->val[i].name, "..")) { if (STREQ (dir, "/")) err = asprintf (&p, "/%s", dirents->val[i].name); else err = asprintf (&p, "%s/%s", dir, dirents->val[i].name); if (err >= 0) { if (!xalloc_oversized (nr_words+1, sizeof (struct word))) { struct word *w; w = realloc (words, sizeof (struct word) * (nr_words+1)); if (w == NULL) { free_words (words, nr_words); words = NULL; nr_words = 0; } else { words = w; words[nr_words].name = p; words[nr_words].is_dir = dirents->val[i].ftyp == 'd'; nr_words++; } } } } } guestfs_free_dirent_list (dirents); } } } /* else ... In theory we could complete other things here such as VG * names. At the moment we don't do that. */ guestfs_pop_error_handler (g); } /* This inhibits ordinary (local filename) completion. */ rl_attempted_completion_over = 1; /* Sort the words so the list is stable over multiple calls. */ if (words) qsort (words, nr_words, sizeof (struct word), compare_words); /* Complete the string. */ while (index < nr_words) { struct word *word; word = &words[index]; index++; /* Whether we should match case insensitively here or not is * determined by the value of the completion-ignore-case readline * variable. Default to case insensitive. (See: RHBZ#582993). */ char *cic_var = rl_variable_value ("completion-ignore-case"); int cic = 1; if (cic_var && STREQ (cic_var, "off")) cic = 0; int matches = cic ? STRCASEEQLEN (word->name, text, len) : STREQLEN (word->name, text, len); if (matches) { if (word->is_dir) rl_completion_append_character = '/'; return strdup (word->name); } } #endif /* HAVE_LIBREADLINE */ return NULL; }