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) {
89 fprintf (stderr, _("%s: no operating system was found on this disk\n"),
95 if (roots[1] != NULL) {
96 fprintf (stderr, _("%s: multi-boot operating systems are not supported by the -i option\n"),
105 inspect_mount_root (root);
109 inspect_mount_root (const char *root)
111 char **mountpoints = guestfs_inspect_get_mountpoints (g, root);
112 if (mountpoints == NULL)
115 /* Sort by key length, shortest key first, so that we end up
116 * mounting the filesystems in the correct order.
118 qsort (mountpoints, count_strings (mountpoints) / 2, 2 * sizeof (char *),
122 size_t mount_errors = 0;
123 for (i = 0; mountpoints[i] != NULL; i += 2) {
126 r = guestfs_mount_options (g, "", mountpoints[i+1], mountpoints[i]);
128 r = guestfs_mount_ro (g, mountpoints[i+1], mountpoints[i]);
133 free_strings (mountpoints);
136 fprintf (stderr, _("%s: some filesystems could not be mounted (ignored)\n"),
140 /* This function is called only if the above function was called,
141 * and only after we've printed the prompt in interactive mode.
144 print_inspect_prompt (void)
146 char *name = guestfs_inspect_get_product_name (g, root);
147 if (name && STRNEQ (name, "unknown"))
148 printf (_("Operating system: %s\n"), name);
151 char **mountpoints = guestfs_inspect_get_mountpoints (g, root);
152 if (mountpoints == NULL)
156 qsort (mountpoints, count_strings (mountpoints) / 2, 2 * sizeof (char *),
160 for (i = 0; mountpoints[i] != NULL; i += 2)
161 printf (_("%s mounted on %s\n"), mountpoints[i+1], mountpoints[i]);
163 free_strings (mountpoints);
166 /* Make a LUKS map name from the partition name,
167 * eg "/dev/vda2" => "luksvda2"
170 make_mapname (const char *device, char *mapname, size_t len)
176 strcpy (mapname, "luks");
180 if (STRPREFIX (device, "/dev/"))
183 for (; device[i] != '\0' && len >= 1; ++i) {
184 if (c_isalnum (device[i])) {
185 *mapname++ = device[i];
193 /* Simple implementation of decryption: look for any crypto_LUKS
194 * partitions and decrypt them, then rescan for VGs. This only works
195 * for Fedora whole-disk encryption. WIP to make this work for other
196 * encryption schemes.
199 inspect_do_decrypt (void)
201 char **partitions = guestfs_list_partitions (g);
202 if (partitions == NULL)
207 for (i = 0; partitions[i] != NULL; ++i) {
208 char *type = guestfs_vfs_type (g, partitions[i]);
209 if (type && STREQ (type, "crypto_LUKS")) {
211 make_mapname (partitions[i], mapname, sizeof mapname);
213 char *key = read_key (partitions[i]);
214 /* XXX Should we call guestfs_luks_open_ro if readonly flag
215 * is set? This might break 'mount_ro'.
217 if (guestfs_luks_open (g, partitions[i], key, mapname) == -1)
227 free_strings (partitions);
230 if (guestfs_vgscan (g) == -1)
232 if (guestfs_vg_activate_all (g, 1) == -1)