X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=src%2Finspect.c;h=e7b1e41375bd1a0df5c41448001670413b64cf10;hb=2a33d81e2b7fa2affaaad48538307c818b4a8260;hp=6938c106db203d6efb71de476cb21bf69c09be43;hpb=6e9917f72528d75e819b810bea8e0abd875b6810;p=libguestfs.git diff --git a/src/inspect.c b/src/inspect.c index 6938c10..e7b1e41 100644 --- a/src/inspect.c +++ b/src/inspect.c @@ -52,7 +52,7 @@ static pcre *re_fedora; static pcre *re_rhel_old; static pcre *re_rhel; static pcre *re_rhel_no_minor; -static pcre *re_debian; +static pcre *re_major_minor; static pcre *re_aug_seq; static pcre *re_xdev; static pcre *re_windows_version; @@ -85,7 +85,7 @@ compile_regexps (void) "(?:Red Hat Enterprise Linux|CentOS|Scientific Linux).*release (\\d+)\\.(\\d+)", 0); COMPILE (re_rhel_no_minor, "(?:Red Hat Enterprise Linux|CentOS|Scientific Linux).*release (\\d+)", 0); - COMPILE (re_debian, "(\\d+)\\.(\\d+)", 0); + COMPILE (re_major_minor, "(\\d+)\\.(\\d+)", 0); COMPILE (re_aug_seq, "/\\d+$", 0); COMPILE (re_xdev, "^/dev/(?:h|s|v|xv)d([a-z]\\d*)$", 0); COMPILE (re_windows_version, "^(\\d+)\\.(\\d+)", 0); @@ -101,7 +101,7 @@ free_regexps (void) pcre_free (re_rhel_old); pcre_free (re_rhel); pcre_free (re_rhel_no_minor); - pcre_free (re_debian); + pcre_free (re_major_minor); pcre_free (re_aug_seq); pcre_free (re_xdev); pcre_free (re_windows_version); @@ -645,6 +645,88 @@ parse_release_file (guestfs_h *g, struct inspect_fs *fs, return 0; } +/* Parse generic MAJOR.MINOR from the fs->product_name string. */ +static int +parse_major_minor (guestfs_h *g, struct inspect_fs *fs) +{ + char *major, *minor; + + if (match2 (g, fs->product_name, re_major_minor, &major, &minor)) { + fs->major_version = parse_unsigned_int (g, major); + free (major); + if (fs->major_version == -1) { + free (minor); + return -1; + } + fs->minor_version = parse_unsigned_int (g, minor); + free (minor); + if (fs->minor_version == -1) + return -1; + } + return 0; +} + +/* Ubuntu has /etc/lsb-release containing: + * DISTRIB_ID=Ubuntu # Distro + * DISTRIB_RELEASE=10.04 # Version + * DISTRIB_CODENAME=lucid + * DISTRIB_DESCRIPTION="Ubuntu 10.04.1 LTS" # Product name + * In theory other distros could have this LSB file, but none do. + */ +static int +parse_lsb_release (guestfs_h *g, struct inspect_fs *fs) +{ + char **lines; + size_t i; + int r = 0; + + lines = guestfs_head_n (g, 10, "/etc/lsb-release"); + if (lines == NULL) + return -1; + + for (i = 0; lines[i] != NULL; ++i) { + if (fs->distro == 0 && + STREQ (lines[i], "DISTRIB_ID=Ubuntu")) { + fs->distro = OS_DISTRO_UBUNTU; + r = 1; + } + else if (STRPREFIX (lines[i], "DISTRIB_RELEASE=")) { + char *major, *minor; + if (match2 (g, &lines[i][16], re_major_minor, &major, &minor)) { + fs->major_version = parse_unsigned_int (g, major); + free (major); + if (fs->major_version == -1) { + free (minor); + free_string_list (lines); + return -1; + } + fs->minor_version = parse_unsigned_int (g, minor); + free (minor); + if (fs->minor_version == -1) { + free_string_list (lines); + return -1; + } + } + } + else if (fs->product_name == NULL && + (STRPREFIX (lines[i], "DISTRIB_DESCRIPTION=\"") || + STRPREFIX (lines[i], "DISTRIB_DESCRIPTION='"))) { + size_t len = strlen (lines[i]) - 21 - 1; + fs->product_name = safe_strndup (g, &lines[i][21], len); + r = 1; + } + else if (fs->product_name == NULL && + STRPREFIX (lines[i], "DISTRIB_DESCRIPTION=")) { + size_t len = strlen (lines[i]) - 20; + fs->product_name = safe_strndup (g, &lines[i][20], len); + r = 1; + } + } + + free_string_list (lines); + return r; +} + /* 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 @@ -653,8 +735,18 @@ parse_release_file (guestfs_h *g, struct inspect_fs *fs, static int check_linux_root (guestfs_h *g, struct inspect_fs *fs) { + int r; + fs->type = OS_TYPE_LINUX; + if (guestfs_exists (g, "/etc/lsb-release") > 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_exists (g, "/etc/redhat-release") > 0) { fs->distro = OS_DISTRO_REDHAT_BASED; /* Something generic Red Hat-like. */ @@ -698,20 +790,45 @@ check_linux_root (guestfs_h *g, struct inspect_fs *fs) if (parse_release_file (g, fs, "/etc/debian_version") == -1) return -1; - char *major, *minor; - if (match2 (g, fs->product_name, re_debian, &major, &minor)) { - fs->major_version = parse_unsigned_int (g, major); - free (major); - if (fs->major_version == -1) { - free (minor); - return -1; - } - fs->minor_version = parse_unsigned_int (g, minor); - free (minor); - if (fs->minor_version == -1) - return -1; - } + if (parse_major_minor (g, fs) == -1) + return -1; } + else if (guestfs_exists (g, "/etc/pardus-release") > 0) { + fs->distro = OS_DISTRO_PARDUS; + + if (parse_release_file (g, fs, "/etc/pardus-release") == -1) + return -1; + + if (parse_major_minor (g, fs) == -1) + return -1; + } + else if (guestfs_exists (g, "/etc/arch-release") > 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_exists (g, "/etc/gentoo-release") > 0) { + fs->distro = OS_DISTRO_GENTOO; + + if (parse_release_file (g, fs, "/etc/gentoo-release") == -1) + return -1; + + if (parse_major_minor (g, fs) == -1) + return -1; + } + else if (guestfs_exists (g, "/etc/meego-release") > 0) { + fs->distro = OS_DISTRO_MEEGO; + + if (parse_release_file (g, fs, "/etc/meego-release") == -1) + return -1; + + if (parse_major_minor (g, fs) == -1) + return -1; + } + + skip_release_checks:; /* Determine the architecture. */ const char *binaries[] = @@ -748,7 +865,7 @@ check_linux_root (guestfs_h *g, struct inspect_fs *fs) guestfs_aug_rm (g, "/augeas/load//incl[. != \"/etc/fstab\"]"); guestfs_aug_load (g); - int r = check_fstab (g, fs); + r = check_fstab (g, fs); guestfs_aug_close (g); if (r == -1) return -1; @@ -1226,11 +1343,16 @@ guestfs__inspect_get_distro (guestfs_h *g, const char *root) char *ret; switch (fs->distro) { + case OS_DISTRO_ARCHLINUX: ret = safe_strdup (g, "archlinux"); break; case OS_DISTRO_DEBIAN: ret = safe_strdup (g, "debian"); break; case OS_DISTRO_FEDORA: ret = safe_strdup (g, "fedora"); break; + case OS_DISTRO_GENTOO: ret = safe_strdup (g, "gentoo"); break; + case OS_DISTRO_MEEGO: ret = safe_strdup (g, "meego"); break; + case OS_DISTRO_PARDUS: ret = safe_strdup (g, "pardus"); break; case OS_DISTRO_REDHAT_BASED: ret = safe_strdup (g, "redhat-based"); break; case OS_DISTRO_RHEL: ret = safe_strdup (g, "rhel"); break; case OS_DISTRO_WINDOWS: ret = safe_strdup (g, "windows"); break; + case OS_DISTRO_UBUNTU: ret = safe_strdup (g, "ubuntu"); break; case OS_DISTRO_UNKNOWN: default: ret = safe_strdup (g, "unknown"); break; }