[7260bdc2] | 1 | import glob |
---|
| 2 | import platform |
---|
| 3 | import sys |
---|
| 4 | import os |
---|
| 5 | import subprocess |
---|
| 6 | import tempfile |
---|
| 7 | |
---|
| 8 | from engine.FileLib import * |
---|
| 9 | from engine.RegistryLib import * |
---|
| 10 | from engine.SystemLib import * |
---|
| 11 | from engine.FileSystemLib import * |
---|
| 12 | |
---|
| 13 | def ogGetArch(): |
---|
| 14 | if len(sys.argv) > 1 and sys.argv[1] == "help": |
---|
| 15 | ogHelp(sys.argv[0], sys.argv[0], sys.argv[0] + " => x86_64") |
---|
| 16 | return |
---|
| 17 | |
---|
| 18 | if platform.machine().endswith("64"): |
---|
| 19 | print("x86_64") |
---|
| 20 | else: |
---|
| 21 | print("i386") |
---|
| 22 | |
---|
| 23 | def ogGetOsType(): |
---|
| 24 | # Si se solicita, mostrar ayuda. |
---|
| 25 | if len(sys.argv) > 1 and sys.argv[1] == "help": |
---|
| 26 | ogHelp(sys.argv[0], sys.argv[0] + " int_ndisk int_npartition", sys.argv[0] + " 1 2 => Linux") |
---|
| 27 | return |
---|
| 28 | ogGetOsVersion(sys.argv[1:]).split(':')[0] |
---|
| 29 | |
---|
| 30 | def ogGetOsUuid(): |
---|
| 31 | # Si se solicita, mostrar ayuda. |
---|
| 32 | if len(sys.argv) > 1 and sys.argv[1] == "help": |
---|
| 33 | ogHelp(sys.argv[0], sys.argv[0] + " int_ndisk int_nfilesys", sys.argv[0] + " 1 2 => 540e47c6-8e78-4178-aa46-042e4803fb16") |
---|
| 34 | return |
---|
| 35 | |
---|
| 36 | # Error si no se reciben 2 parametros. |
---|
| 37 | if len(sys.argv) != 3: |
---|
| 38 | ogRaiseError(OG_ERR_FORMAT) |
---|
| 39 | return |
---|
| 40 | |
---|
| 41 | # Montar la particion, si no lo estaba previamente. |
---|
| 42 | MNTDIR = ogMount(sys.argv[1], sys.argv[2]) |
---|
| 43 | if not MNTDIR: |
---|
| 44 | return |
---|
| 45 | |
---|
| 46 | # Obtener UUID según el tipo de sistema operativo. |
---|
| 47 | os_type = ogGetOsType(sys.argv[1], sys.argv[2]) |
---|
| 48 | if os_type == "Linux": |
---|
| 49 | # Leer el UUID del sistema de ficheros raíz o el fichero de identificador. |
---|
| 50 | uuid = subprocess.check_output(["findmnt", "-no", "UUID", MNTDIR], stderr=subprocess.DEVNULL).decode().strip() or open(os.path.join(MNTDIR, "etc", "machine-id")).read().strip() |
---|
| 51 | print(uuid) |
---|
| 52 | elif os_type == "Windows": |
---|
| 53 | # Leer identificador en clave de registro. |
---|
| 54 | uuid = ogGetRegistryValue(MNTDIR, "SOFTWARE", "\\Microsoft\\Cryptography\\MachineGuid") |
---|
| 55 | print(uuid) |
---|
| 56 | |
---|
| 57 | def ogGetSerialNumber(): |
---|
| 58 | # Si se solicita, mostrar ayuda. |
---|
| 59 | if len(sys.argv) > 1 and sys.argv[1] == "help": |
---|
| 60 | ogHelp(sys.argv[0], sys.argv[0], sys.argv[0] + " => 123456") |
---|
| 61 | return |
---|
| 62 | |
---|
| 63 | # Obtener nº de serie (ignorar los no especificados). |
---|
| 64 | SERIALNO = subprocess.check_output(["dmidecode", "-s", "system-serial-number"]).decode().strip() |
---|
| 65 | SERIALNO = re.sub(r"(not specified|to be filled|invalid entry|default string)", "", SERIALNO, flags=re.IGNORECASE) |
---|
| 66 | SERIALNO = SERIALNO.replace(" ", "") |
---|
| 67 | SERIALNO = SERIALNO[:25] if len(SERIALNO) > 25 else SERIALNO |
---|
| 68 | if SERIALNO: |
---|
| 69 | print(SERIALNO) |
---|
| 70 | |
---|
| 71 | return 0 |
---|
| 72 | |
---|
| 73 | def ogIsEfiActive(): |
---|
| 74 | return os.path.isdir("/sys/firmware/efi") |
---|
| 75 | |
---|
| 76 | def ogListHardwareInfo(): |
---|
| 77 | # Si se solicita, mostrar ayuda. |
---|
| 78 | if len(sys.argv) > 1 and sys.argv[1] == "help": |
---|
| 79 | ogHelp(sys.argv[0], sys.argv[0]) |
---|
| 80 | return |
---|
| 81 | |
---|
| 82 | # Recopilación de dispositivos procesando la salida de \c lshw |
---|
| 83 | ogEcho("info", MSG_HARDWAREINVENTORY) |
---|
| 84 | output = subprocess.check_output('echo "cha=$(dmidecode -s chassis-type)" | grep -v "Other"', shell=True).decode().strip() |
---|
| 85 | print(output) |
---|
| 86 | if os.path.isdir("/sys/firmware/efi"): |
---|
| 87 | print("boo=UEFI") |
---|
| 88 | else: |
---|
| 89 | print("boo=BIOS") |
---|
| 90 | subprocess.call(["lshw", "|", "awk", "'BEGIN {type=\"mod\";}", |
---|
| 91 | "/product:/ {sub(/ *product: */,\"\", prod=$0);}", |
---|
| 92 | "/vendor:/ {sub(/ *vendor: */,\"\", vend=$0);}", |
---|
| 93 | "/version:/ {sub(/ *version: */,\"v.\", vers=$0);}", |
---|
| 94 | "/size:/ {size=$2;}", |
---|
| 95 | "/clock:/ {clock=$2;}", |
---|
| 96 | "/slot:/ {sub(/ *slot: */,\"\", slot=$0);}", |
---|
| 97 | "/\\*-/ {if (type==\"mem\"){", |
---|
| 98 | "if (size!=\"\"){", |
---|
| 99 | "numbank++;", |
---|
| 100 | "print type\"=\"vend,prod,size,clock\" (\"slot\")\";}", |
---|
| 101 | "}else{", |
---|
| 102 | "if (type==\"totalmem\"){", |
---|
| 103 | "if (size!=\"\"){", |
---|
| 104 | "totalmemory=\"mem=\"size;}", |
---|
| 105 | "}else{", |
---|
| 106 | "if (type!=\"\" && prod!=\"\"){", |
---|
| 107 | "if (prod==\"v.\"vers)", |
---|
| 108 | "vers=\"\";", |
---|
| 109 | "print type\"=\"vend,prod,size,vers;}}}", |
---|
| 110 | "type=prod=vend=vers=size=clock=slot=\"\";}", |
---|
| 111 | "$1~/-core/ {type=\"boa\";}", |
---|
| 112 | "$1~/-firmware/ {type=\"bio\";}", |
---|
| 113 | "$1~/-cpu/ {type=\"cpu\";}", |
---|
| 114 | "$1~/-bank/ {type=\"mem\";}", |
---|
| 115 | "$1~/-memory/ {type=\"totalmem\";}", |
---|
| 116 | "$1~/-ide/ {type=\"ide\";}", |
---|
| 117 | "$1~/-storage/ {type=\"sto\";}", |
---|
| 118 | "$1~/-disk/ {type=\"dis\";}", |
---|
| 119 | "$1~/-cdrom/ {type=\"cdr\";}", |
---|
| 120 | "$1~/-display/ {type=\"vga\";}", |
---|
| 121 | "$1~/-network/ {type=\"net\";}", |
---|
| 122 | "$1~/-multimedia/ {type=\"mul\";}", |
---|
| 123 | "$1~/-usb/ {type=\"usb\";}", |
---|
| 124 | "$1~/-firewire/ {type=\"fir\";}", |
---|
| 125 | "$1~/-serial/ {type=\"bus\";}", |
---|
| 126 | "END {if (type!=\"\" && prod!=\"\")", |
---|
| 127 | "print type\"=\"vend,prod,size,vers;", |
---|
| 128 | "if (length(numbank)==0 && length(totalmemory)>=4)", |
---|
| 129 | "print totalmemory; }'", |
---|
| 130 | ]) |
---|
| 131 | # */ (comentario para Doxygen) |
---|
| 132 | |
---|
| 133 | def ogListSoftware(): |
---|
| 134 | # Si se solicita, mostrar ayuda. |
---|
| 135 | if len(sys.argv) > 1 and sys.argv[1] == "help": |
---|
| 136 | ogHelp(sys.argv[0], sys.argv[0] + " 1 1") |
---|
| 137 | return |
---|
| 138 | |
---|
| 139 | # Error si no se reciben 2 parametros. |
---|
| 140 | if len(sys.argv) != 3: |
---|
| 141 | ogRaiseError(OG_ERR_FORMAT) |
---|
| 142 | return |
---|
| 143 | |
---|
| 144 | # Obtener tipo de sistema de archivos y montarlo. |
---|
| 145 | MNTDIR = ogMount(sys.argv[1], sys.argv[2]) |
---|
| 146 | if not MNTDIR: |
---|
| 147 | return |
---|
| 148 | TYPE = ogGetOsType(sys.argv[1], sys.argv[2]) |
---|
| 149 | if not TYPE: |
---|
| 150 | return |
---|
| 151 | |
---|
| 152 | # Ficheros temporales. |
---|
| 153 | APPS = tempfile.mktemp() |
---|
| 154 | TMPFILE = tempfile.mktemp() |
---|
| 155 | try: |
---|
| 156 | with open(APPS, "w") as apps_file: |
---|
| 157 | if TYPE == "Linux": |
---|
| 158 | # Procesar paquetes dpkg. |
---|
| 159 | PKGDIR = os.path.join(MNTDIR, "var", "lib", "dpkg") |
---|
| 160 | if os.path.exists(PKGDIR): |
---|
| 161 | # Proceso de fichero en sistemas de 64 bits. |
---|
| 162 | subprocess.call(["awk", "/Package:/ {if (pack!=\"\") print pack,vers;\ |
---|
| 163 | sub(/-dev$/,\"\",$2);\ |
---|
| 164 | pack=$2}\ |
---|
| 165 | /Version:/ {sub(/^.*:/,\"\",$2); sub(/-.*$/,\"\",$2);\ |
---|
| 166 | vers=$2}\ |
---|
| 167 | /Status:/ {if ($2!=\"install\") pack=vers=\"\"}\ |
---|
| 168 | END {if (pack!=\"\") print pack,vers}", os.path.join(PKGDIR, "status")], stdout=apps_file) |
---|
| 169 | |
---|
| 170 | # Procesar paquetes RPM. |
---|
| 171 | PKGDIR = os.path.join(MNTDIR, "var", "lib", "rpm") |
---|
| 172 | if os.path.exists(PKGDIR): |
---|
| 173 | # Listar si está instalado el paquete "rpm" en el cliente. |
---|
| 174 | if shutil.which("rpm"): |
---|
| 175 | subprocess.call(["rm", "-f", os.path.join(PKGDIR, "__db.*")]) |
---|
| 176 | subprocess.call(["rpm", "--dbpath", PKGDIR, "-qa", "--qf", "%{NAME} %{VERSION}\n"], stdout=apps_file, stderr=subprocess.DEVNULL) |
---|
| 177 | subprocess.call(["rm", "-f", os.path.join(PKGDIR, "__db.*")]) |
---|
| 178 | else: |
---|
| 179 | # Obtener el nombre de cada paquete en la BD de RPM. |
---|
| 180 | subprocess.call(["python", "-c", f"import re; import bsddb; db=bsddb.hashopen('{os.path.join(PKGDIR, 'Name')}','r');\ |
---|
| 181 | for k in db.keys():\ |
---|
| 182 | print(re.sub('-devel$','',k));"], stdout=apps_file) |
---|
| 183 | |
---|
| 184 | # Procesar paquetes pacman. |
---|
| 185 | PKGDIR = os.path.join(MNTDIR, "var", "lib", "pacman", "local") |
---|
| 186 | if os.path.exists(PKGDIR): |
---|
| 187 | subprocess.call(["ls", PKGDIR], stdout=subprocess.PIPE) |
---|
| 188 | subprocess.call(["awk", "-F-", "/-/ {print gensub(/-/, \" \", NF-2);}", os.path.join(PKGDIR, "*")], stdout=apps_file) |
---|
| 189 | |
---|
| 190 | # Procesar aplicaciones Snappy. |
---|
| 191 | PKGDIR = os.path.join(MNTDIR, "snap") |
---|
| 192 | subprocess.call(["find", PKGDIR, "-name", "snap.yaml", "-exec", "awk", "/name:/ {pack=$2}\ |
---|
| 193 | /version:/ {vers=$2}\ |
---|
| 194 | END {if (pack!=\"\") print pack,\"(snap)\",vers}", "{}", "+", "2>/dev/null"], stdout=apps_file) |
---|
| 195 | |
---|
| 196 | # Procesar aplicaciones Flatpak. |
---|
| 197 | PKGDIR = os.path.join(MNTDIR, "var", "lib", "flatpak") |
---|
| 198 | subprocess.call(["ls", "-1", os.path.join(PKGDIR, "app", "*", "current", "active", "deploy")], stderr=subprocess.DEVNULL) |
---|
| 199 | subprocess.call(["python", "-c", "import sys; for f in sys.stdin:\ |
---|
| 200 | p = open(f.strip()).read().split('\0');\ |
---|
| 201 | try:\ |
---|
| 202 | if(p[0] != 'flathub'):\ |
---|
| 203 | raise ValueError;\ |
---|
| 204 | print('{} (flatpak) {}'.format(p[p.index('appdata-name') + 4], p[p.index('appdata-version') + 1]));\ |
---|
| 205 | except ValueError:\ |
---|
| 206 | pass;"], stdout=apps_file) |
---|
| 207 | |
---|
| 208 | elif TYPE == "Windows": |
---|
| 209 | # Comprobar tipo de proceso del registro de Windows. |
---|
| 210 | if shutil.which("hivexregedit"): |
---|
| 211 | # Nuevo proceso más rápido basado en "hivexregedit". |
---|
| 212 | HIVE = ogGetHivePath(MNTDIR, "software") |
---|
| 213 | if HIVE: |
---|
| 214 | # Claves de registro para programas instalados. |
---|
| 215 | subprocess.call(["hivexregedit", "--unsafe-printable-strings", "--export", HIVE, "\\Microsoft\\Windows\\CurrentVersion\\Uninstall"], stdout=TMPFILE, stderr=subprocess.DEVNULL) |
---|
| 216 | subprocess.call(["hivexregedit", "--unsafe-printable-strings", "--export", HIVE, "\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall"], stdout=TMPFILE, stderr=subprocess.DEVNULL) |
---|
| 217 | # Mostrar los valores "DisplayName" y "DisplayVersion" para cada clave. |
---|
| 218 | subprocess.call(["awk", "-F\"", "$1~/^\\[/ {n=\"\"}\ |
---|
| 219 | $2~/DisplayName/ {n=$4}\ |
---|
| 220 | $2~/DisplayVersion/ {print n,$4}", TMPFILE], stdout=apps_file) |
---|
| 221 | else: |
---|
| 222 | # Compatibilidad con clientes ogLive antiguos. |
---|
| 223 | # Claves de registro para programas instalados: formato "{clave}". |
---|
| 224 | KEYS = ogListRegistryKeys(MNTDIR, "software", "\\Microsoft\\Windows\\CurrentVersion\\Uninstall") |
---|
| 225 | KEYS32 = ogListRegistryKeys(MNTDIR, "software", "\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall") |
---|
| 226 | # Mostrar los valores "DisplayName" y "DisplayVersion" para cada clave. |
---|
| 227 | for k in KEYS: |
---|
| 228 | PROG = ogGetRegistryValue(MNTDIR, "software", f"\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{k}\\DisplayName") |
---|
| 229 | if PROG: |
---|
| 230 | VERS = ogGetRegistryValue(MNTDIR, "software", f"\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{k}\\DisplayVersion") |
---|
| 231 | apps_file.write(f"{PROG} {VERS}\n") |
---|
| 232 | for k in KEYS32: |
---|
| 233 | PROG = ogGetRegistryValue(MNTDIR, "software", f"\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{k}\\DisplayName") |
---|
| 234 | if PROG: |
---|
| 235 | VERS = ogGetRegistryValue(MNTDIR, "software", f"\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{k}\\DisplayVersion") |
---|
| 236 | apps_file.write(f"{PROG} {VERS}\n") |
---|
| 237 | |
---|
| 238 | elif TYPE == "MacOS": |
---|
| 239 | # Listar directorios de aplicaciones e intentar obtener la versión del fichero .plist (tanto original como descomprimido). |
---|
| 240 | for root, dirs, files in os.walk(os.path.join(MNTDIR, "Applications")): |
---|
| 241 | for dir in dirs: |
---|
| 242 | if dir.endswith(".app"): |
---|
| 243 | file = os.path.join(root, dir, "Contents", "version.plist") |
---|
| 244 | if not os.path.exists(file): |
---|
| 245 | file = os.path.join(root, dir, "Contents", "version.plist.uncompress") |
---|
| 246 | if os.path.exists(file): |
---|
| 247 | with open(file, "r") as plist_file: |
---|
| 248 | plist_data = plist_file.read() |
---|
| 249 | version = re.search("<key>ShortVersionString</key>\s*<string>(.*?)</string>", plist_data) |
---|
| 250 | if version: |
---|
| 251 | apps_file.write(f"{os.path.basename(dir)}.app {version.group(1)}\n") |
---|
| 252 | |
---|
| 253 | elif TYPE == "BSD": |
---|
| 254 | subprocess.call(["sqlite3", os.path.join(MNTDIR, "var", "db", "pkg", "local.sqlite")], input="SELECT name FROM pkg_search;", stdout=apps_file, stderr=subprocess.DEVNULL) |
---|
| 255 | |
---|
| 256 | # Mostrar sistema Operativo y aplicaciones. |
---|
| 257 | ogGetOsVersion(sys.argv[1], sys.argv[2]).split(":")[1].strip() |
---|
| 258 | with open(APPS, "r") as apps_file: |
---|
| 259 | apps = apps_file.readlines() |
---|
| 260 | apps = sorted(set(apps)) |
---|
| 261 | for app in apps: |
---|
| 262 | print(app.strip()) |
---|
| 263 | finally: |
---|
| 264 | os.remove(APPS) |
---|
| 265 | os.remove(TMPFILE) |
---|
| 266 | |
---|
| 267 | def ogGetOsVersion(ndisk, nfilesys): |
---|
| 268 | # Variables locales. |
---|
| 269 | MNTDIR = ogMount(ndisk, nfilesys) |
---|
| 270 | TYPE = "" |
---|
| 271 | VERSION = "" |
---|
| 272 | IS64BIT = "" |
---|
| 273 | |
---|
| 274 | # Si se solicita, mostrar ayuda. |
---|
| 275 | if len(sys.argv) > 1 and sys.argv[1] == "help": |
---|
| 276 | ogHelp(sys.argv[0], sys.argv[0] + " int_ndisk int_nfilesys", sys.argv[0] + " 1 2 => Linux:Ubuntu precise (12.04 LTS) 64 bits") |
---|
| 277 | return |
---|
| 278 | |
---|
| 279 | # Error si no se reciben 2 parametros. |
---|
| 280 | if len(sys.argv) != 3: |
---|
| 281 | ogRaiseError(OG_ERR_FORMAT) |
---|
| 282 | return |
---|
| 283 | |
---|
| 284 | # Montar la particion, si no lo estaba previamente. |
---|
| 285 | MNTDIR = ogMount(sys.argv[1], sys.argv[2]) |
---|
| 286 | if not MNTDIR: |
---|
| 287 | return |
---|
| 288 | |
---|
| 289 | # Buscar tipo de sistema operativo. |
---|
| 290 | # Para GNU/Linux: leer descripción. |
---|
| 291 | TYPE = "Linux" |
---|
| 292 | FILE = os.path.join(MNTDIR, "etc", "os-release") |
---|
| 293 | if os.path.exists(FILE): |
---|
| 294 | with open(FILE, "r") as f: |
---|
| 295 | for line in f: |
---|
| 296 | if line.startswith("PRETTY_NAME"): |
---|
| 297 | VERSION = line.split("=")[1].strip().strip('"') |
---|
| 298 | break |
---|
| 299 | |
---|
| 300 | # Si no se puede obtener, buscar en ficheros del sistema. |
---|
| 301 | if not VERSION: |
---|
| 302 | FILE = os.path.join(MNTDIR, "etc", "lsb-release") |
---|
| 303 | if os.path.exists(FILE): |
---|
| 304 | with open(FILE, "r") as f: |
---|
| 305 | for line in f: |
---|
| 306 | if line.startswith("DESCRIPTION"): |
---|
| 307 | VERSION = line.split("=")[1].strip().strip('"') |
---|
| 308 | break |
---|
| 309 | for DISTRIB in ["redhat", "SuSE", "mandrake", "gentoo"]: |
---|
| 310 | FILE = os.path.join(MNTDIR, "etc", f"{DISTRIB}-release") |
---|
| 311 | if os.path.exists(FILE): |
---|
| 312 | with open(FILE, "r") as f: |
---|
| 313 | VERSION = f.readline().strip() |
---|
| 314 | break |
---|
| 315 | FILE = os.path.join(MNTDIR, "etc", "arch-release") |
---|
| 316 | if os.path.exists(FILE): |
---|
| 317 | VERSION = "Arch Linux" |
---|
| 318 | FILE = os.path.join(MNTDIR, "etc", "slackware-version") |
---|
| 319 | if os.path.exists(FILE): |
---|
| 320 | with open(FILE, "r") as f: |
---|
| 321 | VERSION = f.read().strip() |
---|
| 322 | |
---|
| 323 | # Si no se encuentra, intentar ejecutar "lsb_release". |
---|
| 324 | if not VERSION: |
---|
| 325 | try: |
---|
| 326 | output = subprocess.check_output(["chroot", MNTDIR, "lsb_release", "-d"], stderr=subprocess.DEVNULL).decode().strip() |
---|
| 327 | VERSION = output.split(":")[1].strip() |
---|
| 328 | except subprocess.CalledProcessError: |
---|
| 329 | pass |
---|
| 330 | |
---|
| 331 | # Comprobar Linux de 64 bits. |
---|
| 332 | if VERSION and os.path.exists(os.path.join(MNTDIR, "lib64")): |
---|
| 333 | IS64BIT = "64 bits" |
---|
| 334 | |
---|
| 335 | # Para Android, leer fichero de propiedades. |
---|
| 336 | if not VERSION: |
---|
| 337 | TYPE = "Android" |
---|
| 338 | FILE = os.path.join(MNTDIR, "android*", "system", "build.prop") |
---|
| 339 | if glob.glob(FILE): |
---|
| 340 | with open(glob.glob(FILE)[0], "r") as f: |
---|
| 341 | lines = f.readlines() |
---|
| 342 | brand = "" |
---|
| 343 | release = "" |
---|
| 344 | for line in lines: |
---|
| 345 | if line.startswith("product.brand"): |
---|
| 346 | brand = line.split("=")[1].strip() |
---|
| 347 | elif line.startswith("build.version.release"): |
---|
| 348 | release = line.split("=")[1].strip() |
---|
| 349 | VERSION = f"Android {brand} {release}" |
---|
| 350 | if os.path.exists(os.path.join(MNTDIR, "lib64")): |
---|
| 351 | IS64BIT = "64 bits" |
---|
| 352 | |
---|
| 353 | # Para GNU/Hurd, comprobar fichero de inicio (basado en os-prober). |
---|
| 354 | if not VERSION: |
---|
| 355 | TYPE = "Hurd" |
---|
| 356 | FILE = os.path.join(MNTDIR, "hurd", "init") |
---|
| 357 | if os.path.exists(FILE): |
---|
| 358 | VERSION = "GNU/Hurd" |
---|
| 359 | |
---|
| 360 | # Para Windows: leer la version del registro. |
---|
| 361 | if not VERSION: |
---|
| 362 | TYPE = "Windows" |
---|
| 363 | FILE = ogGetHivePath(MNTDIR, "SOFTWARE") |
---|
| 364 | if FILE: |
---|
| 365 | try: |
---|
| 366 | output = subprocess.check_output(["hivexsh", "load", FILE, "cd", "\\Microsoft\\Windows NT\\CurrentVersion", "lsval", "ProductName", "lsval", "DisplayVersion"], stderr=subprocess.DEVNULL).decode().strip() |
---|
| 367 | lines = output.split("\n") |
---|
| 368 | if len(lines) == 2: |
---|
| 369 | VERSION = lines[1].strip() |
---|
| 370 | if ogGetRegistryValue(MNTDIR, "SOFTWARE", "\\Microsoft\\Windows\\CurrentVersion\\ProgramW6432Dir"): |
---|
| 371 | IS64BIT = "64 bits" |
---|
| 372 | except subprocess.CalledProcessError: |
---|
| 373 | pass |
---|
| 374 | |
---|
| 375 | # Para cargador Windows: buscar versión en fichero BCD (basado en os-prober). |
---|
| 376 | if not VERSION: |
---|
| 377 | TYPE = "WinLoader" |
---|
| 378 | FILE = ogGetPath(MNTDIR, "boot", "bcd") |
---|
| 379 | if not FILE: |
---|
| 380 | FILE = ogGetPath(MNTDIR, "EFI", "Microsoft", "boot", "bcd") |
---|
| 381 | if FILE: |
---|
| 382 | for DISTRIB in ["Windows Recovery", "Windows Boot"]: |
---|
| 383 | with open(FILE, "rb") as f: |
---|
| 384 | if re.search(DISTRIB.encode(), f.read()): |
---|
| 385 | VERSION = f"{DISTRIB} loader" |
---|
| 386 | break |
---|
| 387 | |
---|
| 388 | # Para macOS: detectar kernel y completar con fichero plist de información del sistema. |
---|
| 389 | if not VERSION: |
---|
| 390 | TYPE = "MacOS" |
---|
| 391 | FILE = os.path.join(MNTDIR, "mach_kernel") |
---|
| 392 | if os.path.exists(FILE) and not subprocess.check_output(["file", "-b", FILE]).decode().strip().startswith("text"): |
---|
| 393 | if subprocess.check_output(["file", "-b", FILE]).decode().strip().startswith("Mach-O"): |
---|
| 394 | VERSION = "macOS" |
---|
| 395 | if subprocess.check_output(["file", "-b", FILE]).decode().strip().startswith("Mach-O 64-bit"): |
---|
| 396 | IS64BIT = "64 bits" |
---|
| 397 | FILE = os.path.join(MNTDIR, "System", "Library", "CoreServices", "SystemVersion.plist") |
---|
| 398 | if os.path.exists(FILE): |
---|
| 399 | with open(FILE, "r") as f: |
---|
| 400 | plist_data = f.read() |
---|
| 401 | product_name = re.search("<key>ProductName</key>\s*<string>(.*?)</string>", plist_data) |
---|
| 402 | product_version = re.search("<key>ProductVersion</key>\s*<string>(.*?)</string>", plist_data) |
---|
| 403 | if product_name and product_version: |
---|
| 404 | VERSION = f"{product_name.group(1)} {product_version.group(1)}" |
---|
| 405 | FILE = os.path.join(MNTDIR, "com.apple.recovery.boot") |
---|
| 406 | if os.path.exists(FILE) and VERSION: |
---|
| 407 | VERSION = f"{VERSION} recovery" |
---|
| 408 | |
---|
| 409 | # Para FreeBSD: obtener datos del Kernel. |
---|
| 410 | if not VERSION: |
---|
| 411 | TYPE = "BSD" |
---|
| 412 | FILE = os.path.join(MNTDIR, "boot", "kernel", "kernel") |
---|
| 413 | if os.path.exists(FILE): |
---|
| 414 | output = subprocess.check_output(["strings", FILE]).decode().strip() |
---|
| 415 | match = re.search(r"@.*RELEASE", output) |
---|
| 416 | if match: |
---|
| 417 | VERSION = match.group().split("@")[0].strip() |
---|
| 418 | if subprocess.check_output(["file", "-b", FILE]).decode().strip().endswith("x86-64"): |
---|
| 419 | IS64BIT = "64 bits" |
---|
| 420 | |
---|
| 421 | # Para Solaris: leer el fichero de versión. |
---|
| 422 | if not VERSION: |
---|
| 423 | TYPE = "Solaris" |
---|
| 424 | FILE = os.path.join(MNTDIR, "etc", "release") |
---|
| 425 | if os.path.exists(FILE): |
---|
| 426 | with open(FILE, "r") as f: |
---|
| 427 | VERSION = f.readline().strip() |
---|
| 428 | |
---|
| 429 | # Para cargador GRUB, comprobar fichero de configuración. |
---|
| 430 | if not VERSION: |
---|
| 431 | TYPE = "GrubLoader" |
---|
| 432 | for FILE in [os.path.join(MNTDIR, "grub", "menu.lst"), os.path.join(MNTDIR, "boot", "grub", "menu.lst")]: |
---|
| 433 | if os.path.exists(FILE): |
---|
| 434 | VERSION = "GRUB Loader" |
---|
| 435 | break |
---|
| 436 | for FILE in glob.glob(os.path.join(MNTDIR, "{,boot/}{grub{,2},EFI/*}/grub.cfg")): |
---|
| 437 | if os.path.exists(FILE): |
---|
| 438 | VERSION = "GRUB2 Loader" |
---|
| 439 | break |
---|
| 440 | |
---|
| 441 | # Mostrar resultado y salir sin errores. |
---|
| 442 | if VERSION: |
---|
| 443 | print(f"{TYPE}:{VERSION} {IS64BIT}") |
---|
| 444 | |
---|
| 445 | return 0 |
---|