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 |
---|