1 /* libguestfs - guestfish and guestmount shared option parsing
2 * Copyright (C) 2010 Red Hat Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
31 /* Global that saves the root device between inspect_mount and
32 * print_inspect_prompt.
34 static char *root = NULL;
37 free_strings (char **argv)
41 for (argc = 0; argv[argc] != NULL; ++argc)
47 count_strings (char *const *argv)
51 for (i = 0; argv[i]; ++i)
57 compare_keys_len (const void *p1, const void *p2)
59 const char *key1 = * (char * const *) p1;
60 const char *key2 = * (char * const *) p2;
61 return strlen (key1) - strlen (key2);
65 compare_keys (const void *p1, const void *p2)
67 const char *key1 = * (char * const *) p1;
68 const char *key2 = * (char * const *) p2;
69 return strcasecmp (key1, key2);
72 /* This function implements the -i option. */
77 fprintf (stderr, _("%s: don't use --live and -i options together\n"),
82 inspect_do_decrypt ();
84 char **roots = guestfs_inspect_os (g);
88 if (roots[0] == NULL) {
90 _("%s: no operating system was found on this disk\n"
92 "If using guestfish '-i' option, remove this option and instead\n"
93 "use the commands 'run' followed by 'list-filesystems'.\n"
94 "You can then mount filesystems you want by hand using the\n"
95 "'mount' or 'mount-ro' command.\n"
97 "If using guestmount '-i', remove this option and choose the\n"
98 "filesystem(s) you want to see by manually adding '-m' option(s).\n"
99 "Use 'virt-filesystems' to see what filesystems are available.\n"
101 "If using other virt tools, this disk image won't work\n"
102 "with these tools. Use the guestfish equivalent commands\n"
103 "(see the virt tool manual page).\n"),
105 free_strings (roots);
109 if (roots[1] != NULL) {
111 _("%s: multi-boot operating systems are not supported\n"
113 "If using guestfish '-i' option, remove this option and instead\n"
114 "use the commands 'run' followed by 'list-filesystems'.\n"
115 "You can then mount filesystems you want by hand using the\n"
116 "'mount' or 'mount-ro' command.\n"
118 "If using guestmount '-i', remove this option and choose the\n"
119 "filesystem(s) you want to see by manually adding '-m' option(s).\n"
120 "Use 'virt-filesystems' to see what filesystems are available.\n"
122 "If using other virt tools, multi-boot operating systems won't work\n"
123 "with these tools. Use the guestfish equivalent commands\n"
124 "(see the virt tool manual page).\n"),
126 free_strings (roots);
133 inspect_mount_root (root);
137 inspect_mount_root (const char *root)
139 char **mountpoints = guestfs_inspect_get_mountpoints (g, root);
140 if (mountpoints == NULL)
143 /* Sort by key length, shortest key first, so that we end up
144 * mounting the filesystems in the correct order.
146 qsort (mountpoints, count_strings (mountpoints) / 2, 2 * sizeof (char *),
150 size_t mount_errors = 0;
151 for (i = 0; mountpoints[i] != NULL; i += 2) {
154 r = guestfs_mount_options (g, "", mountpoints[i+1], mountpoints[i]);
156 r = guestfs_mount_ro (g, mountpoints[i+1], mountpoints[i]);
161 free_strings (mountpoints);
164 fprintf (stderr, _("%s: some filesystems could not be mounted (ignored)\n"),
168 /* This function is called only if the above function was called,
169 * and only after we've printed the prompt in interactive mode.
172 print_inspect_prompt (void)
174 char *name = guestfs_inspect_get_product_name (g, root);
175 if (name && STRNEQ (name, "unknown"))
176 printf (_("Operating system: %s\n"), name);
179 char **mountpoints = guestfs_inspect_get_mountpoints (g, root);
180 if (mountpoints == NULL)
184 qsort (mountpoints, count_strings (mountpoints) / 2, 2 * sizeof (char *),
188 for (i = 0; mountpoints[i] != NULL; i += 2)
189 printf (_("%s mounted on %s\n"), mountpoints[i+1], mountpoints[i]);
191 free_strings (mountpoints);
194 /* Make a LUKS map name from the partition name,
195 * eg "/dev/vda2" => "luksvda2"
198 make_mapname (const char *device, char *mapname, size_t len)
204 strcpy (mapname, "luks");
208 if (STRPREFIX (device, "/dev/"))
211 for (; device[i] != '\0' && len >= 1; ++i) {
212 if (c_isalnum (device[i])) {
213 *mapname++ = device[i];
221 /* Simple implementation of decryption: look for any crypto_LUKS
222 * partitions and decrypt them, then rescan for VGs. This only works
223 * for Fedora whole-disk encryption. WIP to make this work for other
224 * encryption schemes.
227 inspect_do_decrypt (void)
229 char **partitions = guestfs_list_partitions (g);
230 if (partitions == NULL)
235 for (i = 0; partitions[i] != NULL; ++i) {
236 char *type = guestfs_vfs_type (g, partitions[i]);
237 if (type && STREQ (type, "crypto_LUKS")) {
239 make_mapname (partitions[i], mapname, sizeof mapname);
241 char *key = read_key (partitions[i]);
242 /* XXX Should we call guestfs_luks_open_ro if readonly flag
243 * is set? This might break 'mount_ro'.
245 if (guestfs_luks_open (g, partitions[i], key, mapname) == -1)
255 free_strings (partitions);
258 if (guestfs_vgscan (g) == -1)
260 if (guestfs_vg_activate_all (g, 1) == -1)