From 6e53c31113cab52e987f17e0336af5d9971f8072 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 21 Nov 2024 15:54:07 +0100 Subject: [PATCH] refs #1166 add ogRestoreEfiBootLoader() --- client/lib/engine/bin/DiskLib.py | 377 ++++++++++++++------------ client/lib/engine/bin/InventoryLib.py | 315 ++++++++++++++++++--- client/lib/engine/bin/RegistryLib.py | 216 ++++++++++++--- client/lib/engine/bin/UEFILib.py | 232 ++++++++++++++++ 4 files changed, 880 insertions(+), 260 deletions(-) create mode 100644 client/lib/engine/bin/UEFILib.py diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py index ddb7168..55f25e2 100755 --- a/client/lib/engine/bin/DiskLib.py +++ b/client/lib/engine/bin/DiskLib.py @@ -486,6 +486,9 @@ def ogDiskToDev (arg_disk=None, arg_part=None): return disk # arg_disk and arg_part are set: there are several possibilities + if arg_disk > len (ALLDISKS): + SystemLib.ogRaiseError([], ogGlobals.OG_ERR_NOTFOUND, arg_disk) + return disk = ALLDISKS[arg_disk-1] if not os.path.exists(disk): SystemLib.ogRaiseError([], ogGlobals.OG_ERR_NOTFOUND, arg_disk) @@ -602,19 +605,27 @@ def ogGetDiskType(*args): print(TYPE) return -def ogGetEsp(): - for d in subprocess.getoutput("blkid -o device").split(): +#/** +# ogGetEsp +#@brief Devuelve números de disco y partición para la partición EFI (ESP). +#*/ ## +def ogGetEsp(): + devices = subprocess.run (['blkid', '-o', 'device'], capture_output=True, text=True).stdout.splitlines() + devices.sort() + for d in devices: # Previene error para /dev/loop0 - PART = ogDevToDisk([d]) + PART = ogDevToDisk (d) + if not PART: continue + # En discos NVMe blkid devuelve una salida del tipo: # >/dev/loop0 # >/dev/nvme0n1 # >/dev/nvme0n1p1 # al analizar la particion nvme0n1, PART solo tiene un argumento y hace que ogGetPartitionId lance un error - LEN = len(PART) - if LEN > 1: - if ogGetPartitionId(PART) == ogTypeToId("EFI", "GPT"): + if len (PART) > 1: + disk, par = PART.split() + if ogGetPartitionId (disk, par) == ogTypeToId ('EFI', 'GPT'): return PART return None @@ -674,39 +685,40 @@ def ogGetPartitionActive(*args): print(output) return -def ogGetPartitionId(*args): - # Variables locales - DISK = None - ID = None - # Si se solicita, mostrar ayuda. - if len(args) == 1 and args[0] == "help": - SystemLib.ogHelp('ogGetPartitionId', 'ogGetPartitionId int_ndisk int_npartition', 'ogGetPartitionId 1 1 => 7') - return +#/** +# ogGetPartitionId int_ndisk int_npartition +#@brief Devuelve el mnemónico con el tipo de partición. +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@return Identificador de tipo de partición. +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o partición no corresponde con un dispositivo. +#@note Requisitos: sfdisk +#*/ ## +def ogGetPartitionId (disk, par): + DISK = ogDiskToDev (disk) + if DISK is None: return - # Error si no se reciben 2 parámetros. - if len(args) != 2: - SystemLib.ogRaiseError(OG_ERR_FORMAT) - return + pttype = ogGetPartitionTableType (disk) + if 'GPT' == pttype: + lines = subprocess.run (['sgdisk', '-p', DISK], capture_output=True, text=True).stdout.splitlines() + start_index = next (i for i, line in enumerate(lines) if 'Number' in line) + for l in lines[start_index:]: + idx, start, end, sz, sz_units, code, *rest = l.split() + if idx == par: + fsid = code + break + if fsid == '8300' and f'{disk} {par}' == ogFindCache(): + fsid = 'CA00' + elif 'MSDOS' == pttype: + fsid = subprocess.run (['sfdisk', '--part-type', DISK, par], capture_output=True, text=True).stdout.strip() + elif 'LVM' == pttype: + fsid = '10000' + elif 'ZPOOL' == pttype: + fsid = '10010' - # Detectar y mostrar el id. de tipo de partición. - DISK = ogDiskToDev(args[0]) - if DISK is None: - return - PTTYPE = ogGetPartitionTableType(args[0]) - if PTTYPE == "GPT": - ID = subprocess.getoutput(f"sgdisk -p {DISK} 2>/dev/null | awk -v p={args[1]} '{{if ($1==p) print $6;}}'") - if ID == "8300" and f"{args[0]} {args[1]}" == ogFindCache(): - ID = "CA00" - elif PTTYPE == "MSDOS": - ID = subprocess.getoutput(f"sfdisk --id {DISK} {args[1]} 2>/dev/null") - elif PTTYPE == "LVM": - ID = "10000" - elif PTTYPE == "ZPOOL": - ID = "10010" - - print(ID) - return + return fsid #/** @@ -765,45 +777,51 @@ def ogGetPartitionsNumber(*args): print(output) return -def ogGetPartitionTableType(*args): - # Variables locales - DISK = None - TYPE = None - # Si se solicita, mostrar ayuda. - if len(args) == 1 and args[0] == "help": - SystemLib.ogHelp('ogGetPartitionTableType', 'ogGetPartitionTableType int_ndisk', 'ogGetPartitionTableType 1 => MSDOS') - return +#/** +# ogGetPartitionTableType int_ndisk +#@brief Devuelve el tipo de tabla de particiones del disco (GPT o MSDOS) +#@param int_ndisk nº de orden del disco +#@return str_tabletype - Tipo de tabla de paritiones +#@warning Salidas de errores no determinada +#@note tabletype = { MSDOS, GPT } +#@note Requisitos: blkid, parted, vgs +#*/ ## +def ogGetPartitionTableType (disk): + DISK = ogDiskToDev (disk) + if DISK is None: return - # Error si no se recibe 1 parámetro. - if len(args) != 1: - SystemLib.ogRaiseError(OG_ERR_FORMAT) - return + m = os.stat (DISK, follow_symlinks=True).st_mode + if stat.S_ISBLK (m): + lines = subprocess.run (['parted', '--script', '--machine', DISK, 'print'], capture_output=True, text=True).stdout.splitlines() + for l in lines: + elems = l.split (':') + if DISK == elems[0]: + type = elems[5].upper() + break - # Sustituye n de disco por su dispositivo. - DISK = ogDiskToDev(args[0]) - if DISK is None: - return - - # Comprobar tabla de particiones. - if os.path.exists(DISK): - output = subprocess.getoutput(f"parted -sm {DISK} print 2>/dev/null | awk -F: -v D={DISK} '{{ if($1 == D) print toupper($6)}}'") - if not output: - output = subprocess.getoutput(f"parted -sm {DISK} print 2>/dev/null | awk -F: -v D={DISK} '{{ if($1 == D) print toupper($6)}}'") # Comprobar si es volumen lógico. - if os.path.isdir(DISK) and subprocess.run(["vgs", DISK], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL).returncode == 0: - output = "LVM" + if os.path.isdir (DISK) and 0 == subprocess.run (['vgs', DISK]).returncode: + type = 'LVM' + # Comprobar si es pool de ZFS. - if not output or output == "UNKNOWN": - blkid_output = subprocess.getoutput(f"blkid -s TYPE {DISK} | grep zfs") - if blkid_output: - output = "ZPOOL" + if not type or 'UNKNOWN' == type: + if 'zfs' in subprocess.run (['blkid', '-s', 'TYPE', DISK], capture_output=True, text=True).stdout: + type = 'ZPOOL' - # Mostrar salida. - if output: - print(output) - return + return type + +#/** +# ogGetPartitionType int_ndisk int_npartition +#@brief Devuelve el mnemonico con el tipo de partición. +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@return Mnemonico +#@note Mnemonico: valor devuelto por ogIdToType. +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#*/ ## def ogGetPartitionType(*args): # Variables locales ID = None @@ -1224,118 +1242,123 @@ def ogSetPartitionType(*args): ogSetPartitionId(args[0], args[1], ID) return -def ogTypeToId(TYPE, PTTYPE="MSDOS"): - # Asociar id. de partición para su mnemónico. - ID = "" - # Elección del tipo de partición. - if PTTYPE == "GPT": - if TYPE == "EMPTY": - ID = "0" - elif TYPE in ["WINDOWS", "NTFS", "EXFAT", "FAT32", "FAT16", "FAT12", "HNTFS", "HFAT32", "HFAT16", "HFAT12"]: - ID = "0700" - elif TYPE == "WIN-RESERV": - ID = "0C01" - elif TYPE == "CHROMEOS-KRN": - ID = "7F00" - elif TYPE == "CHROMEOS": - ID = "7F01" - elif TYPE == "CHROMEOS-RESERV": - ID = "7F02" - elif TYPE == "LINUX-SWAP": - ID = "8200" - elif TYPE in ["LINUX", "EXT2", "EXT3", "EXT4", "REISERFS", "REISER4", "XFS", "JFS"]: - ID = "8300" - elif TYPE == "LINUX-RESERV": - ID = "8301" - elif TYPE == "LINUX-LVM": - ID = "8E00" - elif TYPE == "FREEBSD-DISK": - ID = "A500" - elif TYPE == "FREEBSD-BOOT": - ID = "A501" - elif TYPE == "FREEBSD-SWAP": - ID = "A502" - elif TYPE == "FREEBSD": - ID = "A503" - elif TYPE == "HFS-BOOT": - ID = "AB00" - elif TYPE in ["HFS", "HFS+"]: - ID = "AF00" - elif TYPE == "HFS-RAID": - ID = "AF01" - elif TYPE == "SOLARIS-BOOT": - ID = "BE00" - elif TYPE == "SOLARIS": - ID = "BF00" - elif TYPE == "SOLARIS-SWAP": - ID = "BF02" - elif TYPE == "SOLARIS-DISK": - ID = "BF03" - elif TYPE == "CACHE": - ID = "CA00" - elif TYPE == "EFI": - ID = "EF00" - elif TYPE == "LINUX-RAID": - ID = "FD00" - elif PTTYPE == "MSDOS": - if TYPE == "EMPTY": - ID = "0" - elif TYPE == "FAT12": - ID = "1" - elif TYPE == "EXTENDED": - ID = "5" - elif TYPE == "FAT16": - ID = "6" - elif TYPE in ["WINDOWS", "NTFS", "EXFAT"]: - ID = "7" - elif TYPE == "FAT32": - ID = "b" - elif TYPE == "HFAT12": - ID = "11" - elif TYPE == "HFAT16": - ID = "16" - elif TYPE == "HNTFS": - ID = "17" - elif TYPE == "HFAT32": - ID = "1b" - elif TYPE == "LINUX-SWAP": - ID = "82" - elif TYPE in ["LINUX", "EXT2", "EXT3", "EXT4", "REISERFS", "REISER4", "XFS", "JFS"]: - ID = "83" - elif TYPE == "LINUX-LVM": - ID = "8e" - elif TYPE == "FREEBSD": - ID = "a5" - elif TYPE == "OPENBSD": - ID = "a6" - elif TYPE in ["HFS", "HFS+"]: - ID = "af" - elif TYPE == "SOLARIS-BOOT": - ID = "be" - elif TYPE == "SOLARIS": - ID = "bf" - elif TYPE == "CACHE": - ID = "ca" - elif TYPE == "DATA": - ID = "da" - elif TYPE == "GPT": - ID = "ee" - elif TYPE == "EFI": - ID = "ef" - elif TYPE == "VMFS": - ID = "fb" - elif TYPE == "LINUX-RAID": - ID = "fd" - elif PTTYPE == "LVM": - if TYPE == "LVM-LV": - ID = "10000" - elif PTTYPE == "ZVOL": - if TYPE == "ZFS-VOL": - ID = "10010" +#/** +# ogTypeToId str_parttype [str_tabletype] +#@brief Devuelve el identificador correspondiente a un tipo de partición. +#@param str_parttype mnemónico de tipo de partición. +#@param str_tabletype mnemónico de tipo de tabla de particiones (MSDOS por defecto). +#@return int_idpart identificador de tipo de partición. +#@exception OG_ERR_FORMAT Formato incorrecto. +#@note tabletype = { MSDOS, GPT }, (MSDOS, por defecto) +#*/ ## +#ogTypeToId ('LINUX') => "83" +#ogTypeToId ('LINUX', 'MSDOS') => "83" +def ogTypeToId (type, pttype='MSDOS'): + data = { + 'GPT': { + 'EMPTY': '0', + 'WINDOWS': '0700', + 'NTFS': '0700', + 'EXFAT': '0700', + 'FAT32': '0700', + 'FAT16': '0700', + 'FAT12': '0700', + 'HNTFS': '0700', + 'HFAT32': '0700', + 'HFAT16': '0700', + 'HFAT12': '0700', + 'WIN-RESERV': '0C01', + 'CHROMEOS-KRN': '7F00', + 'CHROMEOS': '7F01', + 'CHROMEOS-RESERV': '7F02', + 'LINUX-SWAP': '8200', + 'LINUX': '8300', + 'EXT2': '8300', + 'EXT3': '8300', + 'EXT4': '8300', + 'REISERFS': '8300', + 'REISER4': '8300', + 'XFS': '8300', + 'JFS': '8300', + 'LINUX-RESERV': '8301', + 'LINUX-LVM': '8E00', + 'FREEBSD-DISK': 'A500', + 'FREEBSD-BOOT': 'A501', + 'FREEBSD-SWAP': 'A502', + 'FREEBSD': 'A503', + 'HFS-BOOT': 'AB00', + 'HFS': 'AF00', + 'HFS+': 'AF00', + 'HFSPLUS': 'AF00', + 'HFS-RAID': 'AF01', + 'SOLARIS-BOOT': 'BE00', + 'SOLARIS': 'BF00', + 'SOLARIS-SWAP': 'BF02', + 'SOLARIS-DISK': 'BF03', + 'CACHE': 'CA00', + 'EFI': 'EF00', + 'LINUX-RAID': 'FD00', + }, + 'MSDOS': { + 'EMPTY': '0', + 'FAT12': '1', + 'EXTENDED': '5', + 'FAT16': '6', + 'WINDOWS': '7', + 'NTFS': '7', + 'EXFAT': '7', + 'FAT32': 'b', + 'HFAT12': '11', + 'HFAT16': '16', + 'HNTFS': '17', + 'HFAT32': '1b', + 'LINUX-SWAP': '82', + 'LINUX': '83', + 'EXT2': '83', + 'EXT3': '83', + 'EXT4': '83', + 'REISERFS': '83', + 'REISER4': '83', + 'XFS': '83', + 'JFS': '83', + 'LINUX-LVM': '8e', + 'FREEBSD': 'a5', + 'OPENBSD': 'a6', + 'HFS': 'af', + 'HFS+': 'af', + 'SOLARIS-BOOT': 'be', + 'SOLARIS': 'bf', + 'CACHE': 'ca', + 'DATA': 'da', + 'GPT': 'ee', + 'EFI': 'ef', + 'VMFS': 'fb', + 'LINUX-RAID': 'fd', + }, + 'LVM': { + 'LVM-LV': '10000', + }, + 'ZVOL': { + 'ZFS-VOL': '10010', + }, + } - return ID + if pttype.upper() not in data: return None + if type.upper() not in data[pttype.upper()]: return None + return data[pttype.upper()][type.upper()] + +#/** +# ogUnhidePartition int_ndisk int_npartition +#@brief Hace visible una partición oculta. +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@return (nada) +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND disco o particion no detectado (no es un dispositivo). +#@exception OG_ERR_PARTITION tipo de partición no reconocido. +#*/ ## def ogUnhidePartition(*args): # Variables locales PART = None diff --git a/client/lib/engine/bin/InventoryLib.py b/client/lib/engine/bin/InventoryLib.py index 48a93ee..0a6aa5f 100755 --- a/client/lib/engine/bin/InventoryLib.py +++ b/client/lib/engine/bin/InventoryLib.py @@ -1,3 +1,12 @@ +#/** +#@file Inventory.lib +#@brief Librería o clase Inventory +#@class Inventory +#@brief Funciones para recogida de datos de inventario de hardware y software de los clientes. +#@version 1.1.0 +#@warning License: GNU GPLv3+ +#*/ + import platform import sys import os @@ -6,14 +15,21 @@ import tempfile import re import json import shutil +import glob +import plistlib +import ogGlobals import SystemLib import FileSystemLib -import ogGlobals import RegistryLib +import FileLib -MSG_HARDWAREINVENTORY = "Inventario de hardware de la máquina" +#/** +# ogGetArch +#@brief Devuelve el tipo de arquitectura del cliente. +#@return str_arch - Arquitectura (i386 para 32 bits, x86_64 para 64 bits). +#*/ def ogGetArch(): if len(sys.argv) > 1 and sys.argv[1] == "help": SystemLib.ogHelp(sys.argv[0], sys.argv[0], sys.argv[0] + " => x86_64") @@ -24,6 +40,15 @@ def ogGetArch(): else: print("i386") + +#/** +# ogGetOsType int_ndisk int_npartition +#@brief Devuelve el tipo del sistema operativo instalado. +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@return OSType - Tipo de sistema operativo. +#@see ogGetOsVersion +#*/ ## def ogGetOsType(disk, partition): try: os_version = ogGetOsVersion(disk, partition) @@ -35,6 +60,16 @@ def ogGetOsType(disk, partition): print(f"Error en ogGetOsType: {e}") return "Unknown" + +#/** +# ogGetOsUuid int_ndisk int_nfilesys +#@brief Devuelve el UUID del sistema operativo instalado en un sistema de archivos. +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden de la partición +#@return str_uuid - UUID del sistema operativo. +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o partición no corresponden con un dispositiv +#*/ ## def ogGetOsUuid(): # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": @@ -65,7 +100,12 @@ def ogGetOsUuid(): # Leer identificador en clave de registro. uuid = RegistryLib.ogGetRegistryValue(MNTDIR, "SOFTWARE", "\\Microsoft\\Cryptography\\MachineGuid") print(uuid) - + + +#/** +# ogGetSerialNumber +#@brief Obtiene el nº de serie del cliente. +#*/ ## def ogGetSerialNumber(): # Si se solicita, mostrar ayuda. if len(sys.argv) > 1 and sys.argv[1] == "help": @@ -82,6 +122,11 @@ def ogGetSerialNumber(): return 0 + +#/** +# ogIsEfiActive +#@brief Comprueba si el sistema tiene activo el arranque EFI. +#*/ ## def ogIsEfiActive(): return os.path.isdir("/sys/firmware/efi") @@ -97,7 +142,7 @@ def parse_lshw_output(): # Ejemplo de datos clave que podríamos extraer if "product" in lshw_data: parsed_output.append(f"product={lshw_data['product']}") - + if "vendor" in lshw_data: parsed_output.append(f"vendor={lshw_data['vendor']}") @@ -115,11 +160,20 @@ def parse_lshw_output(): # Devolver los datos combinados return "\n".join(parsed_output) - + except subprocess.CalledProcessError as e: print(f"Error al ejecutar lshw: {e}") return "Error al obtener información de hardware" + +#/** +# ogListHardwareInfo +#@brief Lista el inventario de hardware de la máquina cliente. +#@return TipoDispositivo:Modelo (por determinar) +#@warning Se ignoran los parámetros de entrada. +#@note TipoDispositivo = { bio, boa, bus, cha, cdr, cpu, dis, fir, mem, mod, mul, net, sto, usb, vga } +#@note Requisitos: dmidecode, lshw, awk +#*/ ## def ogListHardwareInfo(): # Ejecutar dmidecode y obtener tipo de chasis try: @@ -137,6 +191,17 @@ def ogListHardwareInfo(): # Combina y devuelve los resultados return f"{output}\n{firmware}\n{lshw_output}" + +#/** +# ogListSoftware int_ndisk int_npartition +#@brief Lista el inventario de software instalado en un sistema operativo. +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@return programa versión ... +#@warning Se ignoran los parámetros de entrada. +#@note Requisitos: ... +#@todo Detectar software en Linux +#*/ ## def ogListSoftware(disk, partition): if disk is None or partition is None: SystemLib.ogRaiseError(ogGlobals.OG_ERR_FORMAT) @@ -197,41 +262,215 @@ def ogListSoftware(disk, partition): return sorted(set(apps)) +## https://stackoverflow.com/questions/2522651/find-a-key-inside-a-deeply-nested-dictionary/2522706#2522706 +def _find_key_recursive(plist_dict, key_substr): + for k in plist_dict.keys(): + if key_substr in k: return plist_dict[k] + for k, v in plist_dict.items(): + if type(v) is dict: # Only recurse if we hit a dict value + value = _find_key_recursive(v, key_substr) + if value: + return value + return '' + +#/** +# ogGetOsVersion int_ndisk int_nfilesys +#@brief Devuelve la versión del sistema operativo instalado en un sistema de archivos. +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden de la partición +#@return OSType:OSVersion - tipo y versión del sistema operativo. +#@note OSType = { Android, BSD, GrubLoader, Hurd, Linux, MacOS, Solaris, Windows, WinLoader } +#@note Requisitos: awk, head, chroot +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o partición no corresponden con un dispositiv +#@exception OG_ERR_PARTITION Fallo al montar el sistema de archivos. +#*/ ## +#ogGetOsVersion ("1", "2") => "Linux:Ubuntu precise (12.04 LTS) 64 bits" def ogGetOsVersion(disk, part): - try: - mnt_dir = FileSystemLib.ogMount(disk, part) - - version = None - os_release = os.path.join(mnt_dir, "etc/os-release") - if os.path.isfile(os_release): - with open(os_release, "r") as f: + mntdir = FileSystemLib.ogMount (disk, part) + if not mntdir: + return None + + type = version = None + is64bit = '' + +# Buscar tipo de sistema operativo. +# Para GNU/Linux: leer descripción. + os_release = os.path.join(mntdir, "etc/os-release") + if os.path.isfile(os_release): + type = 'Linux' + with open(os_release, "r") as f: + for line in f: + if line.startswith("PRETTY_NAME"): + version = line.split("=", 1)[1].strip().strip('"') + break + + if not version: + lsb_release = os.path.join(mntdir, "etc/lsb-release") + if os.path.isfile(lsb_release): + type = 'Linux' + with open(lsb_release, "r") as f: for line in f: - if line.startswith("PRETTY_NAME"): + if line.startswith("DISTRIB_DESCRIPTION"): version = line.split("=", 1)[1].strip().strip('"') break - - if not version: - lsb_release = os.path.join(mnt_dir, "etc/lsb-release") - if os.path.isfile(lsb_release): - with open(lsb_release, "r") as f: - for line in f: - if line.startswith("DISTRIB_DESCRIPTION"): - version = line.split("=", 1)[1].strip().strip('"') - break - - if not version: - for distrib in ["redhat", "SuSE", "mandrake", "gentoo"]: - distrib_file = os.path.join(mnt_dir, f"etc/{distrib}-release") - if os.path.isfile(distrib_file): - with open(distrib_file, "r") as f: - version = f.readline().strip() - break - - is_64bit = os.path.exists(os.path.join(mnt_dir, "lib64")) - if is_64bit: - version = f"{version} 64 bits" - return f"Linux: {version}" if version else "Linux: Unknown" - except Exception as e: - print(f"Fail to get OS: {e}") - return None \ No newline at end of file + if not version: + for distrib in ["redhat", "SuSE", "mandrake", "gentoo"]: + distrib_file = os.path.join(mntdir, f"etc/{distrib}-release") + if os.path.isfile(distrib_file): + type = 'Linux' + with open(distrib_file, "r") as f: + version = f.readline().strip() + break + + if not version: + arch_release_file = os.path.join(mntdir, "etc/arch-release") + if os.path.isfile(arch_release_file): + type = 'Linux' + version = "Arch Linux" + + if not version: + slack_release_file = os.path.join(mntdir, "slackware-version") + if os.path.isfile(slack_release_file): + type = 'Linux' + with open (slack_release_file, 'r') as fd: + c = fd.read() + version = "Slackware {c}" + +# Si no se encuentra, intentar ejecutar "lsb_release". + if not version: + out = subprocess.run (['chroot', mntdir, 'lsb_release', '-d'], capture_output=True, text=True).stdout + m = re.search (':\t(.*)', out) + if m: + type = 'Linux' + version = m.group(1) +# Comprobar Linux de 64 bits. + if version and os.path.exists(os.path.join(mntdir, "lib64")): + is64bit = ogGlobals.lang.MSG_64BIT +# Para Android, leer fichero de propiedades. + if not version: + type = 'Android' + files = glob.glob (os.path.join (mntdir, 'android*/system/build.prop')) + if files and os.path.isfile (files[0]): + v = [] + with open (files[0], 'r') as f: + for line in f: + if 'product.brand' in line or 'build.version.release' in line: + v.append (line.split('=')[1].strip()) + version = ' '.join (v) + if os.path.exists(os.path.join(mntdir, "lib64")): + is64bit = ogGlobals.lang.MSG_64BIT +# Para GNU/Hurd, comprobar fichero de inicio (basado en os-prober). + if not version: + type = 'Hurd' + if os.path.exists(os.path.join(mntdir, "hurd/init")): + version = 'GNU/Hurd' +# Para Windows: leer la version del registro. + if not version: + type = 'Windows' + build = 0 + file = RegistryLib.ogGetHivePath (mntdir, 'SOFTWARE') + if file: + # Nuevo método más rápido para acceder al registro de Windows.. + i = '\n'.join ([ + f'load {file}', + r'cd \Microsoft\Windows NT\CurrentVersion', + 'lsval ProductName', + 'lsval DisplayVersion', + ]) + version = subprocess.run (['hivexsh'], input=i, capture_output=True, text=True).stdout +# Recoge el valor del número de compilación para ver si es Windows 10/11 + i = '\n'.join ([ + f'load {file}', + r'cd \Microsoft\Windows NT\CurrentVersion', + 'lsval CurrentBuildNumber', + ]) + build = subprocess.run (['hivexsh'], input=i, capture_output=True, text=True).stdout + + if subprocess.run (['reglookup', '-H', '-p', 'Microsoft/Windows/CurrentVersion/ProgramW6432Dir', file], capture_output=True, text=True).stdout: + is64bit = ogGlobals.lang.MSG_64BIT + + if not version: + # Compatibilidad con métrodo antiguo y más lento de acceder al registro. + version = RegistryLib.ogGetRegistryValue (mntdir, 'software', r'\Microsoft\Windows NT\CurrentVersion\ProductName') + if RegistryLib.ogGetRegistryValue (mntdir, 'software', r'\Microsoft\Windows\CurrentVersion\ProgramW6432Dir'): + is64bit = ogGlobals.lang.MSG_64BIT + # Si la compilación es mayor o igual a 22000 es Windows 11 + if int (build) >= 22000: + version = version.replace ('10', '11') +# Para cargador Windows: buscar versión en fichero BCD (basado en os-prober). + if not version: + type = 'WinLoader' + file = FileLib.ogGetPath (file=f'{mntdir}/boot/bcd') + if file: + for distrib in 'Windows Recovery', 'Windows Boot': + with open (file, 'rb') as fd: + contents = fd.read() + distrib_utf16_regex = re.sub (r'(.)', '\\1.', distrib) + distrib_utf16_regex = bytes (distrib_utf16_regex, 'ascii') + if re.search (distrib_utf16, contents): + version = f'{distrib} loader' +# Para macOS: detectar kernel y completar con fichero plist de información del sistema. + if not version: + type = 'MacOS' + # Kernel de Mac OS (no debe ser fichero de texto). + file = f'{mntdir}/mach_kernel' + out = subprocess.run (['file', '--brief', file], capture_output=True, text=True).stdout + if not 'text' in out: + # Obtener tipo de kernel. + if 'Mach-O' in out: version = 'macOS' + if 'Mach-O 64-bit' in out: is64bit = ogGlobals.lang.MSG_64BIT + # Datos de configuración de versión de Mac OS. + file = f'{mntdir}/System/Library/CoreServices/SystemVersion.plist' + if os.path.exists (file): + with open (file, 'rb') as fd: + contents = fd.read() + plist_dict = plistlib.loads (contents) + n = _find_key_recursive (plist_dict, 'ProductName') + v = _find_key_recursive (plist_dict, 'ProductVersion') + version = f'{n} {v}'.strip() + # Datos de recuperación de macOS. + if version and os.path.exists (f'{mntdir}/com.apple.recovery.boot'): + version += ' recovery' + +# Para FreeBSD: obtener datos del Kernel. +### TODO Revisar solución. + if not version: + type = 'BSD' + file = f'{mntdir}/boot/kernel/kernel' + if os.path.exists (file): + lines = subprocess.run (['strings', file], capture_output=True, text=True).stdout.splitlines() + release_search = list (filter (lambda x: re.search ('@.*RELEASE', x), lines)) + if release_search: + first, second, *rest = release_search[0].split() + first = first.replace ('@(#)', '') + version = f'{first} {second}' + out = subprocess.run (['file', '--brief', file], capture_output=True, text=True).stdout + if 'x86-64' in out: is64bit = ogGlobals.lang.MSG_64BIT +# Para Solaris: leer el fichero de versión. +### TODO Revisar solución. + if not version: + type = 'Solaris' + file = f'{mntdir}/etc/release' + if os.path.exists (file): + with open (file, 'r') as fd: + version = fd.readline().strip +# Para cargador GRUB, comprobar fichero de configuración. + if not version: + type = 'GrubLoader' + for file in f'{mntdir}/grub/menu.lst', f'{mntdir}/boot/grub/menu.lst': + if os.path.exists (file): + VERSION = 'GRUB Loader' + for entry in f'{mntdir}/grub/grub.cfg', f'{mntdir}/grub2/grub.cfg', f'{mntdir}/EFI/*/grub.cfg', f'{mntdir}/boot/grub/grub.cfg', f'{mntdir}/boot/grub2/grub.cfg', f'{mntdir}/boot/EFI/*/grub.cfg': + for file in glob.glob (entry): + if os.path.exists (file): + version = 'GRUB2 Loader' + + + + + +# Mostrar resultado y salir sin errores. + if version: return f"{type}: {version} {is64bit}" + return None diff --git a/client/lib/engine/bin/RegistryLib.py b/client/lib/engine/bin/RegistryLib.py index f520520..c4c7eab 100755 --- a/client/lib/engine/bin/RegistryLib.py +++ b/client/lib/engine/bin/RegistryLib.py @@ -1,17 +1,41 @@ +#/** +#@file Registry.lib +#@brief Librería o clase Registry +#@class Boot +#@brief Funciones para gestión del registro de Windows. +#@version 1.1.0 +#@warning License: GNU GPLv3+ +#*/ + import subprocess import os import re +import shutil import ogGlobals import SystemLib import FileLib -def chntpw(*args): - chntpw_path = subprocess.check_output(['which', 'drbl-chntpw']).decode().strip() - if not chntpw_path: - chntpw_path = subprocess.check_output(['which', 'chntpw']).decode().strip() - subprocess.run([chntpw_path, '-e'] + list(args), timeout=5) +# Función ficticia para lanzar chntpw con timeout de 5 s., evitando cuelgues del programa. +def chntpw (file, input): + exe = shutil.which ('drbl-chntpw') or shutil.which ('chntpw') + return subprocess.run ([exe, '-e', file], timeout=5, input=input, capture_output=True, text=True).stdout + + +#/** +# ogAddRegistryKey path_mountpoint str_hive str_keyname +#@brief Añade una nueva clave al registro de Windows. +#@param path_mountpoint directorio donde está montado el sistema Windows +#@param str_hive sección del registro +#@param str_keyname nombre de la clave +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Fichero de registro no encontrado. +#@note hive = { default, sam, security, software, system, components } +#@warning Requisitos: chntpw +#@warning El sistema de archivos de Windows debe estar montada previamente. +#*/ ## def ogAddRegistryKey(path_mountpoint, str_hive, str_key): # Variables locales. FILE = ogGetHivePath(path_mountpoint, str_hive) @@ -24,6 +48,22 @@ def ogAddRegistryKey(path_mountpoint, str_hive, str_key): chntpw(FILE, 'q') chntpw(FILE, 'y') + +#/** +# ogAddRegistryValue path_mountpoint str_hive str_valuename [str_valuetype] +#@brief Añade un nuevo valor al registro de Windows, indicando su tipo de datos. +#@param path_mountpoint directorio donde está montado el sistema Windows +#@param str_hive sección del registro +#@param str_valuename nombre del valor +#@param str_valuetype tipo de datos del valor (opcional) +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Fichero de registro no encontrado. +#@note hive = { DEFAULT, SAM, SECURITY, SOFTWARE, SYSTEM, COMPONENTS } +#@note valuetype = { STRING, BINARY, DWORD }, por defecto: STRING +#@warning Requisitos: chntpw +#@warning El sistema de archivos de Windows debe estar montada previamente. +#*/ ## def ogAddRegistryValue(path_mountpoint, str_hive, str_key, str_valuename, str_valuetype=''): # Variables locales. FILE = ogGetHivePath(path_mountpoint, str_hive) @@ -51,6 +91,21 @@ def ogAddRegistryValue(path_mountpoint, str_hive, str_key, str_valuename, str_va chntpw(FILE, 'q') chntpw(FILE, 'y') + +#/** +# ogDeleteRegistryKey path_mountpoint str_hive str_keyname +#@brief Elimina una clave del registro de Windows con todo su contenido. +#@param path_mountpoint directorio donde está montado el sistema Windows +#@param str_hive sección del registro +#@param str_keyname nombre de la clave +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Fichero de registro no encontrado. +#@note hive = { default, sam, security, software, system, components } +#@warning Requisitos: chntpw +#@warning El sistema de archivos de Windows debe estar montada previamente. +#@warning La clave debe estar vacía para poder ser borrada. +#*/ ## def ogDeleteRegistryKey(path_mountpoint, str_hive, str_key): # Variables locales. FILE = ogGetHivePath(path_mountpoint, str_hive) @@ -60,6 +115,20 @@ def ogDeleteRegistryKey(path_mountpoint, str_hive, str_key): # Delete the registry key. subprocess.run(['chntpw', FILE], input=f"cd {str_key.rsplit('\\', 1)[0]}\ndk {str_key.rsplit('\\', 1)[-1]}\nq\ny\n".encode(), timeout=5) + +#/** +# ogDeleteRegistryValue path_mountpoint str_hive str_valuename +#@brief Elimina un valor del registro de Windows. +#@param path_mountpoint directorio donde está montado el sistema Windows +#@param str_hive sección del registro +#@param str_valuename nombre del valor +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Fichero de registro no encontrado. +#@note hive = { default, sam, security, software, system, components } +#@warning Requisitos: chntpw +#@warning El sistema de archivos de Windows debe estar montada previamente. +#*/ ## def ogDeleteRegistryValue(path_mountpoint, str_hive, str_valuename): # Variables locales. FILE = ogGetHivePath(path_mountpoint, str_hive) @@ -72,57 +141,85 @@ def ogDeleteRegistryValue(path_mountpoint, str_hive, str_valuename): chntpw(FILE, 'q') chntpw(FILE, 'y') -def ogGetHivePath(path_mountpoint, str_hive): - # Variables locales. - FILE = None +#/** +# ogGetHivePath path_mountpoint [str_hive|str_user] +#@brief Función básica que devuelve el camino del fichero con una sección del registro. +#@param path_mountpoint directorio donde está montado el sistema Windows +#@param str_hive sección del registro +#@return str_path - camino del fichero de registro +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Fichero de registro no encontrado. +#@note hive = { DEFAULT, SAM, SECURITY, SOFTWARE, SYSTEM, COMPONENTS, NombreDeUsuario } +#@warning El sistema de archivos de Windows debe estar montada previamente. +#*/ ## +#ogGetHivePath ('/mnt/sda1', 'SOFTWARE') => /mnt/sda1/WINDOWS/System32/config/SOFTWARE +#ogGetHivePath ('/mnt/sda1', 'user1') => /mnt/sda1/Users/user1/NTUSER.DAT +def ogGetHivePath(path_mountpoint, str_hive): # Camino del fichero de registro de usuario o de sistema (de menor a mayor prioridad). - FILE = FileLib.ogGetPath(f"/{path_mountpoint}/Windows/System32/config/{str_hive}") - if not FILE: - FILE = FileLib.ogGetPath(f"/{path_mountpoint}/Users/{str_hive}/NTUSER.DAT") - if not FILE: - FILE = FileLib.ogGetPath(f"/{path_mountpoint}/winnt/system32/config/{str_hive}") - if not FILE: - FILE = FileLib.ogGetPath(f"/{path_mountpoint}/Documents and Settings/{str_hive}/NTUSER.DAT") + FILE = FileLib.ogGetPath(file=f"/{path_mountpoint}/Windows/System32/config/{str_hive}") + if not FILE: FILE = FileLib.ogGetPath(file=f"/{path_mountpoint}/Users/{str_hive}/NTUSER.DAT") + if not FILE: FILE = FileLib.ogGetPath(file=f"/{path_mountpoint}/winnt/system32/config/{str_hive}") + if not FILE: FILE = FileLib.ogGetPath(file=f"/{path_mountpoint}/Documents and Settings/{str_hive}/NTUSER.DAT") if FILE and os.path.isfile(FILE): return FILE else: SystemLib.ogRaiseError( - "session", + [], ogGlobals.OG_ERR_NOTFOUND, f"{path_mountpoint} {str_hive}" ) return None - -def ogGetRegistryValue(path_mountpoint, str_hive, str_valuename): - # Variables locales. - FILE = ogGetHivePath(path_mountpoint, str_hive) - if not FILE: - return - # Devolver el dato del valor de registro. - chntpw_cmd = f''' - chntpw "{FILE}" << EOT 2> /dev/null | awk '/> Value/ {{ - if (index($0, "REG_BINARY") > 0) {{ - data="" - }} else {{ - getline - data=$0 - }} - }} - /^:[0-9A-F]+ / {{ - data=data""substr($0, 9, 48) - }} - END {{ - print data - }}' - cd {str_valuename.rsplit('\\', 1)[0]} - cat {str_valuename.rsplit('\\', 1)[-1]} - q - EOT - ''' - subprocess.run(chntpw_cmd, shell=True, timeout=5) - + +#/** +# ogGetRegistryValue path_mountpoint str_hive str_valuename +#@brief Devuelve el dato de un valor del registro de Windows. +#@param path_mountpoint directorio donde está montado el sistema Windows +#@param str_hive sección del registro +#@param str_valuename nombre del valor +#@return str_valuedata - datos del valor. +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Fichero de registro no encontrado. +#@note hive = { default, sam, security, software, system, components } +#@warning Requisitos: chntpw, awk +#@warning El sistema de archivos de Windows debe estar montado previamente. +#*/ ## +def ogGetRegistryValue(path_mountpoint, str_hive, str_valuename): + FILE = ogGetHivePath(path_mountpoint, str_hive) + if not FILE: return + + elems = str_valuename.split ('\\') + dirname = '\\'.join (elems[0:-1]) + basename = elems[-1] + + input = '\n'.join ([ + f'cd {dirname}', + f'cat {basename}', + 'q', + ]) + chntpw_out = chntpw (file, input) + lines = chntpw_out.splitlines() + if 2 != len (lines): + return None + if 'REG_BINARY' in lines[0]: + offset, content = lines[1].split (maxsplit=1) + return content + + +#/** +# ogListRegistryKeys path_mountpoint str_hive str_key +#@brief Lista los nombres de subclaves de una determinada clave del registro de Windows. +#@param path_mountpoint directorio donde está montado el sistema Windows +#@param str_hive sección del registro +#@param str_key clave de registro +#@return str_subkey ... - lista de subclaves +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Fichero de registro no encontrado. +#@note hive = { default, sam, security, software, system, components } +#@warning Requisitos: chntpw, awk +#@warning El sistema de archivos de Windows debe estar montado previamente. +#*/ ## def ogListRegistryKeys(path_mountpoint, str_hive, str_key): # Variables locales. FILE = ogGetHivePath(path_mountpoint, str_hive) @@ -138,6 +235,20 @@ def ogListRegistryKeys(path_mountpoint, str_hive, str_key): ''' subprocess.run(chntpw_cmd, shell=True, timeout=5) + +#/** +# ogListRegistryValues path_mountpoint str_hive str_key +#@brief Lista los nombres de valores de una determinada clave del registro de Windows. +#@param path_mountpoint directorio donde está montado el sistema Windows +#@param str_hive sección del registro +#@param str_key clave de registro +#@return str_value ... - lista de valores +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Fichero de registro no encontrado. +#@note hive = { default, sam, security, software, system, components } +#@warning Requisitos: chntpw, awk +#@warning El sistema de archivos de Windows debe estar montado previamente. +#*/ ## def ogListRegistryValues(path_mountpoint, str_hive, str_key): # Variables locales. FILE = ogGetHivePath(path_mountpoint, str_hive) @@ -153,6 +264,21 @@ def ogListRegistryValues(path_mountpoint, str_hive, str_key): ''' subprocess.run(chntpw_cmd, shell=True, timeout=5) + +#/** +# ogSetRegistryValue path_mountpoint str_hive str_valuename str_valuedata +#@brief Establece el dato asociado a un valor del registro de Windows. +#@param path_mountpoint directorio donde está montado el sistema Windows +#@param str_hive sección del registro +#@param str_valuename nombre del valor de registro +#@param str_valuedata dato del valor de registro +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Fichero de registro no encontrado. +#@note hive = { default, sam, security, software, system, components } +#@warning Requisitos: chntpw +#@warning El sistema de archivos de Windows debe estar montado previamente. +#*/ ## def ogSetRegistryValue(path_mountpoint, str_hive, str_valuename, str_data): # Variables locales. FILE = ogGetHivePath(path_mountpoint, str_hive) diff --git a/client/lib/engine/bin/UEFILib.py b/client/lib/engine/bin/UEFILib.py new file mode 100644 index 0000000..831a7a1 --- /dev/null +++ b/client/lib/engine/bin/UEFILib.py @@ -0,0 +1,232 @@ +import os.path +import shutil + +import ogGlobals +import SystemLib +import FileSystemLib +import DiskLib +import FileLib +import InventoryLib + +#!/bin/bash +# Libreria provisional para uso de UEFI +# Las funciones se incluirán las librerías ya existentes + +#/** +# ogNvramActiveEntry +#@brief Activa entrada de la NVRAM identificada por la etiqueta o el orden +#@param Num_order_entry | Label_entry Número de orden o la etiqueta de la entrada a borrar. +#@return (nada) +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTUEFI UEFI no activa. +#@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. +#*/ ## + +#/** +# ogNvramAddEntry +#@brief Crea nueva entrada en el gestor de arranque (NVRAM), opcionalmente la incluye al final del orden de arranque. +#@param Str_Label_entry Número de disco o etiqueta de la entrada a crear. +#@param Str_BootLoader Número de partición o cargador de arranque. +#@param Bool_Incluir_Arranque Incluir en el orden de arranque (por defecto FALSE) (opcional) +#@return (nada) +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTUEFI UEFI no activa. +#@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. +#*/ ## + + +#/** +# ogCopyEfiBootLoader int_ndisk str_repo path_image +#@brief Copia el cargador de arranque desde la partición EFI a la de sistema. +#@param int_ndisk nº de orden del disco +#@param int_part nº de partición +#@return (nada, por determinar) +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. +#@note Si existe el cargador en la partición de sistema no es válido +#*/ ## + + +#/** +# ogNvramDeleteEntry +#@brief Borra entrada de la NVRAM identificada por la etiqueta o el orden +#@param Num_order_entry | Label_entry Número de orden o la etiqueta de la entrada a borrar. +#@return (nada) +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTUEFI UEFI no activa. +#@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado (entrada en NVRAM). +#*/ ## + + +#/** +# ogNvramGetCurrent +#@brief Muestra la entrada del gestor de arranque (NVRAM) que ha iniciado el equipo. +#@return Entrada con la que se ha iniciado el equipo +#@exception OG_ERR_NOTUEFI UEFI no activa. +#*/ ## + + +# ogNvramGetNext +#@brief Muestra la entrada del gestor de arranque (NVRAM) que se utilizará en el próximo arranque. +#@return Entrada que se utilizará en el próximo arranque +#@exception OG_ERR_NOTUEFI UEFI no activa. +#*/ ## + + +# ogNvramGetOrder +#@brief Muestra el orden de las entradas del gestor de arranque (NVRAM) +#@return Orden de las entradas +#@exception OG_ERR_NOTUEFI UEFI no activa. +#*/ ## + + +#/** +# ogNvramGetTimeout +#@brief Muestra el tiempo de espera del gestor de arranque (NVRAM) +#@return Timeout de la NVRAM +#@exception OG_ERR_NOTUEFI UEFI no activa. +#*/ ## + + +#/** +# ogGrubUefiConf int_ndisk int_part str_dir_grub +#@brief Genera el fichero grub.cfg de la ESP +#@param int_ndisk nº de orden del disco +#@param int_part nº de partición +#@param str_dir_grub prefijo del directorio de grub en la partición de sistema. ej: /boot/grubPARTITION +#@return (nada, por determinar) +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. +#@TODO Confirmar si el fichero "$EFIDIR/EFI/$BOOTLABEL/grub.cfg" es necesario. +#*/ ## + + +#/** +# ogNvramInactiveEntry +#@brief Inactiva entrada de la NVRAM identificada por la etiqueta o el orden +#@param Num_order_entry | Label_entry Número de orden o la etiqueta de la entrada a borrar. +#@return (nada) +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. +#@exception OG_ERR_NOTUEFI UEFI no activa. +#*/ ## + + +#/** +# ogNvramList +#@brief Lista las entradas de la NVRAN (sólo equipos UEFI) +#@return Entradas de la NVRAM con el formato: orden etiqueta [* (si está activa) ] +#@exception OG_ERR_NOTUEFI UEFI no activa. +#*/ ## + + +#/** +# ogNvramPxeFirstEntry +#@brief Sitúa la entrada de la tarjeta de red en el primer lugar en la NVRAM. +#@return (nada) +#@exception OG_ERR_NOTUEFI UEFI no activa. +#*/ ## + + +#/** +# ogRestoreEfiBootLoader int_ndisk str_repo +#@brief Copia el cargador de arranque de la partición de sistema a la partición EFI. +#@param int_ndisk nº de orden del disco +#@param int_part nº de partición +#@return (nada, por determinar) +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado (partición de sistema o EFI). +#@exception OG_ERR_NOTOS sin sistema operativo. +#*/ ## +def ogRestoreEfiBootLoader (disk, par): + mntdir = FileSystemLib.ogMount (disk, par) + if not mntdir: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f'{disk} {par}') + return + + esp = DiskLib.ogGetEsp() + if not esp: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, 'EFI partition') + return + esp_disk, esp_par = esp.split() + efidir = FileSystemLib.ogMount (esp_disk, esp_par) + if not efidir: + FileSystemLib.ogFormat (esp_disk, esp_par, 'FAT32') + efidir = FileSystemLib.ogMount (esp_disk, esp_par) + if not efidir: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, 'ESP') + return + + osversion = InventoryLib.ogGetOsVersion (disk, par) + if 'Windows 1' in osversion: + bootlabel = f'Part-{disk:02d}-{par:02d}' + loader = FileLib.ogGetPath (f'{mntdir}/ogBoot/bootmgfw.efi') + if not loader: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTOS, f'{disk} {par} ({osversion}, EFI)') + return + efi_bl = f'{efidir}/EFI/{bootlabel}' + if os.path.exists (efi_bl): + shutil.rmtree (efi_bl) + os.makedirs (efi_bl, exist_ok=True) + shutil.copytree (os.path.dirname (loader), f'{efi_bl}/Boot', symlinks=True) + shutil.copy (loader, f'{efi_bl}/Boot/ogloader.efi') + if '' != FileLib.ogGetPath (f'{efidir}/EFI/Microsoft'): + os.rename (f'{efidir}/EFI/Microsoft', f'{efidir}/EFI/Microsoft.backup.og') + + return + + +#/** +# ogRestoreUuidPartitions +#@brief Restaura los uuid de las particiones y la tabla de particiones +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden del sistema de archivos +#@param REPO|CACHE repositorio +#@param str_imgname nombre de la imagen +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND No encontrado fichero de información de la imagen (con uuid) +#*/ ## + + +#/** +# ogNvramSetNext +#@brief Configura el próximo arranque con la entrada del gestor de arranque (NVRAM) identificada por la etiqueta o el orden. +#@param Num_order_entry | Label_entry Número de orden o la etiqueta de la entrada a borrar. +#@return (nada) +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTUEFI UEFI no activa. +#@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. +#*/ ## + +#/** +# ogNvramSetOrder +#@brief Configura el orden de las entradas de la NVRAM +#@param Orden de las entradas separadas por espacios +#@return (nada) +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTUEFI UEFI no activa. +#@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado (entrada NVRAM). +#*/ ## + + +#/** +# ogNvramSetTimeout +#@brief Configura el tiempo de espera de la NVRAM +#@param Orden de las entradas separadas por espacios +#@return (nada) + +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. +#*/ ## + + +#/** +# ogUuidChange int_ndisk str_repo +#@brief Reemplaza el UUID de un sistema de ficheros. +#@param int_ndisk nº de orden del disco +#@param int_part nº de partición +#@return (nada, por determinar) +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. +#*/ ##