/* The currently mounted device may be a Hurd root. Hurd has distros * just like Linux. */ int guestfs___check_hurd_root (guestfs_h *g, struct inspect_fs *fs) { fs->type = OS_TYPE_HURD; if (guestfs_is_file_opts (g, "/etc/debian_version", GUESTFS_IS_FILE_OPTS_FOLLOWSYMLINKS, 1, -1) > 0) { fs->distro = OS_DISTRO_DEBIAN; if (parse_release_file (g, fs, "/etc/debian_version") == -1) return -1; if (guestfs___parse_major_minor (g, fs) == -1) return -1; } /* Arch Hurd also exists, but inconveniently it doesn't have * the normal /etc/arch-release file. XXX */ /* Determine the architecture. */ check_architecture (g, fs); /* XXX Check for /etc/fstab. */ /* Determine hostname. */ if (check_hostname_unix (g, fs) == -1) return -1; return 0; }
/* The currently mounted device is known to be a FreeBSD root. */ int guestfs___check_freebsd_root (guestfs_h *g, struct inspect_fs *fs) { fs->type = OS_TYPE_FREEBSD; /* FreeBSD has no authoritative version file. The version number is * in /etc/motd, which the system administrator might edit, but * we'll use that anyway. */ if (guestfs_is_file_opts (g, "/etc/motd", GUESTFS_IS_FILE_OPTS_FOLLOWSYMLINKS, 1, -1) > 0) { if (parse_release_file (g, fs, "/etc/motd") == -1) return -1; if (guestfs___parse_major_minor (g, fs) == -1) return -1; } /* Determine the architecture. */ check_architecture (g, fs); /* We already know /etc/fstab exists because it's part of the test above. */ const char *configfiles[] = { "/etc/fstab", NULL }; if (inspect_with_augeas (g, fs, configfiles, check_fstab) == -1) return -1; /* Determine hostname. */ if (check_hostname_unix (g, fs) == -1) return -1; return 0; }
static int do_log (void) { CLEANUP_FREE_STRING_LIST char **roots = NULL; char *root; CLEANUP_FREE char *type = NULL; CLEANUP_FREE_STRING_LIST char **journal_files = NULL; /* Get root mountpoint. fish/inspect.c guarantees the assertions * below. */ roots = guestfs_inspect_get_roots (g); assert (roots); assert (roots[0] != NULL); assert (roots[1] == NULL); root = roots[0]; type = guestfs_inspect_get_type (g, root); if (!type) return -1; /* Windows needs special handling. */ if (STREQ (type, "windows")) { if (guestfs_inspect_get_major_version (g, root) >= 6) return do_log_windows_evtx (); fprintf (stderr, _("%s: Windows Event Log for pre-Vista guests is not supported.\n"), guestfs_int_program_name); return -1; } /* systemd journal? */ guestfs_push_error_handler (g, NULL, NULL); journal_files = guestfs_ls (g, JOURNAL_DIR); guestfs_pop_error_handler (g); if (STREQ (type, "linux") && journal_files != NULL && journal_files[0] != NULL) return do_log_journal (); /* Regular /var/log text files with different names. */ if (STRNEQ (type, "windows")) { const char *logfiles[] = { "/var/log/syslog", "/var/log/messages", NULL }; size_t i; for (i = 0; logfiles[i] != NULL; ++i) { if (guestfs_is_file_opts (g, logfiles[i], GUESTFS_IS_FILE_OPTS_FOLLOWSYMLINKS, 1, -1) == 1) return do_log_text_file (logfiles[i]); } } /* Otherwise, there are no log files. Hmm, is this right? XXX */ return 0; }
/* Check that the named file 'filename' is a PNG file and is reasonable. * If it is, download and return it. */ static char * get_png (guestfs_h *g, struct inspect_fs *fs, const char *filename, size_t *size_r, size_t max_size) { char *ret; CLEANUP_FREE char *real = NULL; CLEANUP_FREE char *type = NULL; CLEANUP_FREE char *local = NULL; int r, w, h; r = guestfs_is_file_opts (g, filename, GUESTFS_IS_FILE_OPTS_FOLLOWSYMLINKS, 1, -1); if (r == -1) return NULL; /* a real error */ if (r == 0) return NOT_FOUND; /* Resolve the path, in case it's a symbolic link (as in RHEL 7). */ guestfs_push_error_handler (g, NULL, NULL); real = guestfs_realpath (g, filename); guestfs_pop_error_handler (g); if (real == NULL) return NOT_FOUND; /* could just be a broken link */ /* Check the file type and geometry. */ type = guestfs_file (g, real); if (!type) return NOT_FOUND; if (!STRPREFIX (type, "PNG image data, ")) return NOT_FOUND; if (sscanf (&type[16], "%d x %d", &w, &h) != 2) return NOT_FOUND; if (w < 16 || h < 16 || w > 1024 || h > 1024) return NOT_FOUND; /* Define a maximum reasonable size based on the geometry. This * also limits the maximum we allocate below to around 4 MB. */ if (max_size == 0) max_size = 4 * w * h; local = guestfs___download_to_tmp (g, fs, real, "icon", max_size); if (!local) return NOT_FOUND; /* Successfully passed checks and downloaded. Read it into memory. */ if (read_whole_file (g, local, &ret, size_r) == -1) return NULL; return ret; }
static char * icon_cirros (guestfs_h *g, struct inspect_fs *fs, size_t *size_r) { char *ret; CLEANUP_FREE char *type = NULL; CLEANUP_FREE char *local = NULL; CLEANUP_FREE char *pngfile = NULL; CLEANUP_CMD_CLOSE struct command *cmd = guestfs___new_command (g); int r; r = guestfs_is_file_opts (g, CIRROS_LOGO, GUESTFS_IS_FILE_OPTS_FOLLOWSYMLINKS, 1, -1); if (r == -1) return NULL; /* a real error */ if (r == 0) return NOT_FOUND; /* Check the file type and geometry. */ type = guestfs_file (g, CIRROS_LOGO); if (!type) return NOT_FOUND; if (!STRPREFIX (type, "ASCII text")) return NOT_FOUND; local = guestfs___download_to_tmp (g, fs, CIRROS_LOGO, "icon", 1024); if (!local) return NOT_FOUND; /* Use pbmtext to render it. */ pngfile = safe_asprintf (g, "%s/cirros.png", g->tmpdir); guestfs___cmd_add_string_unquoted (cmd, PBMTEXT " < "); guestfs___cmd_add_string_quoted (cmd, local); guestfs___cmd_add_string_unquoted (cmd, " | " PNMTOPNG " > "); guestfs___cmd_add_string_quoted (cmd, pngfile); r = guestfs___cmd_run (cmd); if (r == -1) return NOT_FOUND; if (!WIFEXITED (r) || WEXITSTATUS (r) != 0) return NOT_FOUND; /* Read it into memory. */ if (read_whole_file (g, pngfile, &ret, size_r) == -1) return NULL; return ret; }
/* The currently mounted device is maybe to be a *BSD root. */ int guestfs___check_netbsd_root (guestfs_h *g, struct inspect_fs *fs) { if (guestfs_is_file_opts (g, "/etc/release", GUESTFS_IS_FILE_OPTS_FOLLOWSYMLINKS, 1, -1) > 0) { char *major, *minor; if (parse_release_file (g, fs, "/etc/release") == -1) return -1; if (match2 (g, fs->product_name, re_netbsd, &major, &minor)) { fs->type = OS_TYPE_NETBSD; fs->major_version = guestfs___parse_unsigned_int (g, major); free (major); if (fs->major_version == -1) { free (minor); return -1; } fs->minor_version = guestfs___parse_unsigned_int (g, minor); free (minor); if (fs->minor_version == -1) return -1; } } else { return -1; } /* Determine the architecture. */ check_architecture (g, fs); /* We already know /etc/fstab exists because it's part of the test above. */ const char *configfiles[] = { "/etc/fstab", NULL }; if (inspect_with_augeas (g, fs, configfiles, check_fstab) == -1) return -1; /* Determine hostname. */ if (check_hostname_unix (g, fs) == -1) return -1; return 0; }
void guestfs_int_check_package_management (guestfs_h *g, struct inspect_fs *fs) { switch (fs->distro) { case OS_DISTRO_MEEGO: fs->package_management = OS_PACKAGE_MANAGEMENT_YUM; break; case OS_DISTRO_FEDORA: /* If Fedora >= 22 and dnf is installed, say "dnf". */ if (guestfs_int_version_ge (&fs->version, 22, 0, 0) && guestfs_is_file_opts (g, "/usr/bin/dnf", GUESTFS_IS_FILE_OPTS_FOLLOWSYMLINKS, 1, -1) > 0) fs->package_management = OS_PACKAGE_MANAGEMENT_DNF; else if (guestfs_int_version_ge (&fs->version, 1, 0, 0)) fs->package_management = OS_PACKAGE_MANAGEMENT_YUM; else /* Probably parsing the release file failed, see RHBZ#1332025. */ fs->package_management = OS_PACKAGE_MANAGEMENT_UNKNOWN; break; case OS_DISTRO_REDHAT_BASED: case OS_DISTRO_RHEL: case OS_DISTRO_CENTOS: case OS_DISTRO_SCIENTIFIC_LINUX: case OS_DISTRO_ORACLE_LINUX: if (guestfs_int_version_ge (&fs->version, 5, 0, 0)) fs->package_management = OS_PACKAGE_MANAGEMENT_YUM; else if (guestfs_int_version_ge (&fs->version, 2, 0, 0)) fs->package_management = OS_PACKAGE_MANAGEMENT_UP2DATE; else /* Probably parsing the release file failed, see RHBZ#1332025. */ fs->package_management = OS_PACKAGE_MANAGEMENT_UNKNOWN; break; case OS_DISTRO_DEBIAN: case OS_DISTRO_UBUNTU: case OS_DISTRO_LINUX_MINT: case OS_DISTRO_ALTLINUX: fs->package_management = OS_PACKAGE_MANAGEMENT_APT; break; case OS_DISTRO_ARCHLINUX: fs->package_management = OS_PACKAGE_MANAGEMENT_PACMAN; break; case OS_DISTRO_GENTOO: fs->package_management = OS_PACKAGE_MANAGEMENT_PORTAGE; break; case OS_DISTRO_PARDUS: fs->package_management = OS_PACKAGE_MANAGEMENT_PISI; break; case OS_DISTRO_MAGEIA: case OS_DISTRO_MANDRIVA: fs->package_management = OS_PACKAGE_MANAGEMENT_URPMI; break; case OS_DISTRO_SUSE_BASED: case OS_DISTRO_OPENSUSE: case OS_DISTRO_SLES: fs->package_management = OS_PACKAGE_MANAGEMENT_ZYPPER; break; case OS_DISTRO_ALPINE_LINUX: fs->package_management = OS_PACKAGE_MANAGEMENT_APK; break; case OS_DISTRO_VOID_LINUX: fs->package_management = OS_PACKAGE_MANAGEMENT_XBPS; break; case OS_DISTRO_SLACKWARE: case OS_DISTRO_TTYLINUX: case OS_DISTRO_COREOS: case OS_DISTRO_WINDOWS: case OS_DISTRO_BUILDROOT: case OS_DISTRO_CIRROS: case OS_DISTRO_FREEDOS: case OS_DISTRO_FREEBSD: case OS_DISTRO_NETBSD: case OS_DISTRO_OPENBSD: case OS_DISTRO_FRUGALWARE: case OS_DISTRO_PLD_LINUX: case OS_DISTRO_UNKNOWN: fs->package_management = OS_PACKAGE_MANAGEMENT_UNKNOWN; break; } }
/* For Windows >= Vista, if evtxdump.py is installed then we can * use it to dump the System.evtx log. */ static int do_log_windows_evtx (void) { CLEANUP_FREE char *filename = NULL; CLEANUP_FREE char *tmpdir = guestfs_get_tmpdir (g); CLEANUP_UNLINK_FREE char *localfile = NULL; CLEANUP_FREE char *cmd = NULL; char dev_fd[64]; int fd, status; if (system ("evtxdump.py -h >/dev/null 2>&1") != 0) { fprintf (stderr, _("%s: you need to install 'evtxdump.py' (from the python-evtx package)\n" "in order to parse Windows Event Logs. If you cannot install this, then\n" "use virt-copy-out(1) to copy the contents of /Windows/System32/winevt/Logs\n" "from this guest, and examine in a binary file viewer.\n"), guestfs_int_program_name); return -1; } /* Check if System.evtx exists. XXX Allow the filename to be * configurable, since there are many logs. */ filename = guestfs_case_sensitive_path (g, "/Windows/System32/winevt/Logs/System.evtx"); if (filename == NULL) return -1; /* Note that guestfs_case_sensitive_path does NOT check for existence. */ if (guestfs_is_file_opts (g, filename, GUESTFS_IS_FILE_OPTS_FOLLOWSYMLINKS, 1, -1) <= 0) { fprintf (stderr, _("%s: Windows Event Log file (%s) not found\n"), guestfs_int_program_name, filename); return -1; } /* Download the file to a temporary. Python-evtx wants to mmap * the file so we cannot use a pipe. */ if (asprintf (&localfile, "%s/virtlogXXXXXX", tmpdir) == -1) { perror ("asprintf"); return -1; } if ((fd = mkstemp (localfile)) == -1) { perror ("mkstemp"); return -1; } snprintf (dev_fd, sizeof dev_fd, "/dev/fd/%d", fd); if (guestfs_download (g, filename, dev_fd) == -1) return -1; close (fd); /* This should be safe as long as $TMPDIR is not set to something wild. */ if (asprintf (&cmd, "evtxdump.py '%s'", localfile) == -1) { perror ("asprintf"); return -1; } status = system (cmd); if (status) { char buf[256]; fprintf (stderr, "%s: %s\n", guestfs_int_program_name, guestfs_int_exit_status_to_string (status, "evtxdump.py", buf, sizeof buf)); return -1; } return 0; }
/* The currently mounted device is known to be a Linux root. Try to * determine from this the distro, version, etc. Also parse * /etc/fstab to determine the arrangement of mountpoints and * associated devices. */ int guestfs___check_linux_root (guestfs_h *g, struct inspect_fs *fs) { int r; fs->type = OS_TYPE_LINUX; if (guestfs_is_file_opts (g, "/etc/lsb-release", GUESTFS_IS_FILE_OPTS_FOLLOWSYMLINKS, 1, -1) > 0) { r = parse_lsb_release (g, fs); if (r == -1) /* error */ return -1; if (r == 1) /* ok - detected the release from this file */ goto skip_release_checks; } if (guestfs_is_file_opts (g, "/etc/redhat-release", GUESTFS_IS_FILE_OPTS_FOLLOWSYMLINKS, 1, -1) > 0) { fs->distro = OS_DISTRO_REDHAT_BASED; /* Something generic Red Hat-like. */ if (parse_release_file (g, fs, "/etc/redhat-release") == -1) return -1; char *major, *minor; if ((major = match1 (g, fs->product_name, re_fedora)) != NULL) { fs->distro = OS_DISTRO_FEDORA; fs->major_version = guestfs___parse_unsigned_int (g, major); free (major); if (fs->major_version == -1) return -1; } else if (match2 (g, fs->product_name, re_rhel_old, &major, &minor) || match2 (g, fs->product_name, re_rhel, &major, &minor)) { fs->distro = OS_DISTRO_RHEL; fs->major_version = guestfs___parse_unsigned_int (g, major); free (major); if (fs->major_version == -1) { free (minor); return -1; } fs->minor_version = guestfs___parse_unsigned_int (g, minor); free (minor); if (fs->minor_version == -1) return -1; } else if ((major = match1 (g, fs->product_name, re_rhel_no_minor)) != NULL) { fs->distro = OS_DISTRO_RHEL; fs->major_version = guestfs___parse_unsigned_int (g, major); free (major); if (fs->major_version == -1) return -1; fs->minor_version = 0; } else if (match2 (g, fs->product_name, re_centos_old, &major, &minor) || match2 (g, fs->product_name, re_centos, &major, &minor)) { fs->distro = OS_DISTRO_CENTOS; fs->major_version = guestfs___parse_unsigned_int (g, major); free (major); if (fs->major_version == -1) { free (minor); return -1; } fs->minor_version = guestfs___parse_unsigned_int (g, minor); free (minor); if (fs->minor_version == -1) return -1; } else if ((major = match1 (g, fs->product_name, re_centos_no_minor)) != NULL) { fs->distro = OS_DISTRO_CENTOS; fs->major_version = guestfs___parse_unsigned_int (g, major); free (major); if (fs->major_version == -1) return -1; fs->minor_version = 0; } else if (match2 (g, fs->product_name, re_scientific_linux_old, &major, &minor) || match2 (g, fs->product_name, re_scientific_linux, &major, &minor)) { fs->distro = OS_DISTRO_SCIENTIFIC_LINUX; fs->major_version = guestfs___parse_unsigned_int (g, major); free (major); if (fs->major_version == -1) { free (minor); return -1; } fs->minor_version = guestfs___parse_unsigned_int (g, minor); free (minor); if (fs->minor_version == -1) return -1; } else if ((major = match1 (g, fs->product_name, re_scientific_linux_no_minor)) != NULL) { fs->distro = OS_DISTRO_SCIENTIFIC_LINUX; fs->major_version = guestfs___parse_unsigned_int (g, major); free (major); if (fs->major_version == -1) return -1; fs->minor_version = 0; } } else if (guestfs_is_file_opts (g, "/etc/debian_version", GUESTFS_IS_FILE_OPTS_FOLLOWSYMLINKS, 1, -1) > 0) { fs->distro = OS_DISTRO_DEBIAN; if (parse_release_file (g, fs, "/etc/debian_version") == -1) return -1; if (guestfs___parse_major_minor (g, fs) == -1) return -1; } else if (guestfs_is_file_opts (g, "/etc/pardus-release", GUESTFS_IS_FILE_OPTS_FOLLOWSYMLINKS, 1, -1) > 0) { fs->distro = OS_DISTRO_PARDUS; if (parse_release_file (g, fs, "/etc/pardus-release") == -1) return -1; if (guestfs___parse_major_minor (g, fs) == -1) return -1; } else if (guestfs_is_file_opts (g, "/etc/arch-release", GUESTFS_IS_FILE_OPTS_FOLLOWSYMLINKS, 1, -1) > 0) { fs->distro = OS_DISTRO_ARCHLINUX; /* /etc/arch-release file is empty and I can't see a way to * determine the actual release or product string. */ } else if (guestfs_is_file_opts (g, "/etc/gentoo-release", GUESTFS_IS_FILE_OPTS_FOLLOWSYMLINKS, 1, -1) > 0) { fs->distro = OS_DISTRO_GENTOO; if (parse_release_file (g, fs, "/etc/gentoo-release") == -1) return -1; if (guestfs___parse_major_minor (g, fs) == -1) return -1; } else if (guestfs_is_file_opts (g, "/etc/meego-release", GUESTFS_IS_FILE_OPTS_FOLLOWSYMLINKS, 1, -1) > 0) { fs->distro = OS_DISTRO_MEEGO; if (parse_release_file (g, fs, "/etc/meego-release") == -1) return -1; if (guestfs___parse_major_minor (g, fs) == -1) return -1; } else if (guestfs_is_file_opts (g, "/etc/slackware-version", GUESTFS_IS_FILE_OPTS_FOLLOWSYMLINKS, 1, -1) > 0) { fs->distro = OS_DISTRO_SLACKWARE; if (parse_release_file (g, fs, "/etc/slackware-version") == -1) return -1; if (guestfs___parse_major_minor (g, fs) == -1) return -1; } else if (guestfs_is_file_opts (g, "/etc/ttylinux-target", GUESTFS_IS_FILE_OPTS_FOLLOWSYMLINKS, 1, -1) > 0) { fs->distro = OS_DISTRO_TTYLINUX; if (parse_release_file (g, fs, "/etc/ttylinux-target") == -1) return -1; if (guestfs___parse_major_minor (g, fs) == -1) return -1; } else if (guestfs_is_file_opts (g, "/etc/SuSE-release", GUESTFS_IS_FILE_OPTS_FOLLOWSYMLINKS, 1, -1) > 0) { fs->distro = OS_DISTRO_SUSE_BASED; if (parse_suse_release (g, fs, "/etc/SuSE-release") == -1) return -1; } /* Buildroot (http://buildroot.net) is an embedded Linux distro * toolkit. It is used by specific distros such as Cirros. */ else if (guestfs_is_file_opts (g, "/etc/br-version", GUESTFS_IS_FILE_OPTS_FOLLOWSYMLINKS, 1, -1) > 0) { if (guestfs_is_file_opts (g, "/usr/share/cirros/logo", GUESTFS_IS_FILE_OPTS_FOLLOWSYMLINKS, 1, -1) > 0) fs->distro = OS_DISTRO_CIRROS; else fs->distro = OS_DISTRO_BUILDROOT; /* /etc/br-version has the format YYYY.MM[-git/hg/svn release] */ if (parse_release_file (g, fs, "/etc/br-version") == -1) return -1; if (guestfs___parse_major_minor (g, fs) == -1) return -1; } skip_release_checks:; /* Determine the architecture. */ check_architecture (g, fs); /* We already know /etc/fstab exists because it's part of the test * for Linux root above. We must now parse this file to determine * which filesystems are used by the operating system and how they * are mounted. */ const char *configfiles[] = { "/etc/fstab", "/etc/mdadm.conf", NULL }; if (inspect_with_augeas (g, fs, configfiles, check_fstab) == -1) return -1; /* Determine hostname. */ if (check_hostname_unix (g, fs) == -1) return -1; return 0; }
void guestfs_int_check_package_management (guestfs_h *g, struct inspect_fs *fs) { switch (fs->distro) { case OS_DISTRO_MEEGO: fs->package_management = OS_PACKAGE_MANAGEMENT_YUM; break; case OS_DISTRO_FEDORA: /* If Fedora >= 22 and dnf is installed, say "dnf". */ if (fs->major_version >= 22 && guestfs_is_file_opts (g, "/usr/bin/dnf", GUESTFS_IS_FILE_OPTS_FOLLOWSYMLINKS, 1, -1) > 0) fs->package_management = OS_PACKAGE_MANAGEMENT_DNF; else fs->package_management = OS_PACKAGE_MANAGEMENT_YUM; break; case OS_DISTRO_REDHAT_BASED: case OS_DISTRO_RHEL: case OS_DISTRO_CENTOS: case OS_DISTRO_SCIENTIFIC_LINUX: case OS_DISTRO_ORACLE_LINUX: if (fs->major_version >= 5) fs->package_management = OS_PACKAGE_MANAGEMENT_YUM; else fs->package_management = OS_PACKAGE_MANAGEMENT_UP2DATE; break; case OS_DISTRO_DEBIAN: case OS_DISTRO_UBUNTU: case OS_DISTRO_LINUX_MINT: fs->package_management = OS_PACKAGE_MANAGEMENT_APT; break; case OS_DISTRO_ARCHLINUX: fs->package_management = OS_PACKAGE_MANAGEMENT_PACMAN; break; case OS_DISTRO_GENTOO: fs->package_management = OS_PACKAGE_MANAGEMENT_PORTAGE; break; case OS_DISTRO_PARDUS: fs->package_management = OS_PACKAGE_MANAGEMENT_PISI; break; case OS_DISTRO_MAGEIA: case OS_DISTRO_MANDRIVA: fs->package_management = OS_PACKAGE_MANAGEMENT_URPMI; break; case OS_DISTRO_SUSE_BASED: case OS_DISTRO_OPENSUSE: case OS_DISTRO_SLES: fs->package_management = OS_PACKAGE_MANAGEMENT_ZYPPER; break; case OS_DISTRO_SLACKWARE: case OS_DISTRO_TTYLINUX: case OS_DISTRO_COREOS: case OS_DISTRO_WINDOWS: case OS_DISTRO_BUILDROOT: case OS_DISTRO_CIRROS: case OS_DISTRO_FREEDOS: case OS_DISTRO_FREEBSD: case OS_DISTRO_NETBSD: case OS_DISTRO_OPENBSD: case OS_DISTRO_UNKNOWN: fs->package_management = OS_PACKAGE_MANAGEMENT_UNKNOWN; break; } }