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]);
158 /* If the "/" filesystem could not be mounted, give up, else
159 * just count the errors and print a warning.
161 if (STREQ (mountpoints[i], "/"))
167 free_strings (mountpoints);
170 fprintf (stderr, _("%s: some filesystems could not be mounted (ignored)\n"),
174 /* This function is called only if the above function was called,
175 * and only after we've printed the prompt in interactive mode.
178 print_inspect_prompt (void)
180 char *name = guestfs_inspect_get_product_name (g, root);
181 if (name && STRNEQ (name, "unknown"))
182 printf (_("Operating system: %s\n"), name);
185 char **mountpoints = guestfs_inspect_get_mountpoints (g, root);
186 if (mountpoints == NULL)
190 qsort (mountpoints, count_strings (mountpoints) / 2, 2 * sizeof (char *),
194 for (i = 0; mountpoints[i] != NULL; i += 2)
195 printf (_("%s mounted on %s\n"), mountpoints[i+1], mountpoints[i]);
197 free_strings (mountpoints);
200 /* Make a LUKS map name from the partition name,
201 * eg "/dev/vda2" => "luksvda2"
204 make_mapname (const char *device, char *mapname, size_t len)
210 strcpy (mapname, "luks");
214 if (STRPREFIX (device, "/dev/"))
217 for (; device[i] != '\0' && len >= 1; ++i) {
218 if (c_isalnum (device[i])) {
219 *mapname++ = device[i];
227 /* Simple implementation of decryption: look for any crypto_LUKS
228 * partitions and decrypt them, then rescan for VGs. This only works
229 * for Fedora whole-disk encryption. WIP to make this work for other
230 * encryption schemes.
233 inspect_do_decrypt (void)
235 char **partitions = guestfs_list_partitions (g);
236 if (partitions == NULL)
241 for (i = 0; partitions[i] != NULL; ++i) {
242 char *type = guestfs_vfs_type (g, partitions[i]);
243 if (type && STREQ (type, "crypto_LUKS")) {
245 make_mapname (partitions[i], mapname, sizeof mapname);
247 char *key = read_key (partitions[i]);
248 /* XXX Should we call guestfs_luks_open_ro if readonly flag
249 * is set? This might break 'mount_ro'.
251 if (guestfs_luks_open (g, partitions[i], key, mapname) == -1)
261 free_strings (partitions);
264 if (guestfs_vgscan (g) == -1)
266 if (guestfs_vg_activate_all (g, 1) == -1)