/* libguestfs * Copyright (C) 2018 Red Hat Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include "guestfs.h" #include "guestfs-internal.h" #include "guestfs-internal-actions.h" char * guestfs_impl_inspect_get_osinfo (guestfs_h *g, const char *root) { CLEANUP_FREE char *type = NULL; CLEANUP_FREE char *distro = NULL; int major, minor; type = guestfs_inspect_get_type (g, root); if (!type) return NULL; distro = guestfs_inspect_get_distro (g, root); if (!distro) return NULL; major = guestfs_inspect_get_major_version (g, root); minor = guestfs_inspect_get_minor_version (g, root); if (STREQ (type, "linux")) { if (STREQ (distro, "centos")) { if (major >= 8) return safe_asprintf (g, "%s%d", distro, major); else if (major == 7) return safe_asprintf (g, "%s%d.0", distro, major); else if (major == 6) return safe_asprintf (g, "%s%d.%d", distro, major, minor); } else if (STREQ (distro, "circle")) { if (major >= 8) return safe_asprintf (g, "%s%d", distro, major); } else if (STREQ (distro, "rocky")) { if (major >= 8) return safe_asprintf (g, "%s%d", distro, major); } else if (STREQ (distro, "debian")) { if (major >= 4) return safe_asprintf (g, "%s%d", distro, major); } else if (STREQ (distro, "fedora") || STREQ (distro, "mageia")) return safe_asprintf (g, "%s%d", distro, major); else if (STREQ (distro, "sles")) { const char *base = major >= 15 ? "sle" : "sles"; if (minor == 0) return safe_asprintf (g, "%s%d", base, major); else return safe_asprintf (g, "%s%dsp%d", base, major, minor); } else if (STREQ (distro, "ubuntu")) return safe_asprintf (g, "%s%d.%02d", distro, major, minor); else if (STREQ (distro, "archlinux") || STREQ (distro, "gentoo") || STREQ (distro, "voidlinux")) return safe_strdup (g, distro); else if (STREQ (distro, "altlinux")) { if (major >= 8) return safe_asprintf (g, "alt%d.%d", major, minor); return safe_asprintf (g, "%s%d.%d", distro, major, minor); } if (STRNEQ (distro, "unknown") && (major > 0 || minor > 0)) return safe_asprintf (g, "%s%d.%d", distro, major, minor); } else if (STREQ (type, "freebsd") || STREQ (type, "netbsd") || STREQ (type, "openbsd")) return safe_asprintf (g, "%s%d.%d", distro, major, minor); else if (STREQ (type, "dos")) { if (STREQ (distro, "msdos")) return safe_strdup (g, "msdos6.22"); } else if (STREQ (type, "windows")) { CLEANUP_FREE char *product_name = NULL; CLEANUP_FREE char *product_variant = NULL; CLEANUP_FREE char *build_id_str = NULL; int build_id; product_name = guestfs_inspect_get_product_name (g, root); if (!product_name) return NULL; product_variant = guestfs_inspect_get_product_variant (g, root); if (!product_variant) return NULL; switch (major) { case 5: switch (minor) { case 1: return safe_strdup (g, "winxp"); case 2: if (strstr (product_name, "XP")) return safe_strdup (g, "winxp"); else if (strstr (product_name, "R2")) return safe_strdup (g, "win2k3r2"); else return safe_strdup (g, "win2k3"); } break; case 6: switch (minor) { case 0: if (strstr (product_variant, "Server")) return safe_strdup (g, "win2k8"); else return safe_strdup (g, "winvista"); case 1: if (strstr (product_variant, "Server")) return safe_strdup (g, "win2k8r2"); else return safe_strdup (g, "win7"); case 2: if (strstr (product_variant, "Server")) return safe_strdup (g, "win2k12"); else return safe_strdup (g, "win8"); case 3: if (strstr (product_variant, "Server")) return safe_strdup (g, "win2k12r2"); else return safe_strdup (g, "win8.1"); } break; case 10: switch (minor) { case 0: if (strstr (product_variant, "Server")) { if (strstr (product_name, "2025")) return safe_strdup (g, "win2k25"); else if (strstr (product_name, "2022")) return safe_strdup (g, "win2k22"); else if (strstr (product_name, "2019")) return safe_strdup (g, "win2k19"); else return safe_strdup (g, "win2k16"); } else { /* For Windows >= 10 Client we can only distinguish between * versions by looking at the build ID. See: * https://learn.microsoft.com/en-us/answers/questions/586619/windows-11-build-ver-is-still-10022000194.html * https://github.com/cygwin/cygwin/blob/a263fe0b268580273c1adc4b1bad256147990222/winsup/cygwin/wincap.cc#L429 */ build_id_str = guestfs_inspect_get_build_id (g, root); if (!build_id_str) return NULL; build_id = guestfs_int_parse_unsigned_int (g, build_id_str); if (build_id == -1) return NULL; if (build_id >= 22000) return safe_strdup (g, "win11"); else return safe_strdup (g, "win10"); } } break; } } /* No ID could be guessed, return "unknown". */ return safe_strdup (g, "unknown"); }