static int check_filesystem (guestfs_h *g, const char *mountable, const struct guestfs_internal_mountable *m, int whole_device) { int partnum = -1, nr_partitions = -1; /* Not CLEANUP_FREE, as it will be cleaned up with inspection info */ char *windows_systemroot = NULL; extend_fses (g); if (!whole_device && m->im_type == MOUNTABLE_DEVICE && guestfs_int_is_partition (g, m->im_device)) { if (get_partition_context (g, m->im_device, &partnum, &nr_partitions) == -1) return -1; } struct inspect_fs *fs = &g->fses[g->nr_fses-1]; fs->mountable = safe_strdup (g, mountable); /* Optimize some of the tests by avoiding multiple tests of the same thing. */ const int is_dir_etc = guestfs_is_dir (g, "/etc") > 0; const int is_dir_bin = guestfs_is_dir (g, "/bin") > 0; const int is_dir_share = guestfs_is_dir (g, "/share") > 0; /* Grub /boot? */ if (guestfs_is_file (g, "/grub/menu.lst") > 0 || guestfs_is_file (g, "/grub/grub.conf") > 0 || guestfs_is_file (g, "/grub2/grub.cfg") > 0) ; /* FreeBSD root? */ else if (is_dir_etc && is_dir_bin && guestfs_is_file (g, "/etc/freebsd-update.conf") > 0 && guestfs_is_file (g, "/etc/fstab") > 0) { fs->role = OS_ROLE_ROOT; fs->format = OS_FORMAT_INSTALLED; if (guestfs_int_check_freebsd_root (g, fs) == -1) return -1; } /* NetBSD root? */ else if (is_dir_etc && is_dir_bin && guestfs_is_file (g, "/netbsd") > 0 && guestfs_is_file (g, "/etc/fstab") > 0 && guestfs_is_file (g, "/etc/release") > 0) { fs->role = OS_ROLE_ROOT; fs->format = OS_FORMAT_INSTALLED; if (guestfs_int_check_netbsd_root (g, fs) == -1) return -1; } /* OpenBSD root? */ else if (is_dir_etc && is_dir_bin && guestfs_is_file (g, "/bsd") > 0 && guestfs_is_file (g, "/etc/fstab") > 0 && guestfs_is_file (g, "/etc/motd") > 0) { fs->role = OS_ROLE_ROOT; fs->format = OS_FORMAT_INSTALLED; if (guestfs_int_check_openbsd_root (g, fs) == -1) return -1; } /* Hurd root? */ else if (guestfs_is_file (g, "/hurd/console") > 0 && guestfs_is_file (g, "/hurd/hello") > 0 && guestfs_is_file (g, "/hurd/null") > 0) { fs->role = OS_ROLE_ROOT; fs->format = OS_FORMAT_INSTALLED; /* XXX could be more specific */ if (guestfs_int_check_hurd_root (g, fs) == -1) return -1; } /* Minix root? */ else if (is_dir_etc && is_dir_bin && guestfs_is_file (g, "/service/vm") > 0 && guestfs_is_file (g, "/etc/fstab") > 0 && guestfs_is_file (g, "/etc/version") > 0) { fs->role = OS_ROLE_ROOT; fs->format = OS_FORMAT_INSTALLED; if (guestfs_int_check_minix_root (g, fs) == -1) return -1; } /* Linux root? */ else if (is_dir_etc && (is_dir_bin || is_symlink_to (g, "/bin", "usr/bin") > 0) && (guestfs_is_file (g, "/etc/fstab") > 0 || guestfs_is_file (g, "/etc/hosts") > 0)) { fs->role = OS_ROLE_ROOT; fs->format = OS_FORMAT_INSTALLED; if (guestfs_int_check_linux_root (g, fs) == -1) return -1; } /* CoreOS root? */ else if (is_dir_etc && guestfs_is_dir (g, "/root") > 0 && guestfs_is_dir (g, "/home") > 0 && guestfs_is_dir (g, "/usr") > 0 && guestfs_is_file (g, "/etc/coreos/update.conf") > 0) { fs->role = OS_ROLE_ROOT; fs->format = OS_FORMAT_INSTALLED; if (guestfs_int_check_coreos_root (g, fs) == -1) return -1; } /* Linux /usr/local? */ else if (is_dir_etc && is_dir_bin && is_dir_share && guestfs_is_dir (g, "/local") == 0 && guestfs_is_file (g, "/etc/fstab") == 0) ; /* Linux /usr? */ else if (is_dir_etc && is_dir_bin && is_dir_share && guestfs_is_dir (g, "/local") > 0 && guestfs_is_file (g, "/etc/fstab") == 0) { if (guestfs_int_check_linux_usr (g, fs) == -1) return -1; } /* CoreOS /usr? */ else if (is_dir_bin && is_dir_share && guestfs_is_dir (g, "/local") > 0 && guestfs_is_dir (g, "/share/coreos") > 0) { if (guestfs_int_check_coreos_usr (g, fs) == -1) return -1; } /* Linux /var? */ else if (guestfs_is_dir (g, "/log") > 0 && guestfs_is_dir (g, "/run") > 0 && guestfs_is_dir (g, "/spool") > 0) ; /* Windows root? */ else if ((windows_systemroot = guestfs_int_get_windows_systemroot (g)) != NULL) { fs->role = OS_ROLE_ROOT; fs->format = OS_FORMAT_INSTALLED; if (guestfs_int_check_windows_root (g, fs, windows_systemroot) == -1) return -1; } /* Windows volume with installed applications (but not root)? */ else if (guestfs_int_is_dir_nocase (g, "/System Volume Information") > 0 && guestfs_int_is_dir_nocase (g, "/Program Files") > 0) ; /* Windows volume (but not root)? */ else if (guestfs_int_is_dir_nocase (g, "/System Volume Information") > 0) ; /* FreeDOS? */ else if (guestfs_int_is_dir_nocase (g, "/FDOS") > 0 && guestfs_int_is_file_nocase (g, "/FDOS/FREEDOS.BSS") > 0) { fs->role = OS_ROLE_ROOT; fs->format = OS_FORMAT_INSTALLED; fs->type = OS_TYPE_DOS; fs->distro = OS_DISTRO_FREEDOS; /* FreeDOS is a mix of 16 and 32 bit, but assume it requires a * 32 bit i386 processor. */ fs->arch = safe_strdup (g, "i386"); } /* Install CD/disk? * * Note that we checked (above) for an install ISO, but there are * other types of install image (eg. USB keys) which that check * wouldn't have picked up. * * Skip these checks if it's not a whole device (eg. CD) or the * first partition (eg. bootable USB key). */ else if ((whole_device || (partnum == 1 && nr_partitions == 1)) && (guestfs_is_file (g, "/isolinux/isolinux.cfg") > 0 || guestfs_is_dir (g, "/EFI/BOOT") > 0 || guestfs_is_file (g, "/images/install.img") > 0 || guestfs_is_dir (g, "/.disk") > 0 || guestfs_is_file (g, "/.discinfo") > 0 || guestfs_is_file (g, "/i386/txtsetup.sif") > 0 || guestfs_is_file (g, "/amd64/txtsetup.sif") > 0 || guestfs_is_file (g, "/freedos/freedos.ico") > 0 || guestfs_is_file (g, "/boot/loader.rc") > 0)) { fs->role = OS_ROLE_ROOT; fs->format = OS_FORMAT_INSTALLER; if (guestfs_int_check_installer_root (g, fs) == -1) return -1; } /* The above code should have set fs->type and fs->distro fields, so * we can now guess the package management system. */ guestfs_int_check_package_format (g, fs); guestfs_int_check_package_management (g, fs); return 0; }
/* Find out if 'device' contains a filesystem. If it does, add * another entry in g->fses. */ int guestfs_int_check_for_filesystem_on (guestfs_h *g, const char *mountable) { CLEANUP_FREE char *vfs_type = NULL; int is_swap, r; struct inspect_fs *fs; CLEANUP_FREE_INTERNAL_MOUNTABLE struct guestfs_internal_mountable *m = NULL; int whole_device = 0; /* Get vfs-type in order to check if it's a Linux(?) swap device. * If there's an error we should ignore it, so to do that we have to * temporarily replace the error handler with a null one. */ guestfs_push_error_handler (g, NULL, NULL); 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)", mountable, vfs_type ? vfs_type : "failed to get vfs type"); if (is_swap) { extend_fses (g); fs = &g->fses[g->nr_fses-1]; fs->mountable = safe_strdup (g, mountable); return 0; } m = guestfs_internal_parse_mountable (g, mountable); if (m == NULL) return -1; /* If it's a whole device, see if it is an install ISO. */ 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) { extend_fses (g); fs = &g->fses[g->nr_fses-1]; r = guestfs_int_check_installer_iso (g, fs, m->im_device); if (r == -1) { /* Fatal error. */ g->nr_fses--; return -1; } if (r > 0) /* Found something. */ return 0; /* Didn't find anything. Fall through ... */ g->nr_fses--; } /* Try mounting the device. As above, ignore errors. */ 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", mountable, "/"); if (r == -1) /* while NetBSD and OpenBSD use another variant labeled 44bsd */ r = guestfs_mount_vfs (g, "ro,ufstype=44bsd", "ufs", mountable, "/"); } else { 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, mountable, m, whole_device); /* Unmount the filesystem. */ if (guestfs_umount_all (g) == -1) return -1; return r; }
static int check_filesystem (guestfs_h *g, const char *mountable, const struct guestfs_internal_mountable *m, int whole_device) { /* Not CLEANUP_FREE, as it will be cleaned up with inspection info */ char *windows_systemroot = NULL; if (extend_fses (g) == -1) return -1; int partnum = -1; if (!whole_device && m->im_type == MOUNTABLE_DEVICE) { guestfs_push_error_handler (g, NULL, NULL); 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->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; int is_dir_bin = guestfs_is_dir (g, "/bin") > 0; int is_dir_share = guestfs_is_dir (g, "/share") > 0; /* Grub /boot? */ if (guestfs_is_file (g, "/grub/menu.lst") > 0 || guestfs_is_file (g, "/grub/grub.conf") > 0 || guestfs_is_file (g, "/grub2/grub.cfg") > 0) ; /* FreeBSD root? */ else if (is_dir_etc && is_dir_bin && guestfs_is_file (g, "/etc/freebsd-update.conf") > 0 && guestfs_is_file (g, "/etc/fstab") > 0) { /* Ignore /dev/sda1 which is a shadow of the real root filesystem * that is probably /dev/sda5 (see: * http://www.freebsd.org/doc/handbook/disk-organization.html) */ if (m->im_type == MOUNTABLE_DEVICE && match (g, m->im_device, re_first_partition)) return 0; fs->is_root = 1; fs->format = OS_FORMAT_INSTALLED; if (guestfs___check_freebsd_root (g, fs) == -1) return -1; } else if (is_dir_etc && is_dir_bin && guestfs_is_file (g, "/etc/fstab") > 0 && guestfs_is_file (g, "/etc/release") > 0) { /* Ignore /dev/sda1 which is a shadow of the real root filesystem * that is probably /dev/sda5 (see: * http://www.freebsd.org/doc/handbook/disk-organization.html) */ if (m->im_type == MOUNTABLE_DEVICE && match (g, m->im_device, re_first_partition)) return 0; fs->is_root = 1; fs->format = OS_FORMAT_INSTALLED; if (guestfs___check_netbsd_root (g, fs) == -1) return -1; } /* Hurd root? */ else if (guestfs_is_file (g, "/hurd/console") > 0 && guestfs_is_file (g, "/hurd/hello") > 0 && guestfs_is_file (g, "/hurd/null") > 0) { fs->is_root = 1; fs->format = OS_FORMAT_INSTALLED; /* XXX could be more specific */ if (guestfs___check_hurd_root (g, fs) == -1) return -1; } /* Linux root? */ else if (is_dir_etc && (is_dir_bin || (guestfs_is_symlink (g, "/bin") > 0 && guestfs_is_dir (g, "/usr/bin") > 0)) && guestfs_is_file (g, "/etc/fstab") > 0) { fs->is_root = 1; fs->format = OS_FORMAT_INSTALLED; if (guestfs___check_linux_root (g, fs) == -1) return -1; } /* Linux /usr/local? */ else if (is_dir_etc && is_dir_bin && is_dir_share && guestfs_is_dir (g, "/local") == 0 && guestfs_is_file (g, "/etc/fstab") == 0) ; /* Linux /usr? */ else if (is_dir_etc && is_dir_bin && is_dir_share && guestfs_is_dir (g, "/local") > 0 && guestfs_is_file (g, "/etc/fstab") == 0) ; /* Linux /var? */ else if (guestfs_is_dir (g, "/log") > 0 && guestfs_is_dir (g, "/run") > 0 && guestfs_is_dir (g, "/spool") > 0) ; /* Windows root? */ else if ((windows_systemroot = guestfs___get_windows_systemroot (g)) != NULL) { fs->is_root = 1; fs->format = OS_FORMAT_INSTALLED; if (guestfs___check_windows_root (g, fs, windows_systemroot) == -1) return -1; } /* Windows volume with installed applications (but not root)? */ else if (guestfs___is_dir_nocase (g, "/System Volume Information") > 0 && guestfs___is_dir_nocase (g, "/Program Files") > 0) ; /* Windows volume (but not root)? */ else if (guestfs___is_dir_nocase (g, "/System Volume Information") > 0) ; /* FreeDOS? */ else if (guestfs___is_dir_nocase (g, "/FDOS") > 0 && guestfs___is_file_nocase (g, "/FDOS/FREEDOS.BSS") > 0) { fs->is_root = 1; fs->format = OS_FORMAT_INSTALLED; fs->type = OS_TYPE_DOS; fs->distro = OS_DISTRO_FREEDOS; /* FreeDOS is a mix of 16 and 32 bit, but assume it requires a * 32 bit i386 processor. */ fs->arch = safe_strdup (g, "i386"); } /* Install CD/disk? * * Note that we checked (above) for an install ISO, but there are * other types of install image (eg. USB keys) which that check * wouldn't have picked up. * * Skip these checks if it's not a whole device (eg. CD) or the * first partition (eg. bootable USB key). */ else if ((whole_device || partnum == 1) && (guestfs_is_file (g, "/isolinux/isolinux.cfg") > 0 || guestfs_is_dir (g, "/EFI/BOOT") > 0 || guestfs_is_file (g, "/images/install.img") > 0 || guestfs_is_dir (g, "/.disk") > 0 || guestfs_is_file (g, "/.discinfo") > 0 || guestfs_is_file (g, "/i386/txtsetup.sif") > 0 || guestfs_is_file (g, "/amd64/txtsetup.sif") > 0 || guestfs_is_file (g, "/freedos/freedos.ico") > 0 || guestfs_is_file (g, "/boot/loader.rc") > 0)) { fs->is_root = 1; fs->format = OS_FORMAT_INSTALLER; if (guestfs___check_installer_root (g, fs) == -1) return -1; } /* The above code should have set fs->type and fs->distro fields, so * we can now guess the package management system. */ guestfs___check_package_format (g, fs); guestfs___check_package_management (g, fs); return 0; }