Skip to content

Commit

Permalink
inspect: Update inspect_os to use mountables
Browse files Browse the repository at this point in the history
This fixes inspection of guests which use btrfs subvolumes.
  • Loading branch information
mdbooth committed Feb 12, 2013
1 parent 7d97665 commit 7ba0e10
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 87 deletions.
7 changes: 4 additions & 3 deletions src/guestfs-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ enum inspect_os_package_management {

struct inspect_fs {
int is_root;
char *device;
char *mountable;
enum inspect_os_type type;
enum inspect_os_distro distro;
enum inspect_os_package_format package_format;
Expand All @@ -414,7 +414,7 @@ struct inspect_fs {
};

struct inspect_fstab_entry {
char *device;
char *mountable;
char *mountpoint;
};

Expand Down Expand Up @@ -524,7 +524,8 @@ extern struct inspect_fs *guestfs___search_for_root (guestfs_h *g, const char *r
/* inspect-fs.c */
extern int guestfs___is_file_nocase (guestfs_h *g, const char *);
extern int guestfs___is_dir_nocase (guestfs_h *g, const char *);
extern int guestfs___check_for_filesystem_on (guestfs_h *g, const char *device);
extern int guestfs___check_for_filesystem_on (guestfs_h *g,
const char *mountable);
extern int guestfs___parse_unsigned_int (guestfs_h *g, const char *str);
extern int guestfs___parse_unsigned_int_ignore_trailing (guestfs_h *g, const char *str);
extern int guestfs___parse_major_minor (guestfs_h *g, struct inspect_fs *fs);
Expand Down
2 changes: 1 addition & 1 deletion src/inspect-fs-cd.c
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,7 @@ guestfs___check_installer_iso (guestfs_h *g, struct inspect_fs *fs,
return 0;

/* Otherwise we matched an ISO, so fill in the fs fields. */
fs->device = safe_strdup (g, device);
fs->mountable = safe_strdup (g, device);
fs->is_root = 1;
fs->format = OS_FORMAT_INSTALLER;
fs->type = osinfo->type;
Expand Down
121 changes: 69 additions & 52 deletions src/inspect-fs-unix.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,7 @@ static int check_hostname_redhat (guestfs_h *g, struct inspect_fs *fs);
static int check_hostname_freebsd (guestfs_h *g, struct inspect_fs *fs);
static int check_fstab (guestfs_h *g, struct inspect_fs *fs);
static int add_fstab_entry (guestfs_h *g, struct inspect_fs *fs,
const char *spec, const char *mp,
Hash_table *md_map);
const char *mountable, const char *mp);
static char *resolve_fstab_device (guestfs_h *g, const char *spec,
Hash_table *md_map);
static int inspect_with_augeas (guestfs_h *g, struct inspect_fs *fs, const char **configfiles, int (*f) (guestfs_h *, struct inspect_fs *));
Expand Down Expand Up @@ -873,7 +872,6 @@ check_fstab (guestfs_h *g, struct inspect_fs *fs)
CLEANUP_FREE_STRING_LIST char **entries = NULL;
char **entry;
char augpath[256];
int r;
CLEANUP_HASH_FREE Hash_table *md_map;

/* Generate a map of MD device paths listed in /etc/mdadm.conf to MD device
Expand All @@ -895,14 +893,75 @@ check_fstab (guestfs_h *g, struct inspect_fs *fs)
if (spec == NULL)
return -1;

/* Ignore /dev/fd (floppy disks) (RHBZ#642929) and CD-ROM drives. */
if ((STRPREFIX (spec, "/dev/fd") && c_isdigit (spec[7])) ||
STREQ (spec, "/dev/floppy") ||
STREQ (spec, "/dev/cdrom"))
continue;

snprintf (augpath, sizeof augpath, "%s/file", *entry);
CLEANUP_FREE char *mp = guestfs_aug_get (g, augpath);
if (mp == NULL)
return -1;

r = add_fstab_entry (g, fs, spec, mp, md_map);
if (r == -1)
return -1;
/* Ignore certain mountpoints. */
if (STRPREFIX (mp, "/dev/") ||
STREQ (mp, "/dev") ||
STRPREFIX (mp, "/media/") ||
STRPREFIX (mp, "/proc/") ||
STREQ (mp, "/proc") ||
STRPREFIX (mp, "/selinux/") ||
STREQ (mp, "/selinux") ||
STRPREFIX (mp, "/sys/") ||
STREQ (mp, "/sys"))
continue;

/* Resolve UUID= and LABEL= to the actual device. */
CLEANUP_FREE char *mountable = NULL;
if (STRPREFIX (spec, "UUID="))
mountable = guestfs_findfs_uuid (g, &spec[5]);
else if (STRPREFIX (spec, "LABEL="))
mountable = guestfs_findfs_label (g, &spec[6]);
/* Ignore "/.swap" (Pardus) and pseudo-devices like "tmpfs". */
else if (STREQ (spec, "/dev/root"))
/* Resolve /dev/root to the current device. */
mountable = safe_strdup (g, fs->mountable);
else if (STRPREFIX (spec, "/dev/"))
/* Resolve guest block device names. */
mountable = resolve_fstab_device (g, spec, md_map);

/* If we haven't resolved the device successfully by this point,
* we don't care, just ignore it.
*/
if (mountable == NULL)
continue;

snprintf (augpath, sizeof augpath, "%s/vfstype", *entry);
CLEANUP_FREE char *vfstype = guestfs_aug_get (g, augpath);
if (vfstype == NULL) return -1;

if (STREQ (vfstype, "btrfs")) {
snprintf (augpath, sizeof augpath, "%s/opt", *entry);
CLEANUP_FREE_STRING_LIST char **opts = guestfs_aug_match (g, augpath);
if (opts == NULL) return -1;

for (char **opt = opts; *opt; opt++) {
CLEANUP_FREE char *optname = guestfs_aug_get (g, augpath);
if (optname == NULL) return -1;

if (STREQ (optname, "subvol")) {
snprintf (augpath, sizeof augpath, "%s/value", *opt);
CLEANUP_FREE char *subvol = guestfs_aug_get (g, augpath);
if (subvol == NULL) return -1;

char *new = safe_asprintf (g, "btrfsvol:%s/%s", mountable, subvol);
free (mountable);
mountable = new;
}
}
}

if (add_fstab_entry (g, fs, mountable, mp) == -1) return -1;
}

return 0;
Expand All @@ -918,48 +977,8 @@ check_fstab (guestfs_h *g, struct inspect_fs *fs)
*/
static int
add_fstab_entry (guestfs_h *g, struct inspect_fs *fs,
const char *spec, const char *mp, Hash_table *md_map)
const char *mountable, const char *mountpoint)
{
/* Ignore certain mountpoints. */
if (STRPREFIX (mp, "/dev/") ||
STREQ (mp, "/dev") ||
STRPREFIX (mp, "/media/") ||
STRPREFIX (mp, "/proc/") ||
STREQ (mp, "/proc") ||
STRPREFIX (mp, "/selinux/") ||
STREQ (mp, "/selinux") ||
STRPREFIX (mp, "/sys/") ||
STREQ (mp, "/sys"))
return 0;

/* Ignore /dev/fd (floppy disks) (RHBZ#642929) and CD-ROM drives. */
if ((STRPREFIX (spec, "/dev/fd") && c_isdigit (spec[7])) ||
STREQ (spec, "/dev/floppy") ||
STREQ (spec, "/dev/cdrom"))
return 0;

/* Resolve UUID= and LABEL= to the actual device. */
char *device = NULL;
if (STRPREFIX (spec, "UUID="))
device = guestfs_findfs_uuid (g, &spec[5]);
else if (STRPREFIX (spec, "LABEL="))
device = guestfs_findfs_label (g, &spec[6]);
/* Ignore "/.swap" (Pardus) and pseudo-devices like "tmpfs". */
else if (STREQ (spec, "/dev/root"))
/* Resolve /dev/root to the current device. */
device = safe_strdup (g, fs->device);
else if (STRPREFIX (spec, "/dev/"))
/* Resolve guest block device names. */
device = resolve_fstab_device (g, spec, md_map);

/* If we haven't resolved the device successfully by this point,
* we don't care, just ignore it.
*/
if (device == NULL)
return 0;

char *mountpoint = safe_strdup (g, mp);

/* Add this to the fstab entry in 'fs'.
* Note these are further filtered by guestfs_inspect_get_mountpoints
* and guestfs_inspect_get_filesystems.
Expand All @@ -970,19 +989,17 @@ add_fstab_entry (guestfs_h *g, struct inspect_fs *fs,
p = realloc (fs->fstab, n * sizeof (struct inspect_fstab_entry));
if (p == NULL) {
perrorf (g, "realloc");
free (device);
free (mountpoint);
return -1;
}

fs->fstab = p;
fs->nr_fstab = n;

/* These are owned by the handle and freed by guestfs___free_inspect_info. */
fs->fstab[n-1].device = device;
fs->fstab[n-1].mountpoint = mountpoint;
fs->fstab[n-1].mountable = safe_strdup (g, mountable);
fs->fstab[n-1].mountpoint = safe_strdup (g, mountpoint);

debug (g, "fstab: device=%s mountpoint=%s", device, mountpoint);
debug (g, "fstab: mountable=%s mountpoint=%s", mountable, mountpoint);

return 0;
}
Expand Down
55 changes: 30 additions & 25 deletions src/inspect-fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,15 +79,16 @@ free_regexps (void)
pcre_free (re_major_minor);
}

static int check_filesystem (guestfs_h *g, const char *device,
static int check_filesystem (guestfs_h *g, const char *mountable,
const struct guestfs_internal_mountable *m,
int whole_device);
static int extend_fses (guestfs_h *g);

/* Find out if 'device' contains a filesystem. If it does, add
* another entry in g->fses.
*/
int
guestfs___check_for_filesystem_on (guestfs_h *g, const char *device)
guestfs___check_for_filesystem_on (guestfs_h *g, const char *mountable)
{
CLEANUP_FREE char *vfs_type = NULL;
int is_swap, r;
Expand All @@ -98,33 +99,39 @@ guestfs___check_for_filesystem_on (guestfs_h *g, const char *device)
* temporarily replace the error handler with a null one.
*/
guestfs_push_error_handler (g, NULL, NULL);
vfs_type = guestfs_vfs_type (g, device);
vfs_type = guestfs_vfs_type (g, mountable);
guestfs_pop_error_handler (g);

is_swap = vfs_type && STREQ (vfs_type, "swap");
debug (g, "check_for_filesystem_on: %s (%s)",
device, vfs_type ? vfs_type : "failed to get vfs type");
mountable, vfs_type ? vfs_type : "failed to get vfs type");

if (is_swap) {
if (extend_fses (g) == -1)
return -1;
fs = &g->fses[g->nr_fses-1];
fs->device = safe_strdup (g, device);
fs->mountable = safe_strdup (g, mountable);
return 0;
}

CLEANUP_FREE_INTERNAL_MOUNTABLE struct guestfs_internal_mountable *m =
guestfs_internal_parse_mountable (g, mountable);

/* If it's a whole device, see if it is an install ISO. */
int whole_device = guestfs_is_whole_device (g, device);
if (whole_device == -1) {
return -1;
int whole_device = 0;
if (m->im_type == MOUNTABLE_DEVICE) {
whole_device = guestfs_is_whole_device (g, m->im_device);
if (whole_device == -1) {
return -1;
}
}

if (whole_device) {
if (extend_fses (g) == -1)
return -1;
fs = &g->fses[g->nr_fses-1];

r = guestfs___check_installer_iso (g, fs, device);
r = guestfs___check_installer_iso (g, fs, m->im_device);
if (r == -1) { /* Fatal error. */
g->nr_fses--;
return -1;
Expand All @@ -140,19 +147,19 @@ guestfs___check_for_filesystem_on (guestfs_h *g, const char *device)
guestfs_push_error_handler (g, NULL, NULL);
if (vfs_type && STREQ (vfs_type, "ufs")) { /* Hack for the *BSDs. */
/* FreeBSD fs is a variant of ufs called ufs2 ... */
r = guestfs_mount_vfs (g, "ro,ufstype=ufs2", "ufs", device, "/");
r = guestfs_mount_vfs (g, "ro,ufstype=ufs2", "ufs", mountable, "/");
if (r == -1)
/* while NetBSD and OpenBSD use another variant labeled 44bsd */
r = guestfs_mount_vfs (g, "ro,ufstype=44bsd", "ufs", device, "/");
r = guestfs_mount_vfs (g, "ro,ufstype=44bsd", "ufs", mountable, "/");
} else {
r = guestfs_mount_ro (g, device, "/");
r = guestfs_mount_ro (g, mountable, "/");
}
guestfs_pop_error_handler (g);
if (r == -1)
return 0;

/* Do the rest of the checks. */
r = check_filesystem (g, device, whole_device);
r = check_filesystem (g, mountable, m, whole_device);

/* Unmount the filesystem. */
if (guestfs_umount_all (g) == -1)
Expand All @@ -161,28 +168,24 @@ guestfs___check_for_filesystem_on (guestfs_h *g, const char *device)
return r;
}

/* is_block and is_partnum are just hints: is_block is true if the
* filesystem is a whole block device (eg. /dev/sda). is_partnum
* is > 0 if the filesystem is a direct partition, and in this case
* it is the partition number counting from 1
* (eg. /dev/sda1 => is_partnum == 1).
*/
static int
check_filesystem (guestfs_h *g, const char *device, int whole_device)
check_filesystem (guestfs_h *g, const char *mountable,
const struct guestfs_internal_mountable *m,
int whole_device)
{
if (extend_fses (g) == -1)
return -1;

int partnum = -1;
if (!whole_device) {
if (!whole_device && m->im_type == MOUNTABLE_DEVICE) {
guestfs_push_error_handler (g, NULL, NULL);
partnum = guestfs_part_to_partnum (g, device);
partnum = guestfs_part_to_partnum (g, m->im_device);
guestfs_pop_error_handler (g);
}

struct inspect_fs *fs = &g->fses[g->nr_fses-1];

fs->device = safe_strdup (g, device);
fs->mountable = safe_strdup (g, mountable);

/* Optimize some of the tests by avoiding multiple tests of the same thing. */
int is_dir_etc = guestfs_is_dir (g, "/etc") > 0;
Expand All @@ -203,7 +206,8 @@ check_filesystem (guestfs_h *g, const char *device, int whole_device)
* that is probably /dev/sda5 (see:
* http://www.freebsd.org/doc/handbook/disk-organization.html)
*/
if (match (g, device, re_first_partition))
if (m->im_type == MOUNTABLE_DEVICE &&
match (g, m->im_device, re_first_partition))
return 0;

fs->is_root = 1;
Expand All @@ -219,7 +223,8 @@ check_filesystem (guestfs_h *g, const char *device, int whole_device)
* that is probably /dev/sda5 (see:
* http://www.freebsd.org/doc/handbook/disk-organization.html)
*/
if (match (g, device, re_first_partition))
if (m->im_type == MOUNTABLE_DEVICE &&
match (g, m->im_device, re_first_partition))
return 0;

fs->is_root = 1;
Expand Down

0 comments on commit 7ba0e10

Please sign in to comment.