diff --git a/client/etc/preinit/otherservices.sh b/client/etc/preinit/otherservices.sh index 2bd011b..bc5de62 100755 --- a/client/etc/preinit/otherservices.sh +++ b/client/etc/preinit/otherservices.sh @@ -8,7 +8,7 @@ #*/ # Montar efivar filesystem -isEfiActive && mount -t efivarfs none /sys/firmware/efi/efivars +ogIsEfiActive && mount -t efivarfs none /sys/firmware/efi/efivars # Lanzar servicios complementarios del cliente. echo "${MSG_OTHERSERVICES:-.}" diff --git a/client/lib/engine/bin/Boot.lib b/client/lib/engine/bin/Boot.lib new file mode 100755 index 0000000..04eaded --- /dev/null +++ b/client/lib/engine/bin/Boot.lib @@ -0,0 +1,2973 @@ +#!/bin/bash +#/** +#@file Boot.lib +#@brief Librería o clase Boot +#@class Boot +#@brief Funciones para arranque y post-configuración de sistemas de archivos. +#@version 1.1.0 +#@warning License: GNU GPLv3+ +#*/ + + +#/** +# ogBoot int_ndisk int_nfilesys [str_kernel str_initrd str_krnlparams] +#@brief Inicia el proceso de arranque de un sistema de archivos. +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden del sistema de archivos +#@param str_krnlparams parámetros de arranque del kernel (opcional) +#@return (activar el sistema de archivos). +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. +#@exception OG_ERR_NOTOS La partición no tiene instalado un sistema operativo. +#@note En Linux, si no se indican los parámetros de arranque se detectan de la opción por defecto del cargador GRUB. +#@note En Linux, debe arrancarse la partición del directorio \c /boot +#@version 0.1 - Integración para OpenGnSys. - EAC: HDboot; BootLinuxEX en Boot.lib +#@author Antonio J. Doblas Viso, Universidad de Malaga +#@date 2008-10-27 +#@version 0.9 - Adaptación para OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2009-09-11 +#@version 1.0.4 - Soporta modo de arranque Windows (parámetro de inicio "winboot"). +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2012-04-12 +#@version 1.0.6 - Selección a partir de tipo de sistema operativo (en vez de S.F.) y arrancar Linux con /boot separado. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2015-06-05 +#@version 1.1.0 - Nuevo parámetro opcional con opciones de arranque del Kernel. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2015-07-15 +#@version 1.1.1 - UEFI: Permite iniciar linux recien instalados (ticket #802 #890) +#@author Irina Gomez, ETSII Universidad de Sevilla +#@date 2019-03-13 +#*/ ## +function ogBoot () +{ +# Variables locales. +local PART TYPE MNTDIR PARAMS KERNEL INITRD APPEND FILE LOADER f +local EFIDISK EFIPART EFIDIR BOOTLABEL BOOTLOADER BOOTNO DIRGRUB b + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_nfilesys [str_kernel str_initrd str_kernelparams]" \ + "$FUNCNAME 1 1" "$FUNCNAME 1 2 \"/boot/vmlinuz /boot/initrd.img root=/dev/sda2 ro\"" + return +fi +# Error si no se reciben 2 o 3 parámetros. +[ $# == 2 ] || [ $# == 3 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +# Detectar tipo de sistema de archivos y montarlo. +PART=$(ogDiskToDev $1 $2) || return $? +TYPE=$(ogGetOsType $1 $2) || return $? +# Error si no puede montar sistema de archivos. +MNTDIR=$(ogMount $1 $2) || return $? + +case "$TYPE" in + Linux|Android) + # Si no se indican, obtiene los parámetros de arranque para Linux. + PARAMS="${3:-$(ogLinuxBootParameters $1 $2 2>/dev/null)}" + # Si no existe y el UEFI buscar en particion ESP + [ -z "$PARAMS" ] && ogIsEfiActive && PARAMS="$(ogLinuxBootParameters $(ogGetEsp))" + # Si no existe, buscar sistema de archivo /boot en /etc/fstab. + if [ -z "$PARAMS" -a -e $MNTDIR/etc/fstab ]; then + # Localizar S.F. /boot en /etc/fstab del S.F. actual. + PART=$(ogDevToDisk $(awk '$1!="#" && $2=="/boot" {print $1}' $MNTDIR/etc/fstab)) + # Montar S.F. de /boot. + MNTDIR=$(ogMount $PART) || return $? + # Buscar los datos de arranque. + PARAMS=$(ogLinuxBootParameters $PART) || exit $? + fi + read -e KERNEL INITRD APPEND <<<"$PARAMS" + # Si no hay kernel, no hay sistema operativo. + [ -n "$KERNEL" -a -e "$MNTDIR/$KERNEL" ] || ogRaiseError $OG_ERR_NOTOS "$1 $2 ($TYPE)" || return $? + # Arrancar de partición distinta a la original. + [ -e "$MNTDIR/etc" ] && APPEND=$(echo $APPEND | awk -v P="$PART " '{sub (/root=[-+=_/a-zA-Z0-9]* /,"root="P);print}') + # Comprobar tipo de sistema. + if ogIsEfiActive; then + # Comprobar si el Kernel está firmado. + if ! file -k "$MNTDIR/$KERNEL" | grep -q "EFI app"; then + ogRaiseError $OG_ERR_NOTOS "$1 $2 ($TYPE, EFI)" + return $? + fi + + BOOTLABEL=$(printf "Part-%02d-%02d" $1 $2) + BOOTLOADER="shimx64.efi" + # Obtener parcición EFI. + read -e EFIDISK EFIPART <<<"$(ogGetEsp)" + # TODO: Comprobamos que existe la BOOTLABEL, si no buscamos por sistema operativo + if [ "$(ogGetPath $EFIDISK $EFIPART EFI/$BOOTLABEL)" == "" ]; then + OSVERSION="$(ogGetOsVersion $1 $2)" + case $OSVERSION in + *SUSE*) + BOOTLABEL="opensuse" + ;; + *Fedora*) + BOOTLABEL="fedora" + ;; + *Ubuntu*) + BOOTLABEL="ubuntu" + ;; + *) + ogRaiseError $OG_ERR_NOTFOUND "$EFIDISK $EFIPART Boot loader"; return $? + ;; + esac + fi + + # Crear orden de arranque (con unos valores por defecto). + ogNvramAddEntry $BOOTLABEL "/EFI/$BOOTLABEL/Boot/$BOOTLOADER" + # Marcar próximo arranque y reiniciar. + ogNvramSetNext "$BOOTLABEL" + reboot + else + # Arranque BIOS: configurar kernel Linux con los parámetros leídos de su GRUB. + kexec -l "${MNTDIR}${KERNEL}" --append="$APPEND" --initrd="${MNTDIR}${INITRD}" + kexec -e & + fi + ;; + Windows) + # Comprobar tipo de sistema. + if ogIsEfiActive; then + BOOTLABEL=$(printf "Part-%02d-%02d" $1 $2) + # Obtener parcición EFI. + read -e EFIDISK EFIPART <<<"$(ogGetEsp)" + [ -n "$EFIPART" ] || ogRaiseError $OG_ERR_PARTITION "ESP" || return $? + EFIDIR=$(ogMount $EFIDISK $EFIPART) || exit $? + # Comprobar cargador (si no existe buscar por defecto en ESP). + LOADER=$(ogGetPath $EFIDIR/EFI/$BOOTLABEL/Boot/bootmgfw.efi) + [ -z "$LOADER" ] && BOOTLABEL=Microsoft && LOADER=$(ogGetPath $EFIDIR/EFI/Microsoft/Boot/bootmgfw.efi) + [ -n "$LOADER" ] || ogRaiseError $OG_ERR_NOTOS "$1 $2 ($TYPE, EFI)" || return $? + + # Crear orden de arranque (con unos valores por defecto). + ogNvramAddEntry $BOOTLABEL "/EFI${LOADER#*EFI}" + # Marcar próximo arranque y reiniciar. + ogNvramSetNext "$BOOTLABEL" + reboot + else + # Arranque BIOS: comprueba si hay un cargador de Windows. + for f in io.sys ntldr bootmgr; do + FILE="$(ogGetPath $1 $2 $f 2>/dev/null)" + [ -n "$FILE" ] && LOADER="$f" + done + [ -n "$LOADER" ] || ogRaiseError $OG_ERR_NOTOS "$1 $2 ($TYPE)" || return $? + if [ "$winboot" == "kexec" ]; then + # Modo de arranque en caliente (con kexec). + cp $OGLIB/grub4dos/* $MNTDIR # */ (Comentario Doxygen) + kexec -l $MNTDIR/grub.exe --append=--config-file="root (hd$[$1-1],$[$2-1]); chainloader (hd$[$1-1],$[$2-1])/$LOADER; tpm --init" + kexec -e & + else + # Modo de arranque por reinicio (con reboot). + dd if=/dev/zero of=${MNTDIR}/ogboot.me bs=1024 count=3 + dd if=/dev/zero of=${MNTDIR}/ogboot.firstboot bs=1024 count=3 + dd if=/dev/zero of=${MNTDIR}/ogboot.secondboot bs=1024 count=3 + if [ -z "$(ogGetRegistryValue $MNTDIR SOFTWARE '\Microsoft\Windows\CurrentVersion\Run\ogcleannboot')" ]; then + ogAddRegistryValue $MNTDIR SOFTWARE '\Microsoft\Windows\CurrentVersion\Run\ogcleanboot' + ogSetRegistryValue $MNTDIR SOFTWARE '\Microsoft\Windows\CurrentVersion\Run\ogcleanboot' "cmd /c del c:\ogboot.*" + fi + # Activar la partición. + ogSetPartitionActive $1 $2 + reboot + fi + fi + ;; + MacOS) + # Modo de arranque por reinicio. + # Nota: el cliente tiene que tener configurado correctamente Grub. + touch ${MNTDIR}/boot.mac &>/dev/null + reboot + ;; + GrubLoader) + # Reiniciar. + #reboot + ;; + *) ogRaiseError $OG_ERR_NOTOS "$1 $2 ${TYPE:+($TYPE)}" + return $? + ;; +esac +} + + +#/** +# ogGetWindowsName int_ndisk int_nfilesys +#@brief Muestra el nombre del equipo en el registro de Windows. +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden del sistema de archivos +#@return str_name - nombre del equipo +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. +#@version 0.9 - Adaptación para OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2009-09-23 +#*/ ## +function ogGetWindowsName () +{ +# Variables locales. +local MNTDIR + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_npartition" \ + "$FUNCNAME 1 1 ==> PRACTICA-PC" + return +fi +# Error si no se reciben 2 parámetros. +[ $# == 2 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +# Montar el sistema de archivos. +MNTDIR=$(ogMount $1 $2) || return $? + +# Obtener dato del valor de registro. +ogGetRegistryValue $MNTDIR system '\ControlSet001\Control\ComputerName\ComputerName\ComputerName' +} + + +#/** +# ogLinuxBootParameters int_ndisk int_nfilesys +#@brief Muestra los parámetros de arranque de un sistema de archivos Linux. +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden del sistema de archivos +#@return str_kernel str_initrd str_parameters ... +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. +#@warning Función básica usada por \c ogBoot +#@version 0.9 - Primera adaptación para OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2009-09-11 +#@version 0.9.2 - Soporta partición /boot independiente. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2010-07-20 +#@version 1.0.5 - Mejoras en tratamiento de GRUB2. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2013-05-14 +#@version 1.0.6 - Detectar instalaciones sobre EFI. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2014-09-15 +#*/ ## +function ogLinuxBootParameters () +{ +# Variables locales. +local MNTDIR CONFDIR CONFFILE f + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_nfilesys" \ + "$FUNCNAME 1 2 ==> /vmlinuz-3.5.0-21-generic /initrd.img-3.5.0-21-generic root=/dev/sda2 ro splash" + return +fi +# Error si no se reciben 2 parámetros. +[ $# == 2 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +# Detectar id. de tipo de partición y codificar al mnemonico. +MNTDIR=$(ogMount $1 $2) || return $? + +# Fichero de configuración de GRUB. +CONFDIR=$MNTDIR # Sistema de archivos de arranque (/boot). +[ -d $MNTDIR/boot ] && CONFDIR=$MNTDIR/boot # Sist. archivos raíz con directorio boot. +for f in $MNTDIR/{,boot/}{{grubMBR,grubPARTITION}/boot/,}{grub{2,},{,efi/}EFI/*}/{menu.lst,grub.cfg}; do + [ -r $f ] && CONFFILE=$f +done +[ -n "$CONFFILE" ] || ogRaiseError $OG_ERR_NOTFOUND "grub.cfg" || return $? + +# Toma del fichero de configuracion los valores del kernel, initrd +# y parámetros de arranque usando las cláusulas por defecto +# ("default" en GRUB1, "set default" en GRUB2) +# y los formatea para que sean compatibles con \c kexec . */ +# /* (comentario Doxygen) +awk 'BEGIN {cont=-1;} + $1~/^default$/ {sub(/=/," "); def=$2;} + $1~/^set$/ && $2~/^default/ { gsub(/[="]/," "); def=$3; + if (def ~ /saved_entry/) def=0; + } + $1~/^(title|menuentry)$/ {cont++} + $1~/^set$/ && $2~/^root=.\(hd'$[1-1]',(msdos|gpt)'$2'\).$/ { if (def==0) def=cont; } + $1~/^(kernel|linux(16|efi)?)$/ { if (def==cont) { + kern=$2; + sub($1,""); sub($1,""); sub(/^[ \t]*/,""); app=$0 + } # /* (comentario Doxygen) + } + $1~/^initrd(16|efi)?$/ {if (def==cont) init=$2} + END {if (kern!="") printf("%s %s %s", kern,init,app)} + ' $CONFFILE +# */ (comentario Doxygen) +} + + +#/** +# ogSetWindowsName int_ndisk int_nfilesys str_name +#@brief Establece el nombre del equipo en el registro de Windows. +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden del sistema de archivos +#@param str_name nombre asignado +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. +#@exception OG_ERR_OUTOFLIMIT Nombre Netbios con más de 15 caracteres. +#@version 0.9 - Adaptación a OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2009-09-24 +#@version 1.0.5 - Establecer restricción de tamaño de nombre Netbios. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2013-03-20 +#*/ ## +function ogSetWindowsName () +{ +# Variables locales. +local PART MNTDIR NAME + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_filesys str_name" \ + "$FUNCNAME 1 1 PRACTICA-PC" + return +fi +# Error si no se reciben 3 parámetros. +[ $# == 3 ] || ogRaiseError $OG_ERR_FORMAT || return $? +# Error si el nombre supera los 15 caracteres. +[ ${#3} -le 15 ] || ogRaiseError $OG_ERR_OUTOFLIMIT "\"${3:0:15}...\"" || return $? + +# Montar el sistema de archivos. +MNTDIR=$(ogMount $1 $2) || return $? + +# Asignar nombre. +NAME="$3" + +# Modificar datos de los valores de registro. +ogSetRegistryValue $MNTDIR system '\ControlSet001\Control\ComputerName\ComputerName\ComputerName' "$NAME" 2>/dev/null +ogSetRegistryValue $MNTDIR system '\ControlSet001\Services\Tcpip\Parameters\Hostname' "$NAME" 2>/dev/null +ogSetRegistryValue $MNTDIR system '\ControlSet001\Services\Tcpip\Parameters\HostName' "$NAME" 2>/dev/null +ogSetRegistryValue $MNTDIR system '\ControlSet001\services\Tcpip\Parameters\Hostname' "$NAME" 2>/dev/null +ogSetRegistryValue $MNTDIR system '\ControlSet001\Services\Tcpip\Parameters\NV Hostname' "$NAME" 2>/dev/null +ogSetRegistryValue $MNTDIR system '\ControlSet001\Services\Tcpip\Parameters\NV HostName' "$NAME" 2>/dev/null +ogSetRegistryValue $MNTDIR system '\ControlSet001\services\Tcpip\Parameters\NV Hostname' "$NAME" 2>/dev/null +} + + +#/** +# ogSetWinlogonUser int_ndisk int_npartition str_username +#@brief Establece el nombre de usuario por defecto en la entrada de Windows. +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@param str_username nombre de usuario por defecto +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. +#@version 0.9.2 - Adaptación a OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2010-07-20 +#*/ ## +function ogSetWinlogonUser () +{ +# Variables locales. +local PART MNTDIR NAME + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_npartition str_username" \ + "$FUNCNAME 1 1 USUARIO" + return +fi +# Error si no se reciben 3 parámetros. +[ $# == 3 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +# Montar el sistema de archivos. +MNTDIR=$(ogMount $1 $2) || return $? + +# Asignar nombre. +NAME="$3" + +# Modificar datos en el registro. +ogSetRegistryValue $MNTDIR SOFTWARE '\Microsoft\Windows NT\CurrentVersion\Winlogon\DefaultUserName' "$3" +} + + +#/** +# ogBootMbrXP int_ndisk +#@brief Genera un nuevo Master Boot Record en el disco duro indicado, compatible con los SO tipo Windows +#@param int_ndisk nº de orden del disco +#@return salida del programa my-sys +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. +#@version 0.9 - Adaptación a OpenGnSys. +#@author Antonio J. Doblas Viso. Universidad de Málaga +#@date 2009-09-24 +#*/ ## + +function ogBootMbrXP () +{ +# Variables locales. +local DISK + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk " \ + "$FUNCNAME 1" + return +fi +# Error si no se recibe 1 parámetro. +[ $# == 1 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +DISK="$(ogDiskToDev $1)" || return $? +ms-sys -z -f $DISK +ms-sys -m -f $DISK +} + + +#/** +# ogBootMbrGeneric int_ndisk +#@brief Genera un nuevo Codigo de arranque en el MBR del disco indicado, compatible con los SO tipo Windows, Linux. +#@param int_ndisk nº de orden del disco +#@return salida del programa my-sys +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Tipo de partición desconocido o no se puede montar. +#@version 0.9 - Adaptación a OpenGnSys. +#@author Antonio J. Doblas Viso. Universidad de Málaga +#@date 2009-09-24 +#*/ ## + +function ogBootMbrGeneric () +{ +# Variables locales. +local DISK + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk " \ + "$FUNCNAME 1 " + return +fi +# Error si no se recibe 1 parámetro. +[ $# == 1 ] || return $(ogRaiseError $OG_ERR_FORMAT; echo $?) + +DISK="$(ogDiskToDev $1)" || return $? +ms-sys -z -f $DISK +ms-sys -s -f $DISK + +# Firma necesaria para Windows equipos UEFI +SIGNATURE=0x$(cat /proc/sys/kernel/random/uuid | cut -d '-' -f1) +ms-sys -S $SIGNATURE $DISK +} + + + + +#/** +# ogFixBootSector int_ndisk int_parition +#@brief Corrige el boot sector de una particion activa para MS windows/dos -fat-ntfs +#@param int_ndisk nº de orden del disco +#@param int_partition nº de particion +#@return +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. +#@version 0.9 - Adaptación a OpenGnSys. +#@author Antonio J. Doblas Viso. Universidad de Málaga +#@date 2009-09-24 +#*/ ## + +function ogFixBootSector () +{ +# Variables locales. +local PARTYPE DISK PART FILE + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_partition " \ + "$FUNCNAME 1 1 " + return +fi + +# Error si no se reciben 2 parámetros. +[ $# == 2 ] || return $(ogRaiseError $OG_ERR_FORMAT; echo $?) + +#TODO, solo si la particion existe +#TODO, solo si es ntfs o fat +PARTYPE=$(ogGetPartitionId $1 $2) +case "$PARTYPE" in + 1|4|6|7|b|c|e|f|17|700|EF00) + ;; + *) + return $(ogRaiseError $OG_ERR_PARTITION; echo $?) + ;; +esac + +ogUnmount $1 $2 || return $(ogRaiseError $OG_ERR_PARTITION; echo $?) + +#Preparando instruccion +let DISK=$1-1 +PART=$2 +FILE=/tmp/temp$$ +cat > $FILE < ${MOUNT}/tmp.boot.ini; mv ${MOUNT}/tmp.boot.ini ${MOUNT}/boot.ini + return 0 +fi + +ogUnmount $1 $2 || return $(ogRaiseError $OG_ERR_PARTITION; echo $?) + + +#Preparando instruccion Windows Resume Application +cat > $FILE < $FILE < $FILE < $FILE < $FILE < $FILE < $FILE < $FILE <stico de memoria de Windows +EOF +timeout --foreground --signal=SIGKILL 5s spartlnx.run -cui -nm -w -f $FILE + +rm -f $FILE +} + + + +#/** +# ogWindowsRegisterPartition int_ndisk int_partiton str_volume int_disk int_partition +#@brief Registra una partición en windows con un determinado volumen. +#@param int_ndisk nº de orden del disco a registrar +#@param int_partition nº de particion a registrar +#@param str_volumen volumen a resgistar +#@param int_ndisk_windows nº de orden del disco donde esta windows +#@param int_partition_windows nº de particion donde esta windows +#@return +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. +#@version 0.9 - Adaptación a OpenGnSys. +#@author Antonio J. Doblas Viso. Universidad de Málaga +#@date 2009-09-24 +#*/ ## +function ogWindowsRegisterPartition () +{ +# Variables locales. +local PART DISK FILE REGISTREDDISK REGISTREDPART REGISTREDVOL VERSION SYSTEMROOT + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk_TO_registre int_partition_TO_registre str_NewVolume int_disk int_parition " \ + "$FUNCNAME 1 1 c: 1 1" + return +fi + +# Error si no se reciben 5 parámetros. +[ $# == 5 ] || return $(ogRaiseError $OG_ERR_FORMAT; echo $?) + +REGISTREDDISK=$1 +REGISTREDPART=$2 +REGISTREDVOL=$(echo $3 | cut -c1 | tr '[:lower:]' '[:upper:]') +DISK=$4 +PART=$5 +FILE=/tmp/temp$$ + +ogDiskToDev $REGISTREDDISK $REGISTREDPART || return $(ogRaiseError $OG_ERR_PARTITION "particion a registrar "; echo $?) +ogDiskToDev $DISK $PART || return $(ogRaiseError $OG_ERR_PARTITION "particion de windows"; echo $?) + +ogGetOsType $DISK $PART | grep "Windows" || return $(ogRaiseError $OG_ERR_NOTOS "no es windows"; echo $?) + +VERSION=$(ogGetOsVersion $DISK $PART) + +#Systemroot + +if ogGetPath $DISK $PART WINDOWS +then + SYSTEMROOT="Windows" +elif ogGetPath $DISK $PART WINNT +then + SYSTEMROOT="winnt" +else + return $(ogRaiseError $OG_ERR_NOTOS; echo $?) +fi + +ogUnmount $DISK $PART +let DISK=$DISK-1 +let REGISTREDDISK=$REGISTREDDISK-1 +#Preparando instruccion Windows Boot Manager +cat > $FILE <> /etc/default/grub + echo "GRUB_DISABLE_LINUX_UUID=\"true\"" >> /etc/default/grub + + + #Preparar configuración segunda etapa: crear ubicacion + mkdir -p ${SECONDSTAGE}${PREFIXSECONDSTAGE}/boot/grub/ + #Preparar configuración segunda etapa: crear cabecera del fichero (ignorar errores) + sed -i 's/^set -e/#set -e/' /etc/grub.d/00_header + # (ogLive 5.0) Si 'pkgdatadir' está vacía ponemos valor de otros ogLive + sed -i '/grub-mkconfig_lib/i\pkgdatadir=${pkgdatadir:-"${datarootdir}/grub"}' /etc/grub.d/00_header + /etc/grub.d/00_header > ${SECONDSTAGE}${PREFIXSECONDSTAGE}/boot/grub/grub.cfg 2>/dev/null + + #Preparar configuración segunda etapa: crear entrada del sistema operativo + grubSyntax "$KERNELPARAM" >> ${SECONDSTAGE}${PREFIXSECONDSTAGE}/boot/grub/grub.cfg + + # Renombramos la configuración de grub antigua + [ -f ${SECONDSTAGE}/boot/grub/grub.cfg ] && mv ${SECONDSTAGE}/boot/grub/grub.cfg ${SECONDSTAGE}/boot/grub/grub.cfg$BACKUPNAME + +fi + +#Instalar el grub +grub-install --force ${EFIOPTGRUB} --root-directory=${SECONDSTAGE}${PREFIXSECONDSTAGE} $FIRSTSTAGE +EVAL=$? + +# Movemos el grubx64.efi +if ogIsEfiActive; then + mv ${EFISECONDSTAGE}/EFI/$EFISUBDIR/EFI/BOOT/* ${EFISECONDSTAGE}/EFI/$EFISUBDIR/Boot + rm -rf ${EFISECONDSTAGE}/EFI/$EFISUBDIR/EFI + cp /usr/lib/shim/shimx64.efi.signed ${EFISECONDSTAGE}/EFI/$EFISUBDIR/Boot/shimx64.efi + # Nombre OpenGnsys para cargador + cp ${EFISECONDSTAGE}/EFI/$EFISUBDIR/Boot/{grubx64.efi,ogloader.efi} + + # Creamos entrada NVRAM y la ponemos en segundo lugar + ogNvramAddEntry grub /EFI/grub/Boot/shimx64.efi + GRUBENTRY=$(ogNvramList| awk '{if ($2=="grub") print $1}') + NEWORDER="$(ogNvramGetOrder|awk -v ENTRY=$GRUBENTRY '{gsub(",", " "); printf "%x %x %s\n", $1 , ENTRY , substr($0, index($0,$2))}')" + ogNvramSetOrder $NEWORDER +fi +return $EVAL + +} + + +#/** +# ogGrubInstallPartition int_disk_SECONDSTAGE int_partition_SECONDSTAGE bolean_Check_Os_installed_and_Configure_2ndStage +#@brief Instala y actualiza el gestor grub en el bootsector de la particion indicada +#@param int_disk_SecondStage +#@param int_part_SecondStage +#@param bolean_Check_Os_installed_and_Configure_2ndStage true | false[default] +#@param str "kernel param " +#@return +#@exception OG_ERR_FORMAT Formato incorrecto. +#@version 1.0.2 - Primeras pruebas. +#@author Antonio J. Doblas Viso. Universidad de Malaga. +#@date 2011-10-29 +#@version 1.0.3 - Soporte para linux de 32 y 64 bits +#@author Antonio J. Doblas Viso. Universidad de Malaga. +#@date 2012-03-13 +#@version 1.0.3 - Ficheros de configuracion independientes segun ubicación de la priemra etapa +#@author Antonio J. Doblas Viso. Universidad de Malaga. +#@date 2012-03-13 +#@version 1.1.1 - #802 Equipos EFI: Se crea el grub.cfg de la partición EFI +#@author Irina Gomez, ETSII Universidad de Sevilla +#@date 2019-01-08 +#@version 1.1.1 - #890 UEFI: el grub.cfg original es necesario para obtener los datos del kernel efi: se mueve al final. +#@author Irina Gomez, ETSII Universidad de Sevilla +#@date 2019-03-05 +#*/ ## + +function ogGrubInstallPartition () +{ + +# Variables locales. +local PART DISK VERSION FIRSTAGE SECONSTAGE CHECKOS KERNELPARAM BACKUPNAME +local EFIDISK EFIPART EFISECONDSTAGE EFISUBDIR EFIOPTGRUB EFIBOOTDIR + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndiskSecondStage int_partitionSecondStage bolean_Configure_2ndStage \"param param \" " \ + "$FUNCNAME 1 1 FALSE " \ + "$FUNCNAME 1 1 TRUE \"nomodeset irqpoll pci=noacpi quiet splash \" " + return +fi + +# Error si no se reciben 2 parámetros. +[ $# -ge 2 ] || return $(ogRaiseError $OG_ERR_FORMAT; echo $?) + +DISK=$1; PART=$2; +CHECKOS=${3:-"FALSE"} +KERNELPARAM=$4 +BACKUPNAME=".backup.og" + +#error si no es linux. +VERSION=$(ogGetOsVersion $DISK $PART) +echo $VERSION | grep "Linux" || return $(ogRaiseError $OG_ERR_NOTOS "no es linux"; echo $?) + +#Localizar primera etapa del grub +FIRSTSTAGE=$(ogDiskToDev $DISK $PART) + +#localizar disco segunda etapa del grub +SECONDSTAGE=$(ogMount $DISK $PART) + +#Localizar directorio segunda etapa del grub +PREFIXSECONDSTAGE="/boot/grubPARTITION" + +# Si es EFI instalamos el grub en la ESP +EFIOPTGRUB="" +# Desde el bootdir uefi y bios buscan el grub.cfg en subdirectorios distintos. +EFIBOOTDIR="" +if ogIsEfiActive; then + read EFIDISK EFIPART <<< $(ogGetEsp) + # Comprobamos que exista ESP y el directorio para ubuntu + EFISECONDSTAGE=$(ogMount $EFIDISK $EFIPART) + if [ $? -ne 0 ]; then + ogFormat $EFIDISK $EFIPART FAT32 + EFISECONDSTAGE=$(ogMount $EFIDISK $EFIPART) || ogRaiseError $OG_ERR_PARTITION "ESP" || return $? + fi + EFISUBDIR=$(printf "Part-%02d-%02d" $DISK $PART) + # Borramos la configuración anterior + [ -d ${EFISECONDSTAGE}/EFI/$EFISUBDIR ] && rm -rf ${EFISECONDSTAGE}/EFI/$EFISUBDIR + mkdir -p ${EFISECONDSTAGE}/EFI/$EFISUBDIR/Boot + EFIOPTGRUB=" --removable --no-nvram --uefi-secure-boot --target $(ogGetArch)-efi --efi-directory=${EFISECONDSTAGE}/EFI/$EFISUBDIR " + EFIBOOTDIR="/boot" +fi + +# Si Reconfigurar segunda etapa (grub.cfg) == FALSE +if [ "${CHECKOS^^}" == "FALSE" ] && [ -f ${SECONDSTAGE}/boot/grub/grub.cfg -o -f ${SECONDSTAGE}/boot/grub/grub.cfg$BACKUPNAME ] +then + # Si no se reconfigura se utiliza el grub.cfg orginal + [ -f ${SECONDSTAGE}/boot/grub/grub.cfg$BACKUPNAME ] && mv ${SECONDSTAGE}/boot/grub/grub.cfg$BACKUPNAME ${SECONDSTAGE}/boot/grub/grub.cfg + # Si no se reconfigure se borra los ficheros previos de configuración específicos de opengnsys. + [ -d ${SECONDSTAGE}${PREFIXSECONDSTAGE} ] && rm -fr ${SECONDSTAGE}${PREFIXSECONDSTAGE} + # Reactivamos el grub con el grub.cfg original. + PREFIXSECONDSTAGE="" +else + # SI Reconfigurar segunda etapa (grub.cfg) == TRUE + + if ogIsEfiActive; then + # UEFI: grubSintax necesita grub.cfg para detectar los kernels: si no existe recupero backup. + if ! [ -f ${SECONDSTAGE}/boot/grub/grub.cfg ]; then + [ -f ${SECONDSTAGE}/boot/grub/grub.cfg$BACKUPNAME ] && mv ${SECONDSTAGE}/boot/grub/grub.cfg$BACKUPNAME ${SECONDSTAGE}/boot/grub/grub.cfg + fi + else + #Evitar detectar modo recovery - mover grub.cfg original a grub.cfg.backup + mv ${SECONDSTAGE}/boot/grub/grub.cfg ${SECONDSTAGE}/boot/grub/grub.cfg$BACKUPNAME + fi + + #Configur la sintaxis grub para evitar menus de "recovery" en el OGLive + echo "GRUB_DISABLE_RECOVERY=\"true\"" >> /etc/default/grub + echo "GRUB_DISABLE_LINUX_UUID=\"true\"" >> /etc/default/grub + + #Preparar configuración segunda etapa: crear ubicacion + mkdir -p ${SECONDSTAGE}${PREFIXSECONDSTAGE}/boot/grub/ + #Preparar configuración segunda etapa: crear cabecera del fichero (ingnorar errores) + sed -i 's/^set -e/#set -e/' /etc/grub.d/00_header + # (ogLive 5.0) Si 'pkgdatadir' está vacía ponemos valor de otros ogLive + sed -i '/grub-mkconfig_lib/i\pkgdatadir=${pkgdatadir:-"${datarootdir}/grub"}' /etc/grub.d/00_header + /etc/grub.d/00_header > ${SECONDSTAGE}${PREFIXSECONDSTAGE}/boot/grub/grub.cfg 2>/dev/null + #Preparar configuración segunda etapa: crear entrada del sistema operativo + grubSyntax $DISK $PART "$KERNELPARAM" >> ${SECONDSTAGE}${PREFIXSECONDSTAGE}/boot/grub/grub.cfg + +fi +#Instalar el grub +grub-install --force ${EFIOPTGRUB} --root-directory=${SECONDSTAGE}${PREFIXSECONDSTAGE} $FIRSTSTAGE +EVAL=$? + +# Movemos el grubx64.efi +if ogIsEfiActive; then + mv ${EFISECONDSTAGE}/EFI/$EFISUBDIR/EFI/BOOT/* ${EFISECONDSTAGE}/EFI/$EFISUBDIR/Boot + rm -rf ${EFISECONDSTAGE}/EFI/$EFISUBDIR/EFI + cp /usr/lib/shim/shimx64.efi.signed ${EFISECONDSTAGE}/EFI/$EFISUBDIR/Boot/shimx64.efi + # Nombre OpenGnsys para cargador + cp ${EFISECONDSTAGE}/EFI/$EFISUBDIR/Boot/{grubx64.efi,ogloader.efi} +fi + +return $EVAL +} + + +#/** +# ogConfigureFstab int_ndisk int_nfilesys +#@brief Configura el fstab según particiones existentes +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden del sistema de archivos +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND No se encuentra el fichero fstab a procesar. +#@warning Puede haber un error si hay más de 1 partición swap. +#@version 1.0.5 - Primera versión para OpenGnSys. Solo configura la SWAP +#@author Antonio J. Doblas Viso. Universidad de Malaga. +#@date 2013-03-21 +#@version 1.0.6b - correccion. Si no hay partición fisica para la SWAP, eliminar entrada del fstab. +#@author Antonio J. Doblas Viso. Universidad de Malaga. +#@date 2016-11-03 +#@version 1.1.1 - Se configura la partición ESP (para sistemas EFI) (ticket #802) +#@author Irina Gómez, ETSII Universidad de Sevilla +#@date 2018-12-13 +#*/ ## +function ogConfigureFstab () +{ +# Variables locales. +local FSTAB DEFROOT PARTROOT DEFSWAP PARTSWAP +local EFIDISK EFIPART EFIDEV EFIOPT + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_nfilesys" \ + "$FUNCNAME 1 1" + return +fi +# Error si no se reciben 2 parámetros. +[ $# == 2 ] || ogRaiseError $OG_ERR_FORMAT || return $? +# Error si no se encuentra un fichero etc/fstab en el sistema de archivos. +FSTAB=$(ogGetPath $1 $2 /etc/fstab) 2>/dev/null +[ -n "$FSTAB" ] || ogRaiseError $OG_ERR_NOTFOUND "$1,$2,/etc/fstab" || return $? + +# Hacer copia de seguridad del fichero fstab original. +cp -a ${FSTAB} ${FSTAB}.backup +# Dispositivo del raíz en fichero fstab: 1er campo (si no tiene "#") con 2º campo = "/". +DEFROOT=$(awk '$1!~/#/ && $2=="/" {print $1}' ${FSTAB}) +PARTROOT=$(ogDiskToDev $1 $2) +# Configuración de swap (solo 1ª partición detectada). +PARTSWAP=$(blkid -t TYPE=swap | awk -F: 'NR==1 {print $1}') +if [ -n "$PARTSWAP" ] +then + # Dispositivo de swap en fichero fstab: 1er campo (si no tiene "#") con 3er campo = "swap". + DEFSWAP=$(awk '$1!~/#/ && $3=="swap" {print $1}' ${FSTAB}) + if [ -n "$DEFSWAP" ] + then + echo "Hay definicion de SWAP en el FSTAB $DEFSWAP -> modificamos fichero con nuevo valor $DEFSWAP->$PARTSWAP" # Mensaje temporal. + sed "s|$DEFSWAP|$PARTSWAP|g ; s|$DEFROOT|$PARTROOT|g" ${FSTAB}.backup > ${FSTAB} + else + echo "No hay definicion de SWAP y si hay partición SWAP -> moficamos fichero" # Mensaje temporal. + sed "s|$DEFROOT|$PARTROOT|g" ${FSTAB}.backup > ${FSTAB} + echo "$PARTSWAP none swap sw 0 0" >> ${FSTAB} + fi +else + echo "No hay partición SWAP -> configuramos FSTAB" # Mensaje temporal. + sed "/swap/d" ${FSTAB}.backup > ${FSTAB} +fi +# Si es un sistema EFI incluimos partición ESP (Si existe la modificamos) +if ogIsEfiActive; then + read EFIDISK EFIPART <<< $(ogGetEsp) + EFIDEV=$(ogDiskToDev $EFIDISK $EFIPART) + + # Opciones de la partición ESP: si no existe ponemos un valor por defecto + EFIOPT=$(awk '$1!~/#/ && $2=="/boot/efi" {print $3"\t"$4"\t"$5"\t"$6 }' ${FSTAB}) + [ "$EFIOPT" == "" ] && EFIOPT='vfat\tumask=0077\t0\t1' + + sed -i /"boot\/efi"/d ${FSTAB} + echo -e "$EFIDEV\t/boot/efi\t$EFIOPT" >> ${FSTAB} +fi +} + +#/** +# ogSetLinuxName int_ndisk int_nfilesys [str_name] +#@brief Establece el nombre del equipo en los ficheros hostname y hosts. +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden del sistema de archivos +#@param str_name nombre asignado (opcional) +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. +#@note Si no se indica nombre, se asigna un valor por defecto. +#@version 1.0.5 - Primera versión para OpenGnSys. +#@author Antonio J. Doblas Viso. Universidad de Malaga. +#@date 2013-03-21 +#*/ ## +function ogSetLinuxName () +{ +# Variables locales. +local MNTDIR ETC NAME + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_nfilesys [str_name]" \ + "$FUNCNAME 1 1" "$FUNCNAME 1 1 practica-pc" + return +fi +# Error si no se reciben 2 o 3 parámetros. +case $# in + 2) # Asignar nombre automático (por defecto, "pc"). + NAME="$(ogGetHostname)" + NAME=${NAME:-"pc"} ;; + 3) # Asignar nombre del 3er parámetro. + NAME="$3" ;; + *) # Formato de ejecución incorrecto. + ogRaiseError $OG_ERR_FORMAT + return $? +esac + +# Montar el sistema de archivos. +MNTDIR=$(ogMount $1 $2) || return $? + +ETC=$(ogGetPath $1 $2 /etc) + +if [ -d "$ETC" ]; then + #cambio de nombre en hostname + echo "$NAME" > $ETC/hostname + #Opcion A para cambio de nombre en hosts + #sed "/127.0.1.1/ c\127.0.1.1 \t $HOSTNAME" $ETC/hosts > /tmp/hosts && cp /tmp/hosts $ETC/ && rm /tmp/hosts + #Opcion B componer fichero de hosts + cat > $ETC/hosts <&2; echo $?) + + # Archivo de configuracion del grub + DIRMOUNT=$(ogMount $1 $2) + GRUBGFC="$DIRMOUNT/boot/grubMBR/boot/grub/grub.cfg" + + # Error si no existe archivo del grub + [ -r $GRUBGFC ] || return $(ogRaiseError log session $OG_ERR_NOTFOUND "$GRUBGFC" 1>&2; echo $?) + + # Si existe la entrada de opengnsys, se borra + grep -q "menuentry Opengnsys" $GRUBGFC && sed -ie "/menuentry Opengnsys/,+6d" $GRUBGFC + + # Tipo de tabla de particiones + PARTTABLETYPE=$(ogGetPartitionTableType $1 | tr [:upper:] [:lower:]) + + # Localizacion de la cache + read NUMDISK NUMPART <<< $(ogFindCache) + let NUMDISK=$NUMDISK-1 + # kernel y sus opciones. Pasamos a modo usuario + KERNEL="/boot/${oglivedir}/ogvmlinuz $(sed -e s/^.*linuz//g -e s/ogactiveadmin=[a-z]*//g /proc/cmdline)" + + # Configuracion offline si existe parametro + echo "$@" |grep offline &>/dev/null && STATUS=offline + echo "$@" |grep online &>/dev/null && STATUS=online + [ -z "$STATUS" ] || KERNEL="$(echo $KERNEL | sed s/"ogprotocol=[a-z]* "/"ogprotocol=local "/g ) ogstatus=$STATUS" + + # Numero de línea de la primera entrada del grub. + NUMLINE=$(grep -n -m 1 "^menuentry" $GRUBGFC|cut -d: -f1) + # Texto de la entrada de opengnsys +MENUENTRY="menuentry "OpenGnsys" --class opengnsys --class gnu --class os { \n \ +\tinsmod part_$PARTTABLETYPE \n \ +\tinsmod ext2 \n \ +\tset root='(hd${NUMDISK},$PARTTABLETYPE${NUMPART})' \n \ +\tlinux $KERNEL \n \ +\tinitrd /boot/${oglivedir}/oginitrd.img \n \ +}" + + + # Insertamos la entrada de opengnsys antes de la primera entrada existente. + sed -i "${NUMLINE}i\ $MENUENTRY" $GRUBGFC + + # Ponemos que la entrada por defecto sea la primera. + sed -i s/"set.*default.*$"/"set default=\"0\""/g $GRUBGFC + + # Si me dan valor para timeout lo cambio en el grub. + [ $TIMEOUT ] && sed -i s/timeout=.*$/timeout=$TIMEOUT/g $GRUBGFC +} + +#/** +# ogGrubHidePartitions num_disk num_part +#@brief ver ogBootLoaderHidePartitions +#@see ogBootLoaderHidePartitions +#*/ ## +function ogGrubHidePartitions () +{ + # Si se solicita, mostrar ayuda. + if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_npartition [ num_disk_partdata num_partdata ]" \ + "$FUNCNAME 1 2" \ + "$FUNCNAME 1 2 1 3" + return + fi + ogBootLoaderHidePartitions $@ + return $? +} + +#/** +# ogBurgHidePartitions num_disk num_part +#@brief ver ogBootLoaderHidePartitions +#@see ogBootLoaderHidePartitions +#*/ ## +function ogBurgHidePartitions () +{ + # Si se solicita, mostrar ayuda. + if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_npartition [ num_disk_partdata num_partdata ]" \ + "$FUNCNAME 1 2" \ + "$FUNCNAME 1 2 1 3" + return + fi + ogBootLoaderHidePartitions $@ + return $? +} + +#/** +# ogBootLoaderHidePartitions num_disk num_part +#@brief Configura el grub/burg para que oculte las particiones de windows que no se esten iniciando. +#@param 1 Numero de disco +#@param 2 Numero de particion +#@param 3 Numero de disco de la partición de datos (no ocultar) +#@param 4 Numero de particion de datos (no ocultar) +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception No existe archivo de configuracion del grub/burg. +#@version 1.1 Se comprueban las particiones de Windows con blkid (y no con grub.cfg) +#@author Irina Gomez, ETSII Universidad de Sevilla +#@date 2015-11-17 +#@version 1.1 Se generaliza la función para grub y burg +#@author Irina Gomez, ETSII Universidad de Sevilla +#@date 2017-10-20 +#@version 1.1.1 Se incluye comentarios en codigo para autodocuemtnacion con Doxygen +#@author Antonio J. Doblas Viso, EVLT Univesidad de Malaga. +#@date 2018-07-05 +#@version Se permite una partición de datos que no se ocultará. Soporta más de un disco. Compatible con grub.cfg creado por ogLive 5.0 +#@author Irina Gomez, ETSII Universidad de Sevilla +#@date 2019-08-26 +#*/ + +function ogBootLoaderHidePartitions () +{ + local FUNC DIRMOUNT GFCFILE PARTTABLETYPE WINENTRY WINPART ENTRY LINE PART PARTDATA TEXT PARTHIDDEN HIDDEN + + # Si se solicita, mostrar ayuda. + if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$MSG_SEE ogGrubHidePartitions ogBurgHidePartitions" + return + fi + + # Nombre de la función que llama a esta. + FUNC="${FUNCNAME[@]:1}" + FUNC="${FUNC%%\ *}" + + # Error si no se reciben 2 parámetros. + [ $# -lt 2 ] && return $(ogRaiseError session $OG_ERR_FORMAT "$MSG_FORMAT: $FUNCNAME num_disk num_part [ num_disk_partdata num_partdata ]"; echo $?) + # Si no existe $4 pongo un valor imposible para la partición de datos + [ $# -eq 4 ] && PARTDATA=$(ogDiskToDev $3 $4) || PARTDATA=0 + + # Archivo de configuracion del grub + DIRMOUNT=$(ogMount $1 $2) + # La función debe ser llamanda desde ogGrubHidePartitions or ogBurgHidePartitions. + case "$FUNC" in + ogGrubHidePartitions) + CFGFILE="$DIRMOUNT/boot/grubMBR/boot/grub/grub.cfg" + ;; + ogBurgHidePartitions) + CFGFILE="$DIRMOUNT/boot/burg/burg.cfg" + ;; + *) + ogRaiseError $OG_ERR_FORMAT "Use ogGrubHidePartitions or ogBurgHidePartitions." + return $? + ;; + esac + + # Error si no existe archivo del grub + [ -r $CFGFILE ] || return $(ogRaiseError log session $OG_ERR_NOTFOUND "$CFGFILE" 1>&2; echo $?) + + # Si solo hay una particion de Windows me salgo + [ $(fdisk -l $(ogDiskToDev) | grep 'NTFS' |wc -l) -eq 1 ] && return 0 + + # Elimino llamadas a parttool, se han incluido en otras ejecuciones de esta funcion. + sed -i '/parttool/d' $CFGFILE + + PARTTABLETYPE=$(ogGetPartitionTableType $1 | tr [:upper:] [:lower:]) + +# /* (comentario de bloque para Doxygen) + # Entradas de Windows: numero de linea y particion. De mayor a menor. + WINENTRY=$(awk '/menuentry.*Windows/ {gsub(/\)\"/, ""); gsub(/^.*dev/,""); print NR":/dev"$1} ' $CFGFILE | sed -e '1!G;h;$!d') + #*/ (comentario para bloque Doxygen) + # Particiones de Windows, pueden no estar en el grub. + WINPART=$(fdisk -l $(ogDiskToDev)|awk '/NTFS/ {print $1}'|sed '1!G;h;$!d') + + + # Modifico todas las entradas de Windows. + for ENTRY in $WINENTRY; do + LINE=${ENTRY%:*} + PART=${ENTRY#*:} + + # En cada entrada, oculto o muestro cada particion. + TEXT="" + for PARTHIDDEN in $WINPART; do + # Muestro la particion de la entrada actual y la de datos. + [ "$PARTHIDDEN" == "$PART" -o "$PARTHIDDEN" == "$PARTDATA" ] && HIDDEN="-" || HIDDEN="+" + read NUMDISK NUMPART <<< $(ogDevToDisk $PARTHIDDEN) + + TEXT="\tparttool (hd$((NUMDISK-1)),$PARTTABLETYPE$NUMPART) hidden$HIDDEN \n$TEXT" + done + + sed -i "${LINE}a\ $TEXT" $CFGFILE + done + + # Activamos la particion que se inicia en todas las entradas de windows. + sed -i "/chainloader/i\\\tparttool \$\{root\} boot+" $CFGFILE +} + +#/** +# ogGrubDeleteEntry num_disk num_part num_disk_delete num_part_delete +#@brief ver ogBootLoaderDeleteEntry +#@see ogBootLoaderDeleteEntry +#*/ +function ogGrubDeleteEntry () +{ + # Si se solicita, mostrar ayuda. + if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_npartition int_disk_delete int_npartition_delete" \ + "$FUNCNAME 1 6 2 1" + return + fi + ogBootLoaderDeleteEntry $@ + return $? +} + +#/** +# ogBurgDeleteEntry num_disk num_part num_disk_delete num_part_delete +#@brief ver ogBootLoaderDeleteEntry +#@see ogBootLoaderDeleteEntry +#*/ +function ogBurgDeleteEntry () +{ + # Si se solicita, mostrar ayuda. + if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_npartition int_disk_delete int_npartition_delete" \ + "$FUNCNAME 1 6 2 1" + return + fi + ogBootLoaderDeleteEntry $@ + return $? +} + +#/** +# ogRefindDeleteEntry num_disk_delete num_part_delete +#@brief ver ogBootLoaderDeleteEntry +#@see ogBootLoaderDeleteEntry +#*/ +function ogRefindDeleteEntry () +{ + local EFIDISK EFIPART + # Si se solicita, mostrar ayuda. + if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_disk_delete int_npartition_delete" \ + "$FUNCNAME 2 1" + return + fi + read EFIDISK EFIPART <<< $(ogGetEsp) + ogBootLoaderDeleteEntry $EFIDISK $EFIPART $@ + return $? +} + +#/** +# ogBootLoaderDeleteEntry num_disk num_part num_part_delete +#@brief Borra en el grub las entradas para el inicio en una particion. +#@param 1 Numero de disco donde esta el grub +#@param 2 Numero de particion donde esta el grub +#@param 3 Numero del disco del que borramos las entradas +#@param 4 Numero de la particion de la que borramos las entradas +#@note Tiene que ser llamada desde ogGrubDeleteEntry, ogBurgDeleteEntry o ogRefindDeleteEntry +#@return (nada) +#@exception OG_ERR_FORMAT Use ogGrubDeleteEntry or ogBurgDeleteEntry. +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND No existe archivo de configuracion del grub. +#@version 1.1 Se generaliza la función para grub y burg +#@author Irina Gomez, ETSII Universidad de Sevilla +#@date 2017-10-20 +#*/ ## + +function ogBootLoaderDeleteEntry () +{ + local FUNC DIRMOUNT CFGFILE LABEL MENUENTRY DELETEENTRY ENDENTRY ENTRY + + # Si se solicita, mostrar ayuda. + if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$MSG_SEE ogBurgDeleteEntry, ogGrubDeleteEntry or ogRefindDeleteEntry" + return + fi + + # Si el número de parámetros menos que 4 nos salimos + [ $# -lt 4 ] && return $(ogRaiseError session $OG_ERR_FORMAT "$MSG_FORMAT: $FUNCNAME num_disk num_part num_disk_delete num_part_delete"; echo $?) + + + # Nombre de la función que llama a esta. + FUNC="${FUNCNAME[@]:1}" + FUNC="${FUNC%%\ *}" + + # Archivo de configuracion del grub + DIRMOUNT=$(ogMount $1 $2) + # La función debe ser llamanda desde ogGrubDeleteEntry, ogBurgDeleteEntry or ogRefindDeleteEntry. + case "$FUNC" in + ogGrubDeleteEntry) + CFGFILE="$DIRMOUNT/boot/grubMBR/boot/grub/grub.cfg" + ;; + ogBurgDeleteEntry) + CFGFILE="$DIRMOUNT/boot/burg/burg.cfg" + ;; + ogRefindDeleteEntry) + CFGFILE="$DIRMOUNT/EFI/refind/refind.conf" + ;; + *) + ogRaiseError $OG_ERR_FORMAT "Use ogGrubDeleteEntry, ogBurgDeleteEntry or ogRefindDeleteEntry." + return $? + ;; + esac + + # Dispositivo + if [ "$(basename $CFGFILE)" == "refind.conf" ]; then + LABEL=$(printf "Part-%02d-%02d" $3 $4) + else + LABEL=$(ogDiskToDev $3 $4) + fi + + # Error si no existe archivo de configuración + [ -r $CFGFILE ] || ogRaiseError log session $OG_ERR_NOTFOUND "$CFGFILE" || return $? + + # Numero de linea de cada entrada. + MENUENTRY="$(grep -n -e menuentry $CFGFILE| cut -d: -f1 | sed '1!G;h;$!d' )" + + # Entradas que hay que borrar. + DELETEENTRY=$(grep -n menuentry.*$LABEL $CFGFILE| cut -d: -f1) + + # Si no hay entradas para borrar me salgo con aviso + [ "$DELETEENTRY" != "" ] || ogRaiseError log session $OG_ERR_NOTFOUND "Menuentry $LABEL" || return $? + + # Recorremos el fichero del final hacia el principio. + ENDENTRY="$(wc -l $CFGFILE|cut -d" " -f1)" + for ENTRY in $MENUENTRY; do + # Comprobamos si hay que borrar la entrada. + if ogCheckStringInGroup $ENTRY "$DELETEENTRY" ; then + let ENDENTRY=$ENDENTRY-1 + sed -i -e $ENTRY,${ENDENTRY}d $CFGFILE + fi + + # Guardamos el número de línea de la entrada, que sera el final de la siguiente. + ENDENTRY=$ENTRY + done +} + +#/** +# ogBurgInstallMbr int_disk_GRUBCFG int_partition_GRUBCFG +#@param bolean_Check_Os_installed_and_Configure_2ndStage true | false[default] +#@brief Instala y actualiza el gestor grub en el MBR del disco duro donde se encuentra el fichero grub.cfg. Admite sistemas Windows. +#@param int_disk_SecondStage +#@param int_part_SecondStage +#@param bolean_Check_Os_installed_and_Configure_2ndStage true | false[default] +#@return +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_PARTITION Partición no soportada +#@version 1.1.0 - Primeras pruebas instalando BURG. Codigo basado en el ogGrubInstallMBR. +#@author Antonio J. Doblas Viso. Universidad de Malaga. +#@date 2017-06-23 +#@version 1.1.0 - Redirección del proceso de copiado de archivos y de la instalacion del binario +#@author Antonio J. Doblas Viso. Universidad de Malaga. +#@date 2018-01-21 +#@version 1.1.0 - Refactorizar fichero de configuacion +#@author Antonio J. Doblas Viso. Universidad de Malaga. +#@date 2018-01-24 +#@version 1.1.1 - Se incluye comentarios en codigo para autodocuemtnacion con Doxygen +#@author Antonio J. Doblas Viso. Universidad de Malaga. +#@date 2018-07-05 +#*/ ## + +function ogBurgInstallMbr () +{ + +# Variables locales. +local BINARYAVAILABLE PART DISK DEVICE MOUNTDISK FIRSTAGE SECONSTAGE PREFIXSECONDSTAGE CHECKOS KERNELPARAM BACKUPNAME FILECFG + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndiskSecondStage int_partitionSecondStage bolean_Configure_2ndStage \"param param \" " \ + "$FUNCNAME 1 1 FALSE " \ + "$FUNCNAME 1 1 TRUE \"nomodeset irqpoll pci=noacpi quiet splash \" " + return +fi + +# Error si no se reciben 2 parametros. +[ $# -ge 2 ] || return $(ogRaiseError $OG_ERR_FORMAT; echo $?) + +#Error si no tenemos el binario burg +BINARYAVAILABLE=$(burg-install -v &>/dev/null && echo "YES" ||echo "NO") +if [ "$BINARYAVAILABLE" == NO ]; then + if [ -e $OGLIB/burg/burg.tgz ]; then + cd / ; tar xzvf $OGLIB/burg/burg.tgz --strip 1 &>/dev/null + else + return $(ogRaiseError $OG_ERR_NOTEXEC "Binary burg not found"; echo $?) + fi +fi + +DISK=$1; PART=$2; +CHECKOS=${3:-"FALSE"} +KERNELPARAM=$4 +BACKUPNAME=".backup.og" + +#Controlar disco no uefi +ogIsEfiActive && return $(ogRaiseError $OG_ERR_NOTBIOS " : grub4dos solo soporta PC con bios legacy"; echo $?) +#Controlar particionado tipo msdos +ogCheckStringInGroup $(ogGetPartitionTableType $DISK) "MSDOS" || return $(ogRaiseError $OG_ERR_NOMSDOS ": grub2dos requiere particionado tipo MSDOS"; echo $?) +#Controlar existencia de disco y particion +DEVICE=$(ogDiskToDev $DISK) || ogRaiseError $OG_ERR_NOTFOUND || return $? +MOUNTDISK=$(ogMount $DISK $PART) || ogRaiseError $OG_ERR_PARTITION "$MSG_ERROR " || return $? +#Controlar particion segunda etapa del burg +ogCheckStringInGroup $(ogGetFsType $DISK $PART) "CACHE EXT4 EXT3 EXT2" || return $(ogRaiseError $OG_ERR_PARTITION "burg.cfg soporta solo particiones linux"; echo $?) +#Controlar acceso de escritura a la particion segunda etapa del burg +ogIsReadonly $DISK $PART && return $(ogRaiseError $OG_ERR_NOTWRITE ": $DISK $PART" || echo $?) + +#Asigar la primera etapa del grub en el primer disco duro +FIRSTSTAGE=$(ogDiskToDev 1) +#Localizar disco segunda etapa del grub +SECONDSTAGE=$(ogMount $DISK $PART) + +#Preparar el directorio principal de la segunda etapa (y copia los binarios) +[ -d ${SECONDSTAGE}/boot/burg/ ] || mkdir -p ${SECONDSTAGE}/boot/burg/; cp -prv /boot/burg/* ${SECONDSTAGE}/boot/burg/ 2>&1>/dev/null; cp -prv $OGLIB/burg/themes ${SECONDSTAGE}/boot/burg/ 2>&1>/dev/null; #*/ ## (comentario Dogygen) #*/ ## (comentario Dogygen) +#Copiar el tema de opengnsys +mkdir -p ${SECONDSTAGE}/boot/burg/themes/OpenGnsys +cp -prv "$OGLIB/burg/themes" "${SECONDSTAGE}/boot/burg/" 2>&1>/dev/null + +# No configurar la segunda etapa (grub.cfg). Parámetro FALSE +if [ -f ${SECONDSTAGE}/boot/burg/burg.cfg -o -f ${SECONDSTAGE}/boot/burg/burg.cfg$BACKUPNAME ]; +then + if [ "$CHECKOS" == "false" -o "$CHECKOS" == "FALSE" ] + then + burg-install --force --root-directory=${SECONDSTAGE} $FIRSTSTAGE 2>&1>/dev/null + return $? + fi +fi + +# Configurrar la segunda etapa (burg.cfg) == tercer parámetro TRUE + +#llamar a updateBootCache para que aloje la primera fase del ogLive +updateBootCache + +#Configur la sintaxis grub para evitar menus de "recovery" en el OGLive +echo "GRUB_DISABLE_RECOVERY=\"true\"" >> /etc/default/grub +echo "GRUB_DISABLE_LINUX_UUID=\"true\"" >> /etc/default/grub + +#Preparar configuración segunda etapa: crear ubicacion +mkdir -p ${SECONDSTAGE}${PREFIXSECONDSTAGE}/boot/burg/ +#Preparar configuración segunda etapa: crear cabecera del fichero +FILECFG=${SECONDSTAGE}${PREFIXSECONDSTAGE}/boot/burg/burg.cfg +#/* ## (comentario Dogygen) +cat > "$FILECFG" << EOF + +set theme_name=OpenGnsys +set gfxmode=1024x768 + + +set locale_dir=(\$root)/boot/burg/locale + +set default=0 +set timeout=25 +set lang=es + + +insmod ext2 +insmod gettext + + + + +if [ -s \$prefix/burgenv ]; then + load_env +fi + + + +if [ \${prev_saved_entry} ]; then + set saved_entry=\${prev_saved_entry} + save_env saved_entry + set prev_saved_entry= + save_env prev_saved_entry + set boot_once=true +fi + +function savedefault { + if [ -z \${boot_once} ]; then + saved_entry=\${chosen} + save_env saved_entry + fi +} +function select_menu { + if menu_popup -t template_popup theme_menu ; then + free_config template_popup template_subitem menu class screen + load_config \${prefix}/themes/\${theme_name}/theme \${prefix}/themes/custom/theme_\${theme_name} + save_env theme_name + menu_refresh + fi +} + +function toggle_fold { + if test -z $theme_fold ; then + set theme_fold=1 + else + set theme_fold= + fi + save_env theme_fold + menu_refresh +} +function select_resolution { + if menu_popup -t template_popup resolution_menu ; then + menu_reload_mode + save_env gfxmode + fi +} + + +if test -f \${prefix}/themes/\${theme_name}/theme ; then + insmod coreui + menu_region.text + load_string '+theme_menu { -OpenGnsys { command="set theme_name=OpenGnsys" }}' + load_config \${prefix}/themes/conf.d/10_hotkey + load_config \${prefix}/themes/\${theme_name}/theme \${prefix}/themes/custom/theme_\${theme_name} + insmod vbe + insmod png + insmod jpeg + set gfxfont="Unifont Regular 16" + menu_region.gfx + vmenu resolution_menu + controller.ext +fi + + +EOF +#*/ ## (comentario Dogygen) + +#Preparar configuración segunda etapa: crear entrada del sistema operativo +grubSyntax "$KERNELPARAM" >> "$FILECFG" +#Instalar el burg +burg-install --force --root-directory=${SECONDSTAGE} $FIRSTSTAGE 2>&1>/dev/null +} + +#/** +# ogGrubDefaultEntry int_disk_GRUGCFG int_partition_GRUBCFG int_disk_default_entry int_npartition_default_entry +#@brief ver ogBootLoaderDefaultEntry +#@see ogBootLoaderDefaultEntry +#*/ ## +function ogGrubDefaultEntry () +{ + # Si se solicita, mostrar ayuda. + if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_npartition int_disk_default_entry int_npartition_default_entry" \ + "$FUNCNAME 1 6 1 1" + return + fi + ogBootLoaderDefaultEntry $@ + return $? +} + +#/** +# ogBurgDefaultEntry int_disk_BURGCFG int_partition_BURGCFG int_disk_default_entry int_npartition_default_entry +#@brief ver ogBootLoaderDefaultEntry +#@see ogBootLoaderDefaultEntry +#*/ ## +function ogBurgDefaultEntry () +{ + # Si se solicita, mostrar ayuda. + if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_npartition int_disk_default_entry int_npartition_default_entry" \ + "$FUNCNAME 1 6 1 1" + return + fi + ogBootLoaderDefaultEntry $@ + return $? +} + + +#/** +# ogRefindDefaultEntry int_disk_default_entry int_npartition_default_entry +#@brief ver ogBootLoaderDefaultEntry +#@see ogBootLoaderDefaultEntry +#*/ ## +function ogRefindDefaultEntry () +{ + local EFIDISK EFIPART + # Si se solicita, mostrar ayuda. + if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_disk_default_entry int_npartition_default_entry" \ + "$FUNCNAME 1 1" + return + fi + + read EFIDISK EFIPART <<< $(ogGetEsp) + ogBootLoaderDefaultEntry $EFIDISK $EFIPART $@ + return $? +} + +#/** +# ogBootLoaderDefaultEntry int_disk_CFG int_partition_CFG int_disk_default_entry int_npartition_default_entry +#@brief Configura la entrada por defecto de Burg +#@param int_disk_SecondStage +#@param int_part_SecondStage +#@param int_disk_default_entry +#@param int_part_default_entry +#@return +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_PARTITION Partición errónea o desconocida (ogMount). +#@exception OG_ERR_OUTOFLIMIT Param $3 no es entero. +#@exception OG_ERR_NOTFOUND Fichero de configuración no encontrado: burg.cfg. +#@version 1.1.0 - Define la entrada por defecto del Burg +#@author Irina Gomez, ETSII Universidad de Sevilla +#@date 2017-08-09 +#@version 1.1 Se generaliza la función para grub y burg +#@author Irina Gomez, ETSII Universidad de Sevilla +#@date 2018-01-04 +#*/ ## +function ogBootLoaderDefaultEntry () +{ + +# Variables locales. +local PART FUNC DIRMOUNT LABEL CFGFILE DEFAULTENTRY MENUENTRY MSG + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$MSG_SEE ogGrubDefaultEntry, ogBurgDefaultEntry or ogRefindDefaultEntry." + return +fi + +# Nombre de la función que llama a esta. +FUNC="${FUNCNAME[@]:1}" +FUNC="${FUNC%%\ *}" + +# Error si no se reciben 3 parametros. +[ $# -eq 4 ] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME int_ndiskSecondStage int_partitionSecondStage int_disk_default_entry int_partitions_default_entry" || return $? + +# Error si no puede montar sistema de archivos. +DIRMOUNT=$(ogMount $1 $2) || return $? + +# Comprobamos que exista fichero de configuración +# La función debe ser llamanda desde ogGrubDefaultEntry, ogBurgDefaultEntry or ogRefindDefaultEntry. +case "$FUNC" in + ogGrubDefaultEntry) + CFGFILE="$DIRMOUNT/boot/grubMBR/boot/grub/grub.cfg" + ;; + ogBurgDefaultEntry) + CFGFILE="$DIRMOUNT/boot/burg/burg.cfg" + ;; + ogRefindDefaultEntry) + CFGFILE="$DIRMOUNT/EFI/refind/refind.conf" + ;; + *) + ogRaiseError $OG_ERR_FORMAT "Use ogGrubDefaultEntry, ogBurgDefaultEntry or ogRefindDefaultEntry." + return $? + ;; +esac + +# Error si no existe archivo de configuración +[ -r $CFGFILE ] || ogRaiseError $OG_ERR_NOTFOUND "$CFGFILE" || return $? + +# Dispositivo +if [ "$(basename $CFGFILE)" == "refind.conf" ]; then + LABEL=$(printf "Part-%02d-%02d" $3 $4) +else + LABEL=$(ogDiskToDev $3 $4) +fi + +# Número de línea de la entrada por defecto en CFGFILE (primera de la partición). +DEFAULTENTRY=$(grep -n -m 1 menuentry.*$LABEL $CFGFILE| cut -d: -f1) + +# Si no hay entradas para borrar me salgo con aviso +[ "$DEFAULTENTRY" != "" ] || ogRaiseError session log $OG_ERR_NOTFOUND "No menuentry $LABEL" || return $? + +# Número de la de linea por defecto en el menú de usuario +MENUENTRY="$(grep -n -e menuentry $CFGFILE| cut -d: -f1 | grep -n $DEFAULTENTRY |cut -d: -f1)" + +if [ "$(basename $CFGFILE)" == "refind.conf" ]; then + sed -i /default_selection.*$/d $CFGFILE + sed -i "1 i\default_selection $MENUENTRY" $CFGFILE +else + # En grub y burg las líneas empiezan a contar desde cero + let MENUENTRY=$MENUENTRY-1 + sed --regexp-extended -i s/"set default=\"?[0-9]*\"?$"/"set default=\"$MENUENTRY\""/g $CFGFILE +fi +MSG="MSG_HELP_$FUNC" +echo "${!MSG%%\.}: $@" +} + +#/** +# ogGrubOgliveDefaultEntry num_disk num_part +#@brief ver ogBootLoaderOgliveDefaultEntry +#@see ogBootLoaderOgliveDefaultEntry +#*/ ## +function ogGrubOgliveDefaultEntry () +{ + # Si se solicita, mostrar ayuda. + if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndiskSecondStage int_partitionSecondStage" \ + "$FUNCNAME 1 6" + return + fi + ogBootLoaderOgliveDefaultEntry $@ + return $? +} + +#/** +# ogBurgOgliveDefaultEntry num_disk num_part +#@brief ver ogBootLoaderOgliveDefaultEntry +#@see ogBootLoaderOgliveDefaultEntry +#*/ ## +function ogBurgOgliveDefaultEntry () +{ + # Si se solicita, mostrar ayuda. + if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndiskSecondStage int_partitionSecondStage" \ + "$FUNCNAME 1 6" + return + fi + ogBootLoaderOgliveDefaultEntry $@ + return $? +} + + +#/** +# ogRefindOgliveDefaultEntry +#@brief ver ogBootLoaderOgliveDefaultEntry +#@see ogBootLoaderOgliveDefaultEntry +#*/ ## +function ogRefindOgliveDefaultEntry () +{ + local EFIDISK EFIPART + # Si se solicita, mostrar ayuda. + if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME" \ + "$FUNCNAME" + return + fi + + read EFIDISK EFIPART <<< $(ogGetEsp) + ogBootLoaderOgliveDefaultEntry $EFIDISK $EFIPART + return $? +} + + +#/** +# ogBootLoaderOgliveDefaultEntry +#@brief Configura la entrada de ogLive como la entrada por defecto de Burg. +#@param int_disk_SecondStage +#@param int_part_SecondStage +#@return +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_PARTITION Partición errónea o desconocida (ogMount). +#@exception OG_ERR_NOTFOUND Fichero de configuración no encontrado: burg.cfg. +#@exception OG_ERR_NOTFOUND Entrada de OgLive no encontrada en burg.cfg. +#@version 1.1.0 - Primeras pruebas con Burg +#@author Irina Gomez, ETSII Universidad de Sevilla +#@date 2017-08-09 +#@version 1.1 Se generaliza la función para grub y burg +#@author Irina Gomez, ETSII Universidad de Sevilla +#@date 2018-01-04 +#*/ ## +function ogBootLoaderOgliveDefaultEntry () +{ + +# Variables locales. +local FUNC PART CFGFILE NUMENTRY MSG + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$MSG_SEE ogGrubOgliveDefaultEntry, ogBurgOgliveDefaultEntry or ogRefindOgliveDefaultEntry" \ + return +fi + +# Nombre de la función que llama a esta. +FUNC="${FUNCNAME[@]:1}" +FUNC="${FUNC%%\ *}" + +# Error si no se reciben 2 parametros. +[ $# -eq 2 ] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME int_ndiskSecondStage int_partitionSecondStage" || return $? + +# Error si no puede montar sistema de archivos. +PART=$(ogMount $1 $2) || return $? +# La función debe ser llamanda desde ogGrubOgliveDefaultEntry, ogBurgOgliveDefaultEntry or ogRefindOgliveDefaultEntry. +case "$FUNC" in + ogGrubOgliveDefaultEntry) + CFGFILE="$PART/boot/grubMBR/boot/grub/grub.cfg" + ;; + ogBurgOgliveDefaultEntry) + CFGFILE="$PART/boot/burg/burg.cfg" + ;; + ogRefindOgliveDefaultEntry) + CFGFILE="$PART/EFI/refind/refind.conf" + ;; + *) + ogRaiseError $OG_ERR_FORMAT "Use ogGrubOgliveDefaultEntry, ogBurgOgliveDefaultEntry or ogRefindOgliveDefaultEntry." + return $? + ;; +esac + +# Comprobamos que exista fichero de configuración +[ -f $CFGFILE ] || ogRaiseError $OG_ERR_NOTFOUND "$CFGFILE" || return $? + +# Detectamos cual es la entrada de ogLive +NUMENTRY=$(grep ^menuentry $CFGFILE| grep -n "OpenGnsys Live"|cut -d: -f1) + +# Si no existe entrada de ogLive nos salimos +[ -z "$NUMENTRY" ] && (ogRaiseError $OG_ERR_NOTFOUND "menuentry OpenGnsys Live in $CFGFILE" || return $?) + +if [ "$(basename $CFGFILE)" == "refind.conf" ]; then + sed -i /default_selection.*$/d $CFGFILE + + sed -i "1 i\default_selection $NUMENTRY" $CFGFILE +else + let NUMENTRY=$NUMENTRY-1 + sed --regexp-extended -i s/"set default=\"?[0-9]+\"?"/"set default=\"$NUMENTRY\""/g $CFGFILE +fi + +MSG="MSG_HELP_$FUNC" +echo "${!MSG%%\.}: $@" +} + + +#/** +# ogGrubSecurity int_disk_GRUBCFG int_partition_GRUBCFG [user] [password] +#@brief Configura grub.cfg para que sólo permita editar entrada o acceder a línea de comandos al usuario especificado +#@param int_disk_SecondStage +#@param int_part_SecondStage +#@param user (default root) +#@param password (default "", no puede entrar) +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar (ogMount). +#@exception OG_ERR_NOTFOUND No encuentra archivo de configuración del grub. +#@author Irina Gomez, ETSII Universidad de Sevilla +#@date 2019-12-17 +#*/ ## +function ogGrubSecurity () +{ +# Variables locales. +local SECONDSTAGE GRUBGFC FILE USER PASSWD ENCRYPTPASSWD + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndiskSecondStage int_partitionSecondStage [USER] [PASSWORD]" \ + "$FUNCNAME 1 1 " \ + "$FUNCNAME 1 2 user clave" + return +fi + +# Error si no se reciben 2 parámetros. +[ $# -ge 2 ] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME int_ndiskSecondStage int_partitionSecondStage [USER] [PASSWORD]"|| return $? + +#localizar disco segunda etapa del grub +SECONDSTAGE=$(ogMount "$1" "$2") || return $? + +GRUBGFC=$(ls $SECONDSTAGE/{,boot/}{{grubMBR,grubPARTITION}/boot/,}{grub{,2},{,efi/}EFI/*}/{menu.lst,grub.cfg,grub.cfg.backup.og} 2>/dev/null) + +# comprobamos que exista el archivo de configuración. +[ -n "$GRUBGFC" ] || ogRaiseError $OG_ERR_NOTFOUND "grub.cfg" || return $? + +USER=${3:-root} +PASSWD=${4:-""} + +ENCRYPTPASSWD=$(echo -e "$PASSWD\n$PASSWD"|grub-mkpasswd-pbkdf2|sed -e 1,2d -e s/^.*grub/grub/) + +for FILE in $GRUBGFC; do + # Eliminamos configuración anterior + sed -i -e /superusers/d -e /password_pbkdf2/d $FILE + + # Configuramos grub.cfg para que sólo permita editar o entrar en línea de comandos al usuario especificado + [ "$PASSWD" == "" ] || sed -i "1i\password_pbkdf2 $USER $ENCRYPTPASSWD" $FILE + sed -i "1i\set superusers=\"$USER\"" $FILE + + # Permitimos que se seleccionen las entradas + sed -i /"menuentry "/s/"{"/"--unrestricted {"/ $FILE +done +} + + +#/** +# ogGrubSetTheme num_disk num_part str_theme +#@brief ver ogBootLoaderSetTheme +#@see ogBootLoaderSetTheme +#*/ ## +function ogGrubSetTheme () +{ + # Si se solicita, mostrar ayuda. + if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndiskSecondStage int_partitionSecondStage str_themeName" \ + "$FUNCNAME 1 4 ThemeBasic"\ + "$FUNCNAME \$(ogFindCache) ThemeBasic" + return + fi + ogBootLoaderSetTheme $@ + return $? +} + +#/** +# ogBurgSetTheme num_disk num_part str_theme +#@brief ver ogBootLoaderSetTheme +#@see ogBootLoaderSetTheme +#*/ ## +function ogBurgSetTheme () +{ + # Si se solicita, mostrar ayuda. + if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndiskSecondStage int_partitionSecondStage str_themeName" \ + "$FUNCNAME 1 4 ThemeBasic" \ + "$FUNCNAME \$(ogFindCache) ThemeBasic" + echo "Temas disponibles:\ $(ls $OGCAC/boot/burg/themes/)" + + return + fi + ogBootLoaderSetTheme $@ + return $? +} + + +#/** +# ogRefindSetTheme str_theme +#@brief ver ogBootLoaderSetTheme +#@see ogBootLoaderSetTheme +#*/ ## +function ogRefindSetTheme () { + local PART DIRTHEME CFGFILE + # Si se solicita, mostrar ayuda. + if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME str_themeName" \ + "$FUNCNAME ThemeBasic" + echo -e "\nThemes in $OGLIB/refind:\n$(ls $OGLIB/refind/themes/ 2>/dev/null)" + + return + fi + + # Detectamos partición ESP + read EFIDISK EFIPART <<< $(ogGetEsp) + + PART=$(ogMount $EFIDISK $EFIPART) || return $? + DIRTHEME="$PART/EFI/refind/themes" + CFGFILE="$PART/EFI/refind/refind.conf" + + # Para utilizar ogBootLoaderSetTheme es necesario la entrada set theme_name + if [ -f $CFGFILE ]; then + sed -i '1 i\set theme_name=none' $CFGFILE + else + ogRaiseError $OG_ERR_NOTFOUND "$CFGFILE" || return $? + fi + # Creamos el directorio para los temas + [ -d $DIRTHEME ] || mkdir $DIRTHEME + + ogBootLoaderSetTheme $EFIDISK $EFIPART $@ + return $? +} + + +#/** +# ogBootLoaderSetTheme +#@brief asigna un tema al BURG +#@param int_disk_SecondStage +#@param int_part_SecondStage +#@param str_theme_name +#@return +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_PARTITION Partición errónea o desconocida (ogMount). +#@exception OG_ERR_NOTFOUND Fichero de configuración no encontrado: grub.cfg burg.cfg refind.conf. +#@exception OG_ERR_NOTFOUND Entrada deltema no encontrada en burg.cfg. +#@exception OG_ERR_NOTFOUND Fichero de configuración del tema no encontrado: theme.conf (sólo refind). +#@note El tema debe situarse en OGLIB/BOOTLOADER/themes +#@version 1.1.0 - Primeras pruebas con Burg. grub no soportado. +#@author Antonio J. Doblas Viso. Universidad de Malaga +#@date 2018-01-24 +#@version 1.1.1 - Soporta rEFInd (ticket #802 #888). +#@author Irina Gomez. Universidad de Sevilla +#@date 2019-03-22 +#*/ ## +function ogBootLoaderSetTheme () +{ + +# Variables locales. +local FUNC PART CFGFILE THEME NEWTHEME BOOTLOADER MSG NEWTHEMECFG + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$MSG_SEE ogGrubSetTheme, ogBurgSetTheme or ogRefindSetTheme." + return +fi + + +NEWTHEME="$3" + +# Nombre de la función que llama a esta. +FUNC="${FUNCNAME[@]:1}" +FUNC="${FUNC%%\ *}" + + + +# Error si no se reciben 3 parametros. +[ $# -eq 3 ] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME int_ndiskSecondStage int_partitionSecondStage str_themeName" || return $? + +# Error si no puede montar sistema de archivos. +PART=$(ogMount $1 $2) || return $? +# La función debe ser llamanda desde ogGrubSetTheme, ogBurgSetTheme or ogRefindSetTheme. +case "$FUNC" in + ogGrubSetTheme) + BOOTLOADER="grub" + BOOTLOADERDIR="boot/grubMBR" + CFGFILE="$PART/boot/grubMBR/boot/grub/grub.cfg" + ogRaiseError $OG_ERR_FORMAT "ogGrubSetTheme not sopported" + return $? + ;; + ogBurgSetTheme) + BOOTLOADER="burg" + BOOTLOADERDIR="boot/burg" + CFGFILE="$PART/boot/burg/burg.cfg" + ;; + ogRefindSetTheme) + BOOTLOADER="refind" + BOOTLOADERDIR="EFI/refind" + CFGFILE="$PART/EFI/refind/refind.conf" + ;; + *) + ogRaiseError $OG_ERR_FORMAT "Use ogGrubSetTheme, ogBurgSetTheme or ogRefindSetTheme." + return $? + ;; +esac + +# Comprobamos que exista fichero de configuración +[ -f $CFGFILE ] || ogRaiseError $OG_ERR_NOTFOUND "$CFGFILE" || return $? + +# Detectamos cual es el tema asignado +THEME=$(grep "set theme_name=" $CFGFILE | grep ^set | cut -d= -f2) +# Si no existe entrada de theme_name nos salimos +[ -z "$THEME" ] && (ogRaiseError $OG_ERR_NOTFOUND "theme_name in $CFGFILE" || return $?) + +#Actualizamos el tema del servidor a la particion +if [ -d $OGLIB/$BOOTLOADER/themes/$NEWTHEME ]; then + # Para refind es necesario que exista theme.conf en el directorio del tema. + if [ "$BOOTLOADER" == "refind" ]; then + NEWTHEMECFG="$OGLIB/$BOOTLOADER/themes/$NEWTHEME/theme.conf" + [ -f $NEWTHEMECFG ] || ogRaiserError $OG_ERR_NOTFOUND "theme.conf" || return $? + grep -v "^#" $NEWTHEMECFG >> $CFGFILE + # eliminamos "set theme" es de grub y no de refind + sed -i '/theme_name/d' $CFGFILE + fi + cp -pr $OGLIB/$BOOTLOADER/themes/$NEWTHEME $PART/$BOOTLOADERDIR/themes/ +fi + +#Verificamos que el tema esta en la particion +if ! [ -d $PART/$BOOTLOADERDIR/themes/$NEWTHEME ]; then + ogRaiseError $OG_ERR_NOTFOUND "theme_name=$NEWTHEME in $PART/$BOOTLOADERDIR/themes/" || return $? +fi + +#Cambiamos la entrada el fichero de configuración. +sed --regexp-extended -i s/"set theme_name=$THEME"/"set theme_name=$NEWTHEME"/g $CFGFILE + + +} + +#/** +# ogGrubSetAdminKeys num_disk num_part str_theme +#@brief ver ogBootLoaderSetTheme +#@see ogBootLoaderSetTheme +#*/ ## +function ogGrubSetAdminKeys () +{ + # Si se solicita, mostrar ayuda. + if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndiskSecondStage int_partitionSecondStage str_bolean" \ + "$FUNCNAME 1 4 FALSE "\ + "$FUNCNAME \$(ogFindCache) ThemeBasic" + return + fi + ogBootLoaderSetAdminKeys $@ + return $? +} + +#/** +# ogBurgSetAdminKeys num_disk num_part str_bolean +#@brief ver ogBootLoaderSetAdminKeys +#@see ogBootLoaderSetAdminKeys +#*/ ## +function ogBurgSetAdminKeys () +{ + # Si se solicita, mostrar ayuda. + if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndiskSecondStage int_partitionSecondStage str_bolean" \ + "$FUNCNAME 1 4 TRUE" \ + "$FUNCNAME \$(ogFindCache) FALSE" + return + fi + ogBootLoaderSetAdminKeys $@ + return $? +} + + + +#/** +# ogBootLoaderSetAdminKeys +#@brief Activa/Desactica las teclas de administracion +#@param int_disk_SecondStage +#@param int_part_SecondStage +#@param Boolean TRUE/FALSE +#@return +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_PARTITION Partición errónea o desconocida (ogMount). +#@exception OG_ERR_NOTFOUND Fichero de configuración no encontrado: grub.cfg burg.cfg. +#@exception OG_ERR_NOTFOUND Entrada deltema no encontrada en burg.cfg. +#@version 1.1.0 - Primeras pruebas con Burg. grub no soportado. +#@author Antonio J. Doblas Viso. Universidad de Malaga +#@date 2018-01-24 +#*/ ## +function ogBootLoaderSetAdminKeys () +{ + +# Variables locales. +local FUNC PART CFGFILE BOOTLOADER BOOTLOADERDIR CFGFILE MSG + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$MSG_SEE ogGrubSetSetAdminKeys ogBurgSetSetAdminKeys" + return +fi + + +# Nombre de la función que llama a esta. +FUNC="${FUNCNAME[@]:1}" +FUNC="${FUNC%%\ *}" + + +# Error si no se reciben 2 parametros. +[ $# -eq 3 ] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME int_ndiskSecondStage int_partitionSecondStage str_bolean" || return $? + +# Error si no puede montar sistema de archivos. +PART=$(ogMount $1 $2) || return $? +# La función debe ser llamanda desde ogGrubSetAdminKeys or ogBurgSetAdminKeys. +case "$FUNC" in + ogGrubSetAdminKeys) + BOOTLOADER="grub" + BOOTLOADERDIR="grubMBR" + CFGFILE="$PART/boot/grubMBR/boot/grub/grub.cfg" + ogRaiseError $OG_ERR_FORMAT "ogGrubSetAdminKeys not sopported" + return $? + ;; + ogBurgSetAdminKeys) + BOOTLOADER="burg" + BOOTLOADERDIR="burg" + CFGFILE="$PART/boot/burg/burg.cfg" + ;; + *) + ogRaiseError $OG_ERR_FORMAT "Use ogGrubSetAdminKeys" + return $? + ;; +esac + + +# Comprobamos que exista fichero de configuración +[ -f $CFGFILE ] || ogRaiseError $OG_ERR_NOTFOUND "$CFGFILE" || return $? + + +case "$3" in + true|TRUE) + [ -f ${OGCAC}/boot/$BOOTLOADERDIR/themes/conf.d/10_hotkey.disabled ] && mv ${OGCAC}/boot/$BOOTLOADERDIR/themes/conf.d/10_hotkey.disabled ${OGCAC}/boot/$BOOTLOADERDIR/themes/conf.d/10_hotkey + ;; + false|FALSE) + [ -f ${OGCAC}/boot/$BOOTLOADERDIR/themes/conf.d/10_hotkey ] && mv ${OGCAC}/boot/$BOOTLOADERDIR/themes/conf.d/10_hotkey ${OGCAC}/boot/$BOOTLOADERDIR/themes/conf.d/10_hotkey.disabled + ;; + *) + ogRaiseError $OG_ERR_FORMAT "str bolean unknow " + return $? + ;; +esac +} + + + +#/** +# ogGrubSetTimeOut num_disk num_part int_timeout_seconds +#@brief ver ogBootLoaderSetTimeOut +#@see ogBootLoaderSetTimeOut +#*/ ## +function ogGrubSetTimeOut () +{ + # Si se solicita, mostrar ayuda. + if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndiskSecondStage int_partitionSecondStage int_timeout_seconds" \ + "$FUNCNAME 1 4 50 "\ + "$FUNCNAME \$(ogFindCache) 50" + return + fi + ogBootLoaderSetTimeOut $@ + return $? +} + +#/** +# ogBurgSetTimeOut num_disk num_part str_bolean +#@brief ver ogBootLoaderSetTimeOut +#@see ogBootLoaderSetTimeOut +#*/ ## +function ogBurgSetTimeOut () +{ + # Si se solicita, mostrar ayuda. + if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndiskSecondStage int_partitionSecondStage str_timeout_seconds" \ + "$FUNCNAME 1 4 50" \ + "$FUNCNAME \$(ogFindCache) 50" + return + fi + ogBootLoaderSetTimeOut $@ + return $? +} + + +#/** +# ogRefindSetTimeOut int_timeout_second +#@brief ver ogBootLoaderSetTimeOut +#@see ogBootLoaderSetTimeOut +#*/ ## +function ogRefindSetTimeOut () +{ + local EFIDISK EFIPART + # Si se solicita, mostrar ayuda. + if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_timeout_seconds" \ + "$FUNCNAME 50" + return + fi + + read EFIDISK EFIPART <<< $(ogGetEsp) + ogBootLoaderSetTimeOut $EFIDISK $EFIPART $@ + return $? +} + +#/** +# ogBootLoaderSetTimeOut +#@brief Define el tiempo (segundos) que se muestran las opciones de inicio +#@param int_disk_SecondStage +#@param int_part_SecondStage +#@param int_timeout_seconds +#@return +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_PARTITION Partición errónea o desconocida (ogMount). +#@exception OG_ERR_NOTFOUND Fichero de configuración no encontrado: grub.cfg burg.cfg. +#@exception OG_ERR_NOTFOUND Entrada deltema no encontrada en burg.cfg. +#@version 1.1.0 - Primeras pruebas con Burg. GRUB solo si está instalado en MBR +#@author Antonio J. Doblas Viso. Universidad de Malaga +#@date 2018-01-24 +#*/ ## +function ogBootLoaderSetTimeOut () +{ + +# Variables locales. +local FUNC PART CFGFILE TIMEOUT BOOTLOADER BOOTLOADERDIR CFGFILE MSG + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$MSG_SEE ogGrubSetTimeOut, ogBurgSetTimeOut or ogRefindSetTimeOut" + return +fi + +ogCheckStringInReg $3 "^[0-9]{1,10}$" && TIMEOUT="$3" || ogRaiseError $OG_ERR_FORMAT "param 3 is not a integer" + +# Nombre de la función que llama a esta. +FUNC="${FUNCNAME[@]:1}" +FUNC="${FUNC%%\ *}" + +# Error si no se reciben 3 parametros. +[ $# -eq 3 ] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME int_ndiskSecondStage int_partitionSecondStage int_timeout_seconds" || return $? + +# Error si no puede montar sistema de archivos. +PART=$(ogMount $1 $2) || return $? +# La función debe ser llamanda desde ogGrubSetTimeOut, ogBurgSetTimeOut or ogRefindSetTimeOut. +case "$FUNC" in + ogGrubSetTimeOut) + BOOTLOADER="grub" + BOOTLOADERDIR="boot/grubMBR" + CFGFILE="$PART/boot/grubMBR/boot/grub/grub.cfg" + ;; + ogBurgSetTimeOut) + BOOTLOADER="burg" + BOOTLOADERDIR="boot/burg" + CFGFILE="$PART/boot/burg/burg.cfg" + ;; + ogRefindSetTimeOut) + BOOTLOADER="refind" + BOOTLOADERDIR="EFI/refind" + CFGFILE="$PART/EFI/refind/refind.conf" + ;; + *) + ogRaiseError $OG_ERR_FORMAT "Use ogGrubSetTimeOut, ogBurgSetTimeOut or ogRefindSetTimeOut." + return $? + ;; +esac + +# Comprobamos que exista fichero de configuración +[ -f $CFGFILE ] || ogRaiseError $OG_ERR_NOTFOUND "$CFGFILE" || return $? + +# Asignamos el timeOut. +if [ "$BOOTLOADER" == "refind" ]; then + sed -i s/timeout.*$/"timeout $TIMEOUT"/g $CFGFILE +else + sed -i s/timeout=.*$/timeout=$TIMEOUT/g $CFGFILE +fi +} + + +#/** +# ogGrubSetResolution num_disk num_part int_resolution +#@brief ver ogBootLoaderSetResolution +#@see ogBootLoaderSetResolution +#*/ ## +function ogGrubSetResolution () +{ + # Si se solicita, mostrar ayuda. + if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndiskSecondStage int_partitionSecondStage [str_resolution]" \ + "$FUNCNAME 1 4 1024x768" \ + "$FUNCNAME \$(ogFindCache) 1024x768" \ + "$FUNCNAME 1 4" + return + fi + ogBootLoaderSetResolution $@ + return $? +} + +#/** +# ogBurgSetResolution num_disk num_part str_bolean +#@brief ver ogBootLoaderSetResolution +#@see ogBootLoaderSetResolution +#*/ ## +function ogBurgSetResolution () + { + # Si se solicita, mostrar ayuda. + if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndiskSecondStage int_partitionSecondStage [str_resolution]" \ + "$FUNCNAME 1 4 1024x768" \ + "$FUNCNAME \$(ogFindCache) 1024x768" \ + "$FUNCNAME 1 4" + return + fi + ogBootLoaderSetResolution $@ + return $? +} + + + +#/** +# ogBootLoaderSetResolution +#@brief Define la resolucion que usuara el thema del gestor de arranque +#@param int_disk_SecondStage +#@param int_part_SecondStage +#@param str_resolution (Opcional) +#@return +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_PARTITION Partición errónea o desconocida (ogMount). +#@exception OG_ERR_NOTFOUND Fichero de configuración no encontrado: grub.cfg burg.cfg. +#@version 1.1.0 - Primeras pruebas con Burg. grub no soportado. +#@author Antonio J. Doblas Viso. Universidad de Malaga +#@date 2018-01-24 +#*/ ## +function ogBootLoaderSetResolution () +{ + +# Variables locales. +local FUNC PART CFGFILE RESOLUTION NEWRESOLUTION DEFAULTRESOLUTION BOOTLOADER BOOTLOADERDIR CFGFILE MSG + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$MSG_SEE ogGrubSetResolution, ogBurgSetResolution or ogRefindSetResolution." + return +fi + + +# Nombre de la función que llama a esta. +FUNC="${FUNCNAME[@]:1}" +FUNC="${FUNC%%\ *}" + + +# Error si no se reciben 2 parametros. +[ $# -ge 2 ] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME int_ndiskSecondStage int_partitionSecondStage [str_resolution]" || return $? + +# Error si no puede montar sistema de archivos. +PART=$(ogMount $1 $2) || return $? +# La función debe ser llamanda desde ogGrugSetResolution, ogBurgSetResolution or ogRefindSetResolution. +case "$FUNC" in + ogGrubSetResolution) + BOOTLOADER="grub" + BOOTLOADERDIR="grubMBR" + CFGFILE="$PART/boot/grubMBR/boot/grub/grub.cfg" + ogRaiseError $OG_ERR_FORMAT "ogGrubSetResolution not sopported" + return $? + ;; + ogBurgSetResolution) + BOOTLOADER="burg" + BOOTLOADERDIR="burg" + CFGFILE="$PART/boot/burg/burg.cfg" + ;; + *) + ogRaiseError $OG_ERR_FORMAT "Use GrugSetResolution, ogBurgSetResolution or ogRefindSetResolution." + return $? + ;; +esac + +DEFAULTRESOLUTION=1024x768 + +# Comprobamos que exista fichero de configuración +[ -f $CFGFILE ] || ogRaiseError $OG_ERR_NOTFOUND "$CFGFILE" || return $? + +#controlar variable a consierar vga (default template) o video (menu) +#Si solo dos parametros autoconfiguracion basado en el parametro vga de las propiedad menu. si no hay menu asignado es 788 por defecto +if [ $# -eq 2 ] ; then + if [ -n $video ]; then + NEWRESOLUTION=$(echo "$video" | cut -f2 -d: | cut -f1 -d-) + fi + if [ -n $vga ] ; then + case "$vga" in + 788|789|814) + NEWRESOLUTION=800x600 + ;; + 791|792|824) + NEWRESOLUTION=1024x768 + ;; + 355) + NEWRESOLUTION=1152x864 + ;; + 794|795|829) + NEWRESOLUTION=1280x1024 + ;; + esac + fi +fi + +if [ $# -eq 3 ] ; then + #comprobamos que el parametro 3 cumple formato NNNNxNNNN + ogCheckStringInReg $3 "[0-9]{3,4}[x][0-9]{3,4}\$" && NEWRESOLUTION="$3" || ogRaiseError $OG_ERR_FORMAT "param 3 is not a valid resolution: 800x600, 1024x768, 1152x864, 1280x1024, 1600x1200" +fi + +# Si no existe NEWRESOLUCION asignamos la defaulT +[ -z "$NEWRESOLUTION" ] && NEWRESOLUTION=$DEFAULRESOLUTION + +#Cambiamos la entrada el fichero de configuración. +sed -i s/gfxmode=.*$/gfxmode=$NEWRESOLUTION/g $CFGFILE +} + + + + +#/** +# ogBootLoaderSetResolution +#@brief Define la resolucion que usuara el thema del gestor de arranque +#@param int_resolution1 +#@param int_resolution2 (Opcional) +#@return +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_PARTITION Partición errónea o desconocida (ogMount). +#@exception OG_ERR_NOTFOUND Fichero de configuración no encontrado: grub.cfg burg.cfg. +#*/ ## +function ogRefindSetResolution () { +local PART CFGFILE +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_resolution1 [int_resolution2]" \ + "$FUNCNAME 1366 768" \ + "$FUNCNAME 1" + return +fi + + # Error si no se reciben 2 parametros. +[ $# -ge 1 ] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME int_resolution1 [int_resolution2]" || return $? + +# Error si no puede montar sistema de archivos. +PART=$(ogMount $(ogGetEsp)) || return $? + +# Comprobamos que exista fichero de configuración +CFGFILE=$PART/EFI/refind/refind.conf +[ -f $CFGFILE ] || ogRaiseError $OG_ERR_NOTFOUND "$CFGFILE" || return $? + +# Borramos resolucion anterior y configuramos la nueva +sed -i /^resolution/d $CFGFILE + +sed -i "1 i\resolution $1 $2" $CFGFILE +} + +# ogRefindInstall bool_autoconfig +#@brief Instala y actualiza el gestor rEFInd en la particion EFI +#@param bolean_Check__auto_config true | false[default] +#@return +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND No se encuentra la partición ESP. +#@exception OG_ERR_NOTFOUND No se encuentra shimx64.efi.signed. +#@exception OG_ERR_NOTFOUND No se encuentra refind-install o refind en OGLIB +#@exception OG_ERR_PARTITION No se puede montar la partición ESP. +#@note Refind debe estar instalado en el ogLive o compartido en OGLIB +#@version 1.1.0 - Primeras pruebas. +#@author Juan Carlos Garcia. Universidad de ZAragoza. +#@date 2017-06-26 +#@version 1.1.1 - Usa refind-install. Obtiene partición con ogGetEsp. Configura Part-X-Y y ogLive. +#@author Irina Gomez. Universidad de Sevilla. +#@date 2019-03-22 +#*/ ## +function ogRefindInstall () { +# Variables locales. +local CONFIG EFIDISK EFIPART EFIDEVICE EFIMNT EFIDIR SHIM REFINDDIR +local CACHEDEVICE OGLIVE OGLIVEDIR CMDLINE OGICON CFGFILE DEVICES +local LNXCFGFILE NUMENTRY DIR + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME boolean_autoconfig " \ + "$FUNCNAME TRUE" + return +fi + +# Recogemos parametros +CONFIG=${1:-"FALSE"} + +read -e EFIDISK EFIPART <<< $(ogGetEsp) +EFIDEVICE=$(ogDiskToDev $EFIDISK $EFIPART) || ogRaiseError $OG_ERR_NOTFOUND "ESP" || return $? +EFIMNT=$(ogMount $EFIDISK $EFIPART) || ogRaiseError $OG_ERR_PARTITION "$MSG_ERROR mount ESP" || return $? +EFIDIR="$EFIMNT/EFI" +[ -d $EFIDIR ] || mkdir $EFIDIR + +# Comprobamos que exista shimx64 +SHIM=$(ogGetPath /usr/lib/shim/shimx64.efi.signed) +[ "$SHIM" == "" ] && return $(ogRaiseError $OG_ERR_NOTFOUND "shimx64.efi.signed") + +# Si existe configuración anterior de refind la borro +[ -d "$EFIDIR/refind" ] && rm -rf $EFIDIR/refind + +# Instalamos rEFInd. +refind-install --yes --alldrivers --root $EFIMNT --shim $SHIM + +# Firmo refind con certificado de OpenGnsys +mv $EFIDIR/refind/grubx64.efi $EFIDIR/refind/grubx64.efi-unsigned +sbsign --key $OGETC/ssl/private/opengnsys.key --cert $OGETC/ssl/certs/opengnsys.crt --output $EFIDIR/refind/grubx64.efi $EFIDIR/refind/grubx64.efi-unsigned + +# Copio los certificados +cp /etc/refind.d/keys/* $EFIDIR/refind/keys +# Copio certificado opengnsys +cp $OGETC/ssl/certs/opengnsys.* $EFIDIR/refind/keys + +# Ponemos la entrada en NVRAM en el segundo lugar del orden de arranque +NEWORDER="$(ogNvramGetOrder|awk '{gsub(",", " "); printf "%x %x %s\n", $2, $1, substr($0, index($0,$3))}')" +ogNvramSetOrder $NEWORDER + +# Borramos configuración linux +[ -f $EFIMNT/boot/refind_linux.conf ] && mv $EFIMNT/boot/refind_linux.conf{,.ogbackup} + +# Eliminamos punto de motaje (por si ejecutamos más de una vez) +umount $EFIMNT/boot/efi + +# Para la configuración del ogLive +ogMountCache &>/dev/null +if [ $? -eq 0 ]; then + # Detectamos si hay ogLive + CACHEDEVICE=$(ogDiskToDev $(ogFindCache)) + OGLIVE=$(find $OGCAC/boot -name ogvmlinuz|head -1) + # Obtenemos parametros del kernel y sustituimos root + # La línea de opciones no puede contener la cadena initrd. + CMDLINE="$(cat /proc/cmdline|sed -e 's/^.*ogvmlinuz.efi //g' -e 's/^.*ogvmlinuz //g' -e 's|root=/dev/[a-z]* ||g' \ + -e 's/ogupdateinitrd=[a-z]* //g')" + CMDLINE="root=$CACHEDEVICE ${CMDLINE#*ogvmlinuz}" + + # Icono para la entrada de menú + OGICON=$(ls $OGLIB/refind/icons/so_opengnsys.png 2>/dev/null) + [ "$OGICON" == "" ] && OGICON="${EFIDIR}/refind/icons/os_unknown.png" + cp "$OGICON" "$OGCAC/.VolumeIcon.png" +fi + +# Configuramos rEFInd si es necesario +CFGFILE="${EFIDIR}/refind/refind.conf" +if [ "$CONFIG" == "TRUE" ]; then + echo -e "\n\n# Configuración OpenGnsys" >> $CFGFILE + # Excluimos dispositivos distintos de ESP y CACHE + DEVICES=$(blkid -s PARTUUID |awk -v D=$EFIDEVICE -v C=$CACHEDEVICE '$1!=D":" && $1!=C":" {gsub(/PARTUUID=/,"");gsub(/"/,""); aux = aux" "$2","} END {print aux}') + echo "dont_scan_volumes $DEVICES" >> $CFGFILE + # Excluimos en la ESP los directorios de los sistemas operativos + echo "dont_scan_dirs EFI/microsoft,EFI/ubuntu,EFI/grub" >> $CFGFILE + echo "use_graphics_for osx,linux,windows" >> $CFGFILE + echo "showtools reboot, shutdown" >> $CFGFILE + + # Configuramos ogLive + if [ "$OGLIVE" != "" ]; then + # Cambiamos nombre de kernel e initrd para que lo detecte refind + OGLIVEDIR="$(dirname $OGLIVE)" + cp "$OGLIVE" "${OGLIVE}.efi" + cp "$OGLIVEDIR/oginitrd.img" "$OGLIVEDIR/initrd.img" + + # Incluimos el directorio de ogLive. + echo "also_scan_dirs +,boot/$(basename $OGLIVEDIR)" >> $CFGFILE + # Fichero de configuración de refind para kernel de linux. + LNXCFGFILE="$OGLIVEDIR/refind_linux.conf" + echo "\"OpenGnsys Live\" \"$CMDLINE\"" > $LNXCFGFILE + + # Ponemos ogLive como la entrada por defecto + NUMENTRY=$(ls -d $EFIDIR/Part-??-??|wc -l) + echo "default_selection $((NUMENTRY+1))" >> $CFGFILE + fi +else + # Renombramos la configuración por defecto + mv $CFGFILE ${CFGFILE}.auto + + # Creamos nueva configuración + echo "# Configuración OpenGnsys" >> $CFGFILE + echo "timeout 20" > $CFGFILE + echo "showtools reboot, shutdown" >> $CFGFILE + echo -e "scanfor manual\n" >> $CFGFILE + # Configuración para sistemas restaurados con OpenGnsys + for DIR in $(ls -d /mnt/sda1/EFI/Part-*-* 2>/dev/null); do + echo "menuentry \"${DIR##*/}\" {" >> $CFGFILE + echo " loader /EFI/${DIR##*/}/Boot/ogloader.efi" >> $CFGFILE + [ -f $DIR/Boot/bootmgfw.efi ] && echo " icon /EFI/refind/icons/os_win8.png" >> $CFGFILE + [ -f $DIR/Boot/grubx64.efi ] && echo " icon /EFI/refind/icons/os_linux.png" >> $CFGFILE + echo "}" >> $CFGFILE + done + # Configuración ogLive si secureboot no está activado + if ! dmesg|grep secureboot.*enabled &>/dev/null; then + if [ "$OGLIVE" != "" ]; then + echo "menuentry \"OpenGnsys Live\" {" >> $CFGFILE + echo " volume CACHE" >> $CFGFILE + echo " ostype Linux" >> $CFGFILE + echo " loader /boot/$(basename ${OGLIVE%/*})/ogvmlinuz" >> $CFGFILE + echo " initrd /boot/$(basename ${OGLIVE%/*})/oginitrd.img" >> $CFGFILE + echo " options \"$CMDLINE\"" >> $CFGFILE + echo "}" >> $CFGFILE + + # Ponemos ogLive como la entrada por defecto + sed -i '1 i\default_selection "OpenGnsys Live"' $CFGFILE + fi + fi +fi +} + +#/** +# ogGrub4dosInstallMbr int_ndisk +#@brief Genera un nuevo Codigo de arranque en el MBR del disco indicado, compatible con los SO tipo Windows, Linux. +#@param int_ndisk nº de orden del disco +#@param int_ndisk nº de orden del particion +#@return +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Tipo de partición desconocido o no se puede montar. +#@exception OG_ERR_NOTBIOS Equipo no firmware BIOS legacy +#@exception OG_ERR_NOMSDOS Disco duro no particioniado en modo msdos +#@exception OG_ERR_NOTWRITE Particion no modificable. +#@version 1.1.1 - Adaptacion a OpenGnSys. +#@author Alberto García Padilla / Antonio J. Doblas Viso. Universidad de Malaga +#@date 2009-10-17 +#*/ ## + +function ogGrub4dosInstallMbr () +{ +# Variables locales. +local DISK PART DEVICE MOUNTDISK GRUBDISK BINBDIR + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_part " \ + "$FUNCNAME 1 1 " + return +fi +# Error si no se recibe 2 parámetros. +[ $# == 2 ] || return $(ogRaiseError $OG_ERR_FORMAT; echo $?) + +DISK="$1" +PART="$2" + +#Controlar existencia de disco y particion +DEVICE=$(ogDiskToDev $DISK) || ogRaiseError $OG_ERR_NOTFOUND || return $? +MOUNTDISK=$(ogMount $DISK $PART) || ogRaiseError $OG_ERR_PARTITION "$MSG_ERROR " || return $? +#Controlar acceso de escritura a la particion +ogIsReadonly $DISK $PART && return $(ogRaiseError $OG_ERR_NOTWRITE ": $DISK $PART" || echo $?) +#Controlar disco no uefi +ogIsEfiActive && return $(ogRaiseError $OG_ERR_NOTBIOS " : grub4dos solo soporta PC con bios legacy"; echo $?) +#Controlar particionado tipo msdos +ogCheckStringInGroup $(ogGetPartitionTableType $DISK) "MSDOS" || return $(ogRaiseError $OG_ERR_NOMSDOS ": grub2dos requiere particionado tipo MSDOS"; echo $?) +#Controlar la existencia del grub4dos con acceso a ntfs +BINDIR="${OGLIB}/grub4dos/grub4dos-0.4.6a" +[ -f ${BINDIR}/bootlace.com ] || ogRaiseError $OG_ERR_NOTFOUND ": ${BINDIR}/bootlace.com" || return $? + +#instalar el bootloader de grlrd en el MBR +${BINDIR}/bootlace64.com $DEVICE &>/dev/null +#copiar grld a la particion +cp ${BINDIR}/grldr $MOUNTDISK +#Instalar y configurar grub4dos +if [[ -f $MOUNTDISK/boot/grub/menu.lst ]]; then + rm $MOUNTDISK/boot/grub/menu.lst + rmdir /$MOUNTDISK/boot/grub +fi +if [[ ! -f $MOUNTDISK/boot/grub/menu.lst ]]; then + mkdir -p /$MOUNTDISK/boot/grub + touch /$MOUNTDISK/boot/grub/menu.lst + + GRUBDISK=$[$1-1] + +cat << EOT >/$MOUNTDISK/boot/grub/menu.lst +##NO-TOCAR-ESTA-LINEA MBR +timeout 0 +title MBR +root (hd$GRUBDISK,0) +chainloader (hd$GRUBDISK,0)+1 +boot +EOT + +fi +} diff --git a/client/lib/engine/bin/BootLib.py b/client/lib/engine/bin/BootLib.py deleted file mode 100644 index bf6f0b9..0000000 --- a/client/lib/engine/bin/BootLib.py +++ /dev/null @@ -1,1018 +0,0 @@ -#/** -#@file BootLib.py -#@brief Librería o clase Boot -#@class Boot -#@brief Funciones para arranque y post-configuración de sistemas de archivos. -#@warning License: GNU GPLv3+ -#*/ - -import os -import re -import tempfile -import subprocess -import shutil -import glob - -import ogGlobals -import SystemLib -import FileSystemLib -import RegistryLib -import DiskLib -import InventoryLib -import FileLib -import UEFILib - -#/** -# ogBoot int_ndisk int_nfilesys [ NVRAMPERM ] [str_kernel str_initrd str_krnlparams] -#@brief Inicia el proceso de arranque de un sistema de archivos. -#@param int_ndisk nº de orden del disco -#@param int_nfilesys nº de orden del sistema de archivos -#@param str_nvramperm UEFI: La entrada en la NVRAM se incluye en el orden de arranque (opcional) -#@param str_krnlparams parámetros de arranque del kernel (opcional) -#@return (activar el sistema de archivos). -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. -#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. -#@exception OG_ERR_NOTOS La partición no tiene instalado un sistema operativo. -#@note En Linux, si no se indican los parámetros de arranque se detectan de la opción por defecto del cargador GRUB. -#@note En Linux, debe arrancarse la partición del directorio \c /boot -#*/ ## - - -#/** -# ogGetWindowsName int_ndisk int_nfilesys -#@brief Muestra el nombre del equipo en el registro de Windows. -#@param int_ndisk nº de orden del disco -#@param int_nfilesys nº de orden del sistema de archivos -#@return str_name - nombre del equipo -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. -#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. -#*/ ## - - -#/** -# ogLinuxBootParameters int_ndisk int_nfilesys -#@brief Muestra los parámetros de arranque de un sistema de archivos Linux. -#@param int_ndisk nº de orden del disco -#@param int_nfilesys nº de orden del sistema de archivos -#@return str_kernel str_initrd str_parameters ... -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. -#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. -#@warning Función básica usada por \c ogBoot -#*/ ## - - -#/** -# ogSetWindowsName int_ndisk int_nfilesys str_name -#@brief Establece el nombre del equipo en el registro de Windows. -#@param int_ndisk nº de orden del disco -#@param int_nfilesys nº de orden del sistema de archivos -#@param str_name nombre asignado -#@return (nada) -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. -#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. -#@exception OG_ERR_OUTOFLIMIT Nombre Netbios con más de 15 caracteres. -#*/ ## -def ogSetWindowsName (disk, par, name): - if len (name) > 15: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_OUTOFLIMIT, f'"{name[0:15]}..."') - return - - mntdir = FileSystemLib.ogMount (disk, par) - if not mntdir: return None - - RegistryLib.ogSetRegistryValue (mntdir, 'system', r'\ControlSet001\Control\ComputerName\ComputerName\ComputerName', name) - RegistryLib.ogSetRegistryValue (mntdir, 'system', r'\ControlSet001\Services\Tcpip\Parameters\Hostname', name) - RegistryLib.ogSetRegistryValue (mntdir, 'system', r'\ControlSet001\Services\Tcpip\Parameters\HostName', name) - RegistryLib.ogSetRegistryValue (mntdir, 'system', r'\ControlSet001\services\Tcpip\Parameters\Hostname', name) - RegistryLib.ogSetRegistryValue (mntdir, 'system', r'\ControlSet001\Services\Tcpip\Parameters\NV Hostname', name) - RegistryLib.ogSetRegistryValue (mntdir, 'system', r'\ControlSet001\Services\Tcpip\Parameters\NV HostName', name) - RegistryLib.ogSetRegistryValue (mntdir, 'system', r'\ControlSet001\services\Tcpip\Parameters\NV Hostname', name) - - - -#/** -# ogSetWinlogonUser int_ndisk int_npartition str_username -#@brief Establece el nombre de usuario por defecto en la entrada de Windows. -#@param int_ndisk nº de orden del disco -#@param int_npartition nº de orden de la partición -#@param str_username nombre de usuario por defecto -#@return (nada) -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. -#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. -#*/ ## - - -#/** -# ogBootMbrXP int_ndisk -#@brief Genera un nuevo Master Boot Record en el disco duro indicado, compatible con los SO tipo Windows -#@param int_ndisk nº de orden del disco -#@return salida del programa my-sys -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. -#*/ ## - - -#/** -# ogBootMbrGeneric int_ndisk -#@brief Genera un nuevo Codigo de arranque en el MBR del disco indicado, compatible con los SO tipo Windows, Linux. -#@param int_ndisk nº de orden del disco -#@return salida del programa my-sys -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_NOTFOUND Tipo de partición desconocido o no se puede montar. -#*/ ## - - - - -#/** -# ogFixBootSector int_ndisk int_parition -#@brief Corrige el boot sector de una particion activa para MS windows/dos -fat-ntfs -#@param int_ndisk nº de orden del disco -#@param int_partition nº de particion -#@return -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. -#*/ ## -def ogFixBootSector (disk, par): - partype = DiskLib.ogGetPartitionId (disk, par) - if partype not in [ '1', '4', '6', '7', 'b', 'c', 'e', 'f', '17', '700', 'EF00' ]: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, '') - return - - if not FileSystemLib.ogUnmount (disk, par): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, '') - return - - disk0 = str (int (disk) - 1) - - tmpfile = tempfile.NamedTemporaryFile (prefix='ogFBS-', mode='w').name - with open (tmpfile, 'w') as fd: - fd.write (f"""disk={disk0} -main_part={par} -fix_first_sector=yes -""") - subprocess.run (['timeout', '--foreground', '--signal=SIGKILL', '5s', 'spartlnx.run', '-cui', '-nm', '-w', '-f', tmpfile], stdin=subprocess.DEVNULL) - - os.remove (tmpfile) - - -#/** -# ogGetBootMbr int_ndisk -#@brief Obtiene el contenido del sector de arranque de un disco. -#@param int_ndisk nº de orden del disco -#@return str_MBR Descripción del contenido del MBR. -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_NOTFOUND Dispositivo de disco no encontrado. -#*/ ## - -#/** -# ogWindowsBootParameters int_ndisk int_parition -#@brief Configura el gestor de arranque de windows 7 / vista / XP / 2000 -#@param int_ndisk nº de orden del disco -#@param int_partition nº de particion -#@return -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. -#*/ ## - -def ogWindowsBootParameters (disk, par): - if not DiskLib.ogDiskToDev (disk, par): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, '') - return - - disk0 = int (disk) - 1 - - tmpfile = tempfile.NamedTemporaryFile (prefix='ogWBP-', mode='w').name - if InventoryLib.ogIsEfiActive(): - bootdisk, bootpar = DiskLib.ogGetEsp().split() - if not FileSystemLib.ogUnmount (bootdisk, bootpar): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f'ESP: {bootdisk} {bootpar}') - return - bootdisk = str (int (bootdisk) - 1) - bootlabel = f'Part-{int(bootdisk):02d}-{int(bootpar):02d}' - bcdfile = f'boot_BCD_file=/EFI/{bootlabel}/Boot/BCD' - else: - bootdisk = disk0 - bootpar = par - bcdfile = '' - - -# Obtener versión de Windows. - winver = InventoryLib.ogGetOsVersion (disk, par) - parts = re.split (':| ', winver) - if 'Windows' == parts[0] and 'Server' == parts[2]: - winver = parts[1] + parts[2] + parts[3] - else: - winver = parts[1] + parts[2] - if not winver: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTOS, 'Windows') - return - -# Acciones para Windows XP. - if 'XP' in winver: - m = FileSystemLib.ogMount (disk, par) - if not m or not os.path.exists (f'{m}/boot.ini'): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, 'boot.ini') - return - with open (f'{m}/boot.ini', 'r') as fd: - boot_ini = fd.read() - boot_ini = re.sub (r'partition\([0-9]\)', f'partition({par})', boot_ini) - boot_ini = re.sub (r'rdisk\([0-9]\)', f'rdisk({disk0})', boot_ini) - with open (f'{m}/tmp.boot.ini', 'w') as fd: - fd.write (boot_ini) - os.rename (f'{m}/tmp.boot.ini', f'{m}/boot.ini') - return True - - if not FileSystemLib.ogUnmount (disk, par): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, '') - return - - -#Preparando instruccion Windows Resume Application - with open (tmpfile, 'w') as fd: - fd.write (f"""boot_disk={bootdisk} -boot_main_part={bootpar} -{bcdfile} -disk={disk0} -main_part={par} -boot_entry=Windows Resume Application -""") - subprocess.run (['timeout', '--foreground', '--signal=SIGKILL', '5s', 'spartlnx.run', '-cui', '-nm', '-w', '-f', tmpfile], stdin=subprocess.DEVNULL) - - -#Preparando instruccion tipo windows - with open (tmpfile, 'w') as fd: - fd.write (f"""boot_disk={bootdisk} -boot_main_part={bootpar} -{bcdfile} -disk={disk0} -main_part={par} -boot_entry={winver} -""") - subprocess.run (['timeout', '--foreground', '--signal=SIGKILL', '5s', 'spartlnx.run', '-cui', '-nm', '-w', '-f', tmpfile], stdin=subprocess.DEVNULL) - -##Preparando instruccion Ramdisk Options - with open (tmpfile, 'w') as fd: - fd.write (f"""boot_disk={bootdisk} -boot_main_part={bootpar} -{bcdfile} -disk={disk0} -main_part={par} -boot_entry=Ramdisk Options -""") - subprocess.run (['timeout', '--foreground', '--signal=SIGKILL', '5s', 'spartlnx.run', '-cui', '-nm', '-w', '-f', tmpfile], stdin=subprocess.DEVNULL) - -##Preparando instruccion Recovery Environment - with open (tmpfile, 'w') as fd: - fd.write (f"""boot_disk={bootdisk} -boot_main_part={bootpar} -{bcdfile} -disk={disk0} -main_part={par} -boot_entry=Windows Recovery Environment -""") - subprocess.run (['timeout', '--foreground', '--signal=SIGKILL', '5s', 'spartlnx.run', '-cui', '-nm', '-w', '-f', tmpfile], stdin=subprocess.DEVNULL) - -##Preparando instruccion Recovery - with open (tmpfile, 'w') as fd: - fd.write (f"""boot_disk={bootdisk} -boot_main_part={bootpar} -{bcdfile} -disk={disk0} -main_part={par} -boot_entry=Windows Recovery -""") - subprocess.run (['timeout', '--foreground', '--signal=SIGKILL', '5s', 'spartlnx.run', '-cui', '-nm', '-w', '-f', tmpfile], stdin=subprocess.DEVNULL) - -#Preparando instruccion Windows Boot Manager - with open (tmpfile, 'w') as fd: - fd.write (f"""boot_disk={bootdisk} -boot_main_part={bootpar} -{bcdfile} -disk={bootdisk} -main_part={bootpar} -boot_entry=Windows Boot Manager -""") - subprocess.run (['timeout', '--foreground', '--signal=SIGKILL', '5s', 'spartlnx.run', '-cui', '-nm', '-w', '-f', tmpfile], stdin=subprocess.DEVNULL) - -#Preparando instruccion Herramienta de diagnóstico de memoria de Windows - with open (tmpfile, 'w') as fd: - fd.write (f"""boot_disk={bootdisk} -boot_main_part={bootpar} -{bcdfile} -disk={bootdisk} -main_part={bootpar} -boot_entry=Herramienta de diagnóstico de memoria de Windows -""") - subprocess.run (['timeout', '--foreground', '--signal=SIGKILL', '5s', 'spartlnx.run', '-cui', '-nm', '-w', '-f', tmpfile], stdin=subprocess.DEVNULL) - -#Preparando instruccion Herramienta de diagnóstico de memoria de Windows - with open (tmpfile, 'w') as fd: - fd.write (f"""boot_disk={bootdisk} -boot_main_part={bootpar} -{bcdfile} -disk={bootdisk} -main_part={bootpar} -boot_entry=Herramienta de diagnstico de memoria de Windows -""") - subprocess.run (['timeout', '--foreground', '--signal=SIGKILL', '5s', 'spartlnx.run', '-cui', '-nm', '-w', '-f', tmpfile], stdin=subprocess.DEVNULL) - - os.remove (tmpfile) - - - -#/** -# ogWindowsRegisterPartition int_ndisk int_partiton str_volume int_disk int_partition -#@brief Registra una partición en windows con un determinado volumen. -#@param int_ndisk nº de orden del disco a registrar -#@param int_partition nº de particion a registrar -#@param str_volumen volumen a resgistar -#@param int_ndisk_windows nº de orden del disco donde esta windows -#@param int_partition_windows nº de particion donde esta windows -#@return -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. -#*/ ## -#ogWindowsRegisterPartition ("1", "1", "c:", "1", "1") -def ogWindowsRegisterPartition (registered_disk, registered_par, registered_vol, disk, par): - registered_vol = registered_vol[0].upper() - tmpfile = tempfile.NamedTemporaryFile (prefix='ogWRP-', mode='w').name - - if not DiskLib.ogDiskToDev (registered_disk, registered_par): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, 'particion a registrar') - return - - if not DiskLib.ogDiskToDev (disk, par): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, 'particion de windows') - return - - t = InventoryLib.ogGetOsType (disk, par) - if 'Windows' not in t: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTOS, 'no es windows') - return - - v = InventoryLib.ogGetOsVersion (disk, par) - - if FileLib.ogGetPath (src=f'{disk} {par}', file='WINDOWS'): - systemroot = 'Windows' - elif FileLib.ogGetPath (src=f'{disk} {par}', file='WINNT'): - systemroot = 'winnt' - else: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTOS, '') - return - - FileSystemLib.ogUnmount (disk, par) - disk0 = str (int (disk) - 1) - registered_disk0 = str (int (registered_disk) - 1) - - with open (tmpfile, 'w') as fd: - fd.write (f"""windows_disk={disk0} -windows_main_part={par} -windows_dir={systemroot} -disk={registered_disk0} -main_part={registered_par} -;ext_part -part_letter={registered_vol} -""") - subprocess.run (['timeout', '--foreground', '--signal=SIGKILL', '5s', 'spartlnx.run', '-cui', '-nm', '-w', '-f', tmpfile], stdin=subprocess.DEVNULL) - - os.remove (tmpfile) - - -#/** -# ogGrubInstallMbr int_disk_GRUBCFG int_partition_GRUBCFG -#@brief Instala el grub el el MBR del primer disco duro (FIRSTSTAGE). El fichero de configuración grub.cfg ubicado según parametros disk y part(SECONDSTAGE). Admite sistemas Windows. -#@param int_disk_SecondStage -#@param int_part_SecondStage -#@param bolean_Check_Os_installed_and_Configure_2ndStage true | false[default] -#@return -#@exception OG_ERR_FORMAT Formato incorrecto. -#*/ ## - -#ogGrubInstallMbr ('1', '1', 'FALSE') -#ogGrubInstallMbr ('1', '1', 'TRUE', 'nomodeset irqpoll pci=noacpi quiet splash') -def ogGrubInstallMbr (disk, par, checkos='FALSE', kernelparam=''): - backupname = '.backup.og' - - #error si no es linux. - #version = InventoryLib.ogGetOsVersion (disk, par) - #if not version or 'Linux' not in version: - # SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTOS, 'no es linux') - # return - - firststage = DiskLib.ogDiskToDev ('1') #La primera etapa del grub se fija en el primer disco duro - secondstage = FileSystemLib.ogMount (disk, par) #localizar disco segunda etapa del grub - if not secondstage: return - os.makedirs (f'{secondstage}/boot/grub/', exist_ok=True) - prefixsecondstage = '/boot/grubMBR' #Localizar directorio segunda etapa del grub - efioptgrub = [] - - if InventoryLib.ogIsEfiActive(): - esp = DiskLib.ogGetEsp() - efidisk, efipart = esp.split() - # Comprobamos que exista ESP y el directorio para ubuntu - efisecondstage = FileSystemLib.ogMount (efidisk, efipart) - if not efisecondstage: - FileSystemLib.ogFormat (efidisk, efipart, 'FAT32') - efisecondstage = FileSystemLib.ogMount (efidisk, efipart) - if not efisecondstage: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, 'ESP') - return - efisubdir = 'grub' - if os.path.isdir (f'{efisecondstage}/EFI/{efisubdir}'): # Borramos la configuración anterior - shutil.rmtree (f'{efisecondstage}/EFI/{efisubdir}') - os.makedirs (f'{efisecondstage}/EFI/{efisubdir}/Boot') - arch = InventoryLib.ogGetArch() - efioptgrub = ['--removable', '--no-nvram', '--uefi-secure-boot', '--target', f'{arch}-efi', f'--efi-directory={efisecondstage}/EFI/{efisubdir}'] - - # Si Reconfigurar segunda etapa (grub.cfg) == FALSE - if 'FALSE' == checkos.upper() and (os.path.exists (f'{secondstage}/boot/grub/grub.cfg') or os.path.exists (f'{secondstage}/boot/grub/grub.cfg{backupname}')): - if os.path.exists (f'{secondstage}/boot/grub/grub.cfg{backupname}'): - os.rename (f'{secondstage}/boot/grub/grub.cfg{backupname}', f'{secondstage}/boot/grub/grub.cfg') - if os.path.isdir (f'{secondstage}{prefixsecondstage}'): - shutil.rmtree (f'{secondstage}{prefixsecondstage}') - prefixsecondstage = '' # Reactivamos el grub con el grub.cfg original. - else: # SI Reconfigurar segunda etapa (grub.cfg) == TRUE - #llamada a updateBootCache para que aloje la primera fase del ogLive - subprocess.run ([f'{ogGlobals.OGSCRIPTS}/updateBootCache.py'], check=True) ## TODO: check that this works - - if InventoryLib.ogIsEfiActive(): - # UEFI: grubSintax necesita grub.cfg para detectar los kernels: si no existe recupero backup. - if not os.path.exists (f'{secondstage}/boot/grub/grub.cfg'): - if os.path.exists (f'{secondstage}/boot/grub/grub.cfg{backupname}'): - os.rename (f'{secondstage}/boot/grub/grub.cfg{backupname}', f'{secondstage}/boot/grub/grub.cfg') - else: - os.rename (f'{secondstage}/boot/grub/grub.cfg', f'{secondstage}/boot/grub/grub.cfg{backupname}') - - with open ('/etc/default/grub', 'a') as fd: #Configur la sintaxis grub para evitar menus de "recovery" en el OGLive - fd.write ('GRUB_DISABLE_RECOVERY="true"\n') - fd.write ('GRUB_DISABLE_LINUX_UUID="true"\n') - - os.makedirs (f'{secondstage}{prefixsecondstage}/boot/grub/') #Preparar configuración segunda etapa: crear ubicacion - subprocess.run (['sed', '-i', 's/^set -e/#set -e/', '/etc/grub.d/00_header']) #Preparar configuración segunda etapa: crear cabecera del fichero (ingnorar errores) - # (ogLive 5.0) Si 'pkgdatadir' está vacía ponemos valor de otros ogLive - subprocess.run (['sed', '-i', r'/grub-mkconfig_lib/i\pkgdatadir=${pkgdatadir:-"${datarootdir}/grub"}', '/etc/grub.d/00_header']) - out = subprocess.run (['/etc/grub.d/00_header'], capture_output=True, text=True).stdout - with open (f'{secondstage}{prefixsecondstage}/boot/grub/grub.cfg', 'w') as fd: - fd.write (out + '\n') - - #Preparar configuración segunda etapa: crear entrada del sistema operativo - out = subprocess.run (['grubSyntax', kernelparam], capture_output=True, text=True).stdout - with open (f'{secondstage}{prefixsecondstage}/boot/grub/grub.cfg', 'a') as fd: - fd.write (out + '\n') - - # Renombramos la configuración de grub antigua - if os.path.exists (f'{secondstage}/boot/grub/grub.cfg'): - os.rename (f'{secondstage}/boot/grub/grub.cfg', f'{secondstage}/boot/grub/grub.cfg{backupname}') - - eval = subprocess.run (['grub-install', '--force'] + efioptgrub + [f'--root-directory={secondstage}{prefixsecondstage}', firststage]).returncode - - if InventoryLib.ogIsEfiActive(): # Movemos el grubx64.efi - for b in (glob.glob (f'{efisecondstage}/EFI/{efisubdir}/EFI/BOOT/*')): - bn = os.path.basename (b) - os.rename (f'{efisecondstage}/EFI/{efisubdir}/EFI/BOOT/{bn}', f'{efisecondstage}/EFI/{efisubdir}/Boot/{bn}') - shutil.rmtree (f'{efisecondstage}/EFI/{efisubdir}/EFI') - shutil.copy2 ('/usr/lib/shim/shimx64.efi.signed', f'{efisecondstage}/EFI/{efisubdir}/Boot/shimx64.efi') - # Nombre OpenGnsys para cargador - shutil.copy2 (f'{efisecondstage}/EFI/{efisubdir}/Boot/grubx64.efi', f'{efisecondstage}/EFI/{efisubdir}/Boot/ogloader.efi') - - # Creamos entrada NVRAM y la ponemos en segundo lugar - UEFILib.ogNvramAddEntry ('grub', '/EFI/grub/Boot/shimx64.efi') - grubentry = UEFILib.ogNvramList() - for l in grubentry.splitlines(): - words = l.split() - if len(words) < 2: continue - if 'grub' == words[1]: - grubentry = words[0] - neworder = UEFILib.ogNvramGetOrder() - neworder = neworder[0:1] + [grubentry] + neworder[1:] ## la ponemos en segundo lugar - UEFILib.ogNvramSetOrder (neworder) - - return eval - - -#/** -# ogGrubInstallPartition int_disk_SECONDSTAGE int_partition_SECONDSTAGE bolean_Check_Os_installed_and_Configure_2ndStage -#@brief Instala y actualiza el gestor grub en el bootsector de la particion indicada -#@param int_disk_SecondStage -#@param int_part_SecondStage -#@param bolean_Check_Os_installed_and_Configure_2ndStage true | false[default] -#@param str "kernel param " -#@return -#@exception OG_ERR_FORMAT Formato incorrecto. -#*/ ## - -#ogGrubInstallPartition ('1', '1', 'FALSE') -#ogGrubInstallPartition ('1', '1', 'TRUE', 'nomodeset irqpoll pci=noacpi quiet splash') -def ogGrubInstallPartition (disk, par, checkos='FALSE', kernelparam=''): - backupname = '.backup.og' - - #error si no es linux. - version = InventoryLib.ogGetOsVersion (disk, par) - if not version or 'Linux' not in version: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTOS, 'no es linux') - return - - firststage = DiskLib.ogDiskToDev (disk, par) #Localizar primera etapa del grub - secondstage = FileSystemLib.ogMount (disk, par) #localizar disco segunda etapa del grub - prefixsecondstage = '/boot/grubPARTITION' #Localizar directorio segunda etapa del grub - efioptgrub = [] - - if InventoryLib.ogIsEfiActive(): - esp = DiskLib.ogGetEsp() - efidisk, efipart = esp.split() - # Comprobamos que exista ESP y el directorio para ubuntu - efisecondstage = FileSystemLib.ogMount (efidisk, efipart) - if not efisecondstage: - FileSystemLib.ogFormat (efidisk, efipart, 'FAT32') - efisecondstage = FileSystemLib.ogMount (efidisk, efipart) - if not efisecondstage: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, 'ESP') - return - efisubdir = f'Part-{int(disk):02d}-{int(par):02d}' - if os.path.isdir (f'{efisecondstage}/EFI/{efisubdir}'): # Borramos la configuración anterior - shutil.rmtree (f'{efisecondstage}/EFI/{efisubdir}') - os.makedirs (f'{efisecondstage}/EFI/{efisubdir}/Boot') - arch = InventoryLib.ogGetArch() - efioptgrub = ['--removable', '--no-nvram', '--uefi-secure-boot', '--target', f'{arch}-efi', f'--efi-directory={efisecondstage}/EFI/{efisubdir}'] - - # Si Reconfigurar segunda etapa (grub.cfg) == FALSE - if 'FALSE' == checkos.upper() and (os.path.exists (f'{secondstage}/boot/grub/grub.cfg') or os.path.exists (f'{secondstage}/boot/grub/grub.cfg{backupname}')): - if os.path.exists (f'{secondstage}/boot/grub/grub.cfg{backupname}'): - os.rename (f'{secondstage}/boot/grub/grub.cfg{backupname}', f'{secondstage}/boot/grub/grub.cfg') - if os.path.isdir (f'{secondstage}{prefixsecondstage}'): - shutil.rmtree (f'{secondstage}{prefixsecondstage}') - prefixsecondstage = '' # Reactivamos el grub con el grub.cfg original. - else: # SI Reconfigurar segunda etapa (grub.cfg) == TRUE - if InventoryLib.ogIsEfiActive(): - # UEFI: grubSintax necesita grub.cfg para detectar los kernels: si no existe recupero backup. - if not os.path.exists (f'{secondstage}/boot/grub/grub.cfg'): - if os.path.exists (f'{secondstage}/boot/grub/grub.cfg{backupname}'): - os.rename (f'{secondstage}/boot/grub/grub.cfg{backupname}', f'{secondstage}/boot/grub/grub.cfg') - else: - if (os.path.exists (f'{secondstage}/boot/grub/grub.cfg')): - os.rename (f'{secondstage}/boot/grub/grub.cfg', f'{secondstage}/boot/grub/grub.cfg{backupname}') - - with open ('/etc/default/grub', 'a') as fd: #Configur la sintaxis grub para evitar menus de "recovery" en el OGLive - fd.write ('GRUB_DISABLE_RECOVERY="true"\n') - fd.write ('GRUB_DISABLE_LINUX_UUID="true"\n') - - os.makedirs (f'{secondstage}{prefixsecondstage}/boot/grub/', exist_ok=True) #Preparar configuración segunda etapa: crear ubicacion - subprocess.run (['sed', '-i', 's/^set -e/#set -e/', '/etc/grub.d/00_header']) #Preparar configuración segunda etapa: crear cabecera del fichero (ingnorar errores) - # (ogLive 5.0) Si 'pkgdatadir' está vacía ponemos valor de otros ogLive - subprocess.run (['sed', '-i', r'/grub-mkconfig_lib/i\pkgdatadir=${pkgdatadir:-"${datarootdir}/grub"}', '/etc/grub.d/00_header']) - out = subprocess.run (['/etc/grub.d/00_header'], capture_output=True, text=True).stdout - with open (f'{secondstage}{prefixsecondstage}/boot/grub/grub.cfg', 'w') as fd: - fd.write (out + '\n') - - #Preparar configuración segunda etapa: crear entrada del sistema operativo - out = subprocess.run (['grubSyntax', disk, par, kernelparam], capture_output=True, text=True).stdout - with open (f'{secondstage}{prefixsecondstage}/boot/grub/grub.cfg', 'a') as fd: - fd.write (out + '\n') - - eval = subprocess.run (['grub-install', '--force'] + efioptgrub + [f'--root-directory={secondstage}{prefixsecondstage}', firststage]).returncode - - if InventoryLib.ogIsEfiActive(): # Movemos el grubx64.efi - for b in (glob.glob (f'{efisecondstage}/EFI/{efisubdir}/EFI/BOOT/*')): - os.rename (f'{efisecondstage}/EFI/{efisubdir}/EFI/BOOT/{b}', f'{efisecondstage}/EFI/{efisubdir}/Boot/{b}') - shutil.rmtree (f'{efisecondstage}/EFI/{efisubdir}/EFI') - shutil.copy2 ('/usr/lib/shim/shimx64.efi.signed', f'{efisecondstage}/EFI/{efisubdir}/Boot/shimx64.efi') - # Nombre OpenGnsys para cargador - shutil.copy2 (f'{efisecondstage}/EFI/{efisubdir}/Boot/grubx64.efi', f'{efisecondstage}/EFI/{efisubdir}/Boot/ogloader.efi') - - return eval - - - -#/** -# ogConfigureFstab int_ndisk int_nfilesys -#@brief Configura el fstab según particiones existentes -#@param int_ndisk nº de orden del disco -#@param int_nfilesys nº de orden del sistema de archivos -#@return (nada) -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_NOTFOUND No se encuentra el fichero fstab a procesar. -#@warning Puede haber un error si hay más de 1 partición swap. -#*/ ## -def ogConfigureFstab (disk, par): - fstab = FileLib.ogGetPath (src=f'{disk} {par}', file='/etc/fstab') - if not fstab: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'{disk},{par},/etc/fstab') - return - - efiopt = '' - - shutil.copy2 (fstab, fstab+'.backup') - - with open ('/etc/fstab', 'r') as fd: - while True: - l = fd.readline() - if not l: break - cosas = l.split() - if 6 != len (cosas): continue - fstab_dev, fstab_mntpt, fstab_fstype, fstab_opts, fstab_dump, fstab_pass = cosas - if '#' in fstab_dev: continue - if '/' == fstab_mntpt: - defroot = fstab_dev - elif 'swap' == fstab_fstype: - defswap = fstab_dev - elif '/boot/efi' == fstab_mntpt: - efiopt = '\t'.join ([fstab_fstype, fstab_opts, fstab_dump, fstab_pass]) - - partroot = DiskLib.ogDiskToDev (disk, par) - partswap = subprocess.run (['blkid', '-', ' TYPE=swap'], capture_output=True, text=True).stdout - if partswap: - partswap = partswap.splitlines()[0] - partswap = partswap.split (':')[0] - if defswap: - print ("Hay definicion de SWAP en el FSTAB $DEFSWAP -> modificamos fichero con nuevo valor $DEFSWAP->$PARTSWAP") # Mensaje temporal. - subprocess.run (f'sed "s|{defswap}|{partswap}|g; s|{defroot}|{partroot}|g" {fstab}.backup > {fstab}', shell=True) - else: - print ("No hay definicion de SWAP y si hay partición SWAP -> moficamos fichero") # Mensaje temporal. - subprocess.run (f'sed "s|{defroot}|{partroot}|g" {fstab}.backup > {fstab}', shell=True) - with open ('/etc/fstab', 'a') as fd: - fd.write (f'{partswap} none swap sw 0 0\n') - else: - print ("No hay partición SWAP -> configuramos FSTAB") # Mensaje temporal. - subprocess.run (f'sed "/swap/d" {fstab}.backup > {fstab}', shell=True) -# Si es un sistema EFI incluimos partición ESP (Si existe la modificamos) - if InventoryLib.ogIsEfiActive(): - esp = DiskLib.ogGetEsp() - efidisk, efipart = esp.split() - efidev = DiskLib.ogDiskToDev (efidisk, efipart) - - ## Opciones de la partición ESP: si no existe ponemos un valor por defecto - if not efiopt: - efiopt = '\t'.join (['vfat', 'umask=0077', '0', '1']) - - subprocess.run (f'sed -i /"boot\\/efi"/d {fstab}', shell=True) - with open ('/etc/fstab', 'a') as fd: - fd.write ('{efidev}\t/boot/efi\t{efiopt}\n') - - - -#/** -# ogSetLinuxName int_ndisk int_nfilesys [str_name] -#@brief Establece el nombre del equipo en los ficheros hostname y hosts. -#@param int_ndisk nº de orden del disco -#@param int_nfilesys nº de orden del sistema de archivos -#@param str_name nombre asignado (opcional) -#@return (nada) -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. -#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. -#@note Si no se indica nombre, se asigna un valor por defecto. -#*/ ## - - - -#/** -# ogCleanLinuxDevices int_ndisk int_nfilesys -#@brief Limpia los dispositivos del equipo de referencia. Interfaz de red ... -#@param int_ndisk nº de orden del disco -#@param int_nfilesys nº de orden del sistema de archivos -#@return (nada) -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. -#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. -#*/ ## -#ogCleanLinuxDevices (1, 1) -def ogCleanLinuxDevices (disk, par): - mntdir = FileSystemLib.ogMount (disk, par) - if not mntdir: return None - - # Eliminar fichero de configuración de udev para dispositivos fijos de red. - if os.path.exists (f'{mntdir}/etc/udev/rules.d/70-persistent-net.rules'): - os.unlink (f'{mntdir}/etc/udev/rules.d/70-persistent-net.rules') - # Eliminar fichero resume (estado previo de hibernación) utilizado por el initrd scripts-premount - if os.path.exists (f'{mntdir}/etc/initramfs-tools/conf.d/resume'): - os.unlink ( f'{mntdir}/etc/initramfs-tools/conf.d/resume') - -#/** -# ogGrubAddOgLive num_disk num_part [ timeout ] [ offline ] -#@brief Crea entrada de menu grub para ogclient, tomando como paramentros del kernel los actuales del cliente. -#@param 1 Numero de disco -#@param 2 Numero de particion -#@param 3 timeout Segundos de espera para iniciar el sistema operativo por defecto (opcional) -#@param 4 offline configura el modo offline [offline|online] (opcional) -#@return (nada) -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_NOTFOUND No existe kernel o initrd en cache. -#@exception OG_ERR_NOTFOUND No existe archivo de configuracion del grub. -# /// FIXME: Solo para el grub instalado en MBR por Opengnsys, ampliar para más casos. -#*/ ## - -#/** -# ogGrubHidePartitions num_disk num_part -#@brief ver ogBootLoaderHidePartitions -#@see ogBootLoaderHidePartitions -#*/ ## - -#/** -# ogBurgHidePartitions num_disk num_part -#@brief ver ogBootLoaderHidePartitions -#@see ogBootLoaderHidePartitions -#*/ ## - -#/** -# ogBootLoaderHidePartitions num_disk num_part -#@brief Configura el grub/burg para que oculte las particiones de windows que no se esten iniciando. -#@param 1 Numero de disco -#@param 2 Numero de particion -#@param 3 Numero de disco de la partición de datos (no ocultar) -#@param 4 Numero de particion de datos (no ocultar) -#@return (nada) -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception No existe archivo de configuracion del grub/burg. -#*/ - -#/** -# ogGrubDeleteEntry num_disk num_part num_disk_delete num_part_delete -#@brief ver ogBootLoaderDeleteEntry -#@see ogBootLoaderDeleteEntry -#*/ - -#/** -# ogBurgDeleteEntry num_disk num_part num_disk_delete num_part_delete -#@brief ver ogBootLoaderDeleteEntry -#@see ogBootLoaderDeleteEntry -#*/ - -#/** -# ogRefindDeleteEntry num_disk_delete num_part_delete -#@brief ver ogBootLoaderDeleteEntry -#@see ogBootLoaderDeleteEntry -#*/ - -#/** -# ogBootLoaderDeleteEntry num_disk num_part num_part_delete -#@brief Borra en el grub las entradas para el inicio en una particion. -#@param 1 Numero de disco donde esta el grub -#@param 2 Numero de particion donde esta el grub -#@param 3 Numero del disco del que borramos las entradas -#@param 4 Numero de la particion de la que borramos las entradas -#@note Tiene que ser llamada desde ogGrubDeleteEntry, ogBurgDeleteEntry o ogRefindDeleteEntry -#@return (nada) -#@exception OG_ERR_FORMAT Use ogGrubDeleteEntry or ogBurgDeleteEntry. -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_NOTFOUND No existe archivo de configuracion del grub. -#*/ ## - -#/** -# ogBurgInstallMbr int_disk_GRUBCFG int_partition_GRUBCFG -#@param bolean_Check_Os_installed_and_Configure_2ndStage true | false[default] -#@brief Instala y actualiza el gestor grub en el MBR del disco duro donde se encuentra el fichero grub.cfg. Admite sistemas Windows. -#@param int_disk_SecondStage -#@param int_part_SecondStage -#@param bolean_Check_Os_installed_and_Configure_2ndStage true | false[default] -#@return -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_PARTITION Partición no soportada -#*/ ## - -#/** -# ogGrubDefaultEntry int_disk_GRUGCFG int_partition_GRUBCFG int_disk_default_entry int_npartition_default_entry -#@brief ver ogBootLoaderDefaultEntry -#@see ogBootLoaderDefaultEntry -#*/ ## - -#/** -# ogBurgDefaultEntry int_disk_BURGCFG int_partition_BURGCFG int_disk_default_entry int_npartition_default_entry -#@brief ver ogBootLoaderDefaultEntry -#@see ogBootLoaderDefaultEntry -#*/ ## - - -#/** -# ogRefindDefaultEntry int_disk_default_entry int_npartition_default_entry -#@brief ver ogBootLoaderDefaultEntry -#@see ogBootLoaderDefaultEntry -#*/ ## - -#/** -# ogBootLoaderDefaultEntry int_disk_CFG int_partition_CFG int_disk_default_entry int_npartition_default_entry -#@brief Configura la entrada por defecto de Burg -#@param int_disk_SecondStage -#@param int_part_SecondStage -#@param int_disk_default_entry -#@param int_part_default_entry -#@return -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_PARTITION Partición errónea o desconocida (ogMount). -#@exception OG_ERR_OUTOFLIMIT Param $3 no es entero. -#@exception OG_ERR_NOTFOUND Fichero de configuración no encontrado: burg.cfg. -#*/ ## - -#/** -# ogGrubOgliveDefaultEntry num_disk num_part -#@brief ver ogBootLoaderOgliveDefaultEntry -#@see ogBootLoaderOgliveDefaultEntry -#*/ ## - -#/** -# ogBurgOgliveDefaultEntry num_disk num_part -#@brief ver ogBootLoaderOgliveDefaultEntry -#@see ogBootLoaderOgliveDefaultEntry -#*/ ## - - -#/** -# ogRefindOgliveDefaultEntry -#@brief ver ogBootLoaderOgliveDefaultEntry -#@see ogBootLoaderOgliveDefaultEntry -#*/ ## - - -#/** -# ogBootLoaderOgliveDefaultEntry -#@brief Configura la entrada de ogLive como la entrada por defecto de Burg. -#@param int_disk_SecondStage -#@param int_part_SecondStage -#@return -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_PARTITION Partición errónea o desconocida (ogMount). -#@exception OG_ERR_NOTFOUND Fichero de configuración no encontrado: burg.cfg. -#@exception OG_ERR_NOTFOUND Entrada de OgLive no encontrada en burg.cfg. -#*/ ## - - -#/** -# ogGrubSecurity int_disk_GRUBCFG int_partition_GRUBCFG [user] [password] -#@brief Configura grub.cfg para que sólo permita editar entrada o acceder a línea de comandos al usuario especificado -#@param int_disk_SecondStage -#@param int_part_SecondStage -#@param user (default root) -#@param password (default "", no puede entrar) -#@return (nada) -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar (ogMount). -#@exception OG_ERR_NOTFOUND No encuentra archivo de configuración del grub. -#*/ ## - - -#/** -# ogGrubSetTheme num_disk num_part str_theme -#@brief ver ogBootLoaderSetTheme -#@see ogBootLoaderSetTheme -#*/ ## - -#/** -# ogBurgSetTheme num_disk num_part str_theme -#@brief ver ogBootLoaderSetTheme -#@see ogBootLoaderSetTheme -#*/ ## - - -#/** -# ogRefindSetTheme str_theme -#@brief ver ogBootLoaderSetTheme -#@see ogBootLoaderSetTheme -#*/ ## - - -#/** -# ogBootLoaderSetTheme -#@brief asigna un tema al BURG -#@param int_disk_SecondStage -#@param int_part_SecondStage -#@param str_theme_name -#@return -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_PARTITION Partición errónea o desconocida (ogMount). -#@exception OG_ERR_NOTFOUND Fichero de configuración no encontrado: grub.cfg burg.cfg refind.conf. -#@exception OG_ERR_NOTFOUND Entrada deltema no encontrada en burg.cfg. -#@exception OG_ERR_NOTFOUND Fichero de configuración del tema no encontrado: theme.conf (sólo refind). -#@note El tema debe situarse en OGLIB/BOOTLOADER/themes -#*/ ## - -#/** -# ogGrubSetAdminKeys num_disk num_part str_theme -#@brief ver ogBootLoaderSetTheme -#@see ogBootLoaderSetTheme -#*/ ## - -#/** -# ogBurgSetAdminKeys num_disk num_part str_bolean -#@brief ver ogBootLoaderSetAdminKeys -#@see ogBootLoaderSetAdminKeys -#*/ ## - - - -#/** -# ogBootLoaderSetAdminKeys -#@brief Activa/Desactica las teclas de administracion -#@param int_disk_SecondStage -#@param int_part_SecondStage -#@param Boolean TRUE/FALSE -#@return -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_PARTITION Partición errónea o desconocida (ogMount). -#@exception OG_ERR_NOTFOUND Fichero de configuración no encontrado: grub.cfg burg.cfg. -#@exception OG_ERR_NOTFOUND Entrada deltema no encontrada en burg.cfg. -#*/ ## - - - -#/** -# ogGrubSetTimeOut num_disk num_part int_timeout_seconds -#@brief ver ogBootLoaderSetTimeOut -#@see ogBootLoaderSetTimeOut -#*/ ## - -#/** -# ogBurgSetTimeOut num_disk num_part str_bolean -#@brief ver ogBootLoaderSetTimeOut -#@see ogBootLoaderSetTimeOut -#*/ ## - - -#/** -# ogRefindSetTimeOut int_timeout_second -#@brief ver ogBootLoaderSetTimeOut -#@see ogBootLoaderSetTimeOut -#*/ ## - -#/** -# ogBootLoaderSetTimeOut -#@brief Define el tiempo (segundos) que se muestran las opciones de inicio -#@param int_disk_SecondStage -#@param int_part_SecondStage -#@param int_timeout_seconds -#@return -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_PARTITION Partición errónea o desconocida (ogMount). -#@exception OG_ERR_NOTFOUND Fichero de configuración no encontrado: grub.cfg burg.cfg. -#@exception OG_ERR_NOTFOUND Entrada deltema no encontrada en burg.cfg. -#*/ ## - - -#/** -# ogGrubSetResolution num_disk num_part int_resolution -#@brief ver ogBootLoaderSetResolution -#@see ogBootLoaderSetResolution -#*/ ## - -#/** -# ogBurgSetResolution num_disk num_part str_bolean -#@brief ver ogBootLoaderSetResolution -#@see ogBootLoaderSetResolution -#*/ ## - - - -#/** -# ogBootLoaderSetResolution -#@brief Define la resolucion que usuara el thema del gestor de arranque -#@param int_disk_SecondStage -#@param int_part_SecondStage -#@param str_resolution (Opcional) -#@return -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_PARTITION Partición errónea o desconocida (ogMount). -#@exception OG_ERR_NOTFOUND Fichero de configuración no encontrado: grub.cfg burg.cfg. -#*/ ## - - - - -#/** -# ogBootLoaderSetResolution -#@brief Define la resolucion que usuara el thema del gestor de arranque -#@param int_resolution1 -#@param int_resolution2 (Opcional) -#@return -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_PARTITION Partición errónea o desconocida (ogMount). -#@exception OG_ERR_NOTFOUND Fichero de configuración no encontrado: grub.cfg burg.cfg. -#*/ ## - -# ogRefindInstall bool_autoconfig -#@brief Instala y actualiza el gestor rEFInd en la particion EFI -#@param bolean_Check__auto_config true | false[default] -#@return -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_NOTFOUND No se encuentra la partición ESP. -#@exception OG_ERR_NOTFOUND No se encuentra shimx64.efi.signed. -#@exception OG_ERR_NOTFOUND No se encuentra refind-install o refind en OGLIB -#@exception OG_ERR_PARTITION No se puede montar la partición ESP. -#@note Refind debe estar instalado en el ogLive o compartido en OGLIB -#*/ ## - -#/** -# ogGrub4dosInstallMbr int_ndisk -#@brief Genera un nuevo Codigo de arranque en el MBR del disco indicado, compatible con los SO tipo Windows, Linux. -#@param int_ndisk nº de orden del disco -#@param int_ndisk nº de orden del particion -#@return -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_NOTFOUND Tipo de partición desconocido o no se puede montar. -#@exception OG_ERR_NOTBIOS Equipo no firmware BIOS legacy -#@exception OG_ERR_NOMSDOS Disco duro no particioniado en modo msdos -#@exception OG_ERR_NOTWRITE Particion no modificable. -#*/ ## diff --git a/client/lib/engine/bin/Cache.lib b/client/lib/engine/bin/Cache.lib new file mode 100755 index 0000000..cacba40 --- /dev/null +++ b/client/lib/engine/bin/Cache.lib @@ -0,0 +1,439 @@ +#!/bin/bash +#/** +#@file Cache.lib +#@brief Librería o clase Cache +#@class Cache +#@brief Funciones para gestión de la caché local de disco. +#@version 1.1.1 +#@warning License: GNU GPLv3+ +#*/ + + +#/** +# ogCreateCache [int_ndisk] int_partsize +#@brief Define la caché local, por defecto en partición 4 del disco 1. +#@param int_ndisk numero de disco donde crear la cache, si no se indica es el 1 por defecto +#@param int_npart número de partición (opcional, 4 por defecto) +#@param int_partsize tamaño de la partición (en KB) +#@return (nada, por determinar) +#@exception OG_ERR_FORMAT formato incorrecto. +#@note Requisitos: sfdisk, parted, awk, sed +#@warning El tamaño de caché debe estar entre 50 MB y la mitad del disco. +#@warning La caché no puede solaparse con las particiones de datos. +#@version 0.9.1 - Definición de caché local. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2010/03/09 +#@version 0.9.2 - Corrección definición de límites. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2010/06/01 +#@version 1.0.4 - Soporte para discos GPT. +#@author Universidad de Huelva +#@date 2012/03/13 +#@version 1.0.5 - Posibilidad de crear la cache en cualquier disco duro +#@author Universidad de Huelva +#@date 2012/09/18 +#@version 1.1.0 - Posibilidad de crear la caché en cualquier partición. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2016/05/25 +#@version 1.1.0 - Soporte discos con sectores de 4k +#@date 2017/01/09 +#@version 1.0.6b - Al crear las particiones ordenamos los dispositivos en el fichero auxiliar. +#@author Irina Gomez, ETSII Universidad de Sevilla +#@date 2017/01/09 +#*/ ## +function ogCreateCache () +{ +# Variables locales. +local FINDCACHE IOSIZE NDSK SIZECACHE PART DISK START END ENDPREVPART SIZE MINSIZE MAXSIZE +local PTTYPE ID TMPFILE NVME_PREFIX +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME [int_ndisk [int_npart]] int_partsize" \ + "$FUNCNAME 10000000" "$FUNCNAME 1 10000000" "$FUNCNAME 1 4 10000000" + return +fi +# Si se recibe un parametro, sera el tamano de la cache +case $# in + 1) # Error, si no es un entero positivo + [[ $1 =~ ^[1-9][0-9]*$ ]] || ogRaiseError $OG_ERR_FORMAT "$1" || return $? + NDSK=1 + PART=4 + SIZECACHE=$1 + ;; + 2) # Error, si no son enteros positivos + [[ $1 =~ ^[1-9][0-9]*$ ]] || ogRaiseError $OG_ERR_FORMAT "$1" || return $? + [[ $2 =~ ^[1-9][0-9]*$ ]] || ogRaiseError $OG_ERR_FORMAT "$2" || return $? + NDSK=$1 + PART=4 + SIZECACHE=$2 + ;; + 3) # Error, si no son enteros positivos + [[ $1 =~ ^[1-9][0-9]*$ ]] || ogRaiseError $OG_ERR_FORMAT "$1" || return $? + [[ $2 =~ ^[1-9][0-9]*$ ]] || ogRaiseError $OG_ERR_FORMAT "$2" || return $? + [[ $3 =~ ^[1-9][0-9]*$ ]] || ogRaiseError $OG_ERR_FORMAT "$3" || return $? + NDSK=$1 + PART=$2 + SIZECACHE=$3 + ;; + *) ogRaiseError $OG_ERR_FORMAT + return $? + ;; +esac + +TMPFILE=/tmp/sfdisk$$ +DISK=$(ogDiskToDev $NDSK) || return $? + + # PATCH Para discos nvme la particion debe ser p1, p2, etc...en lugar de 1,2, sino falla sfdisk +NVME_PREFIX="" +if [[ $DISK == *"nvme"* ]]; then + NVME_PREFIX="p" +fi + + +END=$[$(ogGetLastSector $NDSK 2>/dev/null)] # Sector final del disco. +SIZE=$[$SIZECACHE*2] # Tamaño en sectores de 512 B. +# Inicio partición cache según el disco tenga sectores de 4k o menores +IOSIZE=$(fdisk -l $DISK | awk '/I\/O/ {print $4}') +if [ $IOSIZE -eq 4096 ]; then + END=$[$END-8192] + START=$[END-SIZE+2048-(END-SIZE)%2048] +else + START=$[END-SIZE+1] +fi +ENDPREVPART=$[$(ogGetLastSector $NDSK $[PART-1] 2>/dev/null)] +# Error si tamaño no está entre límites permitidos o si se solapa con la partición anterior. +MINSIZE=25000 # Error de formateo si tamaño < 50 MB. +MAXSIZE=$END # Para restringir tamaño > mitad del disco: MAXSIZE=$[END/2] +if [ $SIZE -lt $MINSIZE -o $SIZE -gt $MAXSIZE -o $START -le $ENDPREVPART ]; then + ogRaiseError $OG_ERR_FORMAT "$1" || return $? +fi + +# Desmontar todos los sistemas de archivos del disco. +ogUnmountAll $NDSK 2>/dev/null +# Definir particiones y notificar al kernel. +# En el caso de ser disco GPT, de momento se borra la particion y se vuelve a crear, +# por lo que se pierden los datos. +PTTYPE=$(ogGetPartitionTableType $NDSK) +if [ -z "$PTTYPE" ]; then + PTTYPE="MSDOS" # Por defecto para discos vacíos. + ogCreatePartitionTable $NDSK $PTTYPE +fi +case "$(ogGetPartitionTableType $NDSK)" in + GPT) + # Si la tabla de particiones no es valida, volver a generarla. + [ ! $(sgdisk -p $DISK &>/dev/null) ] || echo -e "2\nw\nY\n" | gdisk $DISK + # Si existe la cache se borra previamente + [ -n "$(ogFindCache)" ] && ogDeleteCache + # Capturamos el codigo de particion GPT para cache + # PATCH - Cuando es GPT, la particion con codigo CACHE (CA00) no existe y no puede crearse, se cambia por LINUX (8300) + ID=$(ogTypeToId LINUX GPT) + sgdisk $DISK -n$PART:$START:$END -c$PART:CACHE -t$PART:$ID 2>/dev/null + ;; + MSDOS) + # Si la tabla de particiones no es valida, volver a generarla. + parted -s $DISK print &>/dev/null || fdisk $DISK <<< "w" + # Definir particiones y notificar al kernel. + ID=$(ogTypeToId CACHE MSDOS) + # Salvamos la configuración de las particiones e incluimos la cache. + trap "rm -f $TMPFILE" 1 2 3 9 15 + sfdisk --dump $DISK | grep -v $DISK$PART > $TMPFILE + echo "$DISK$NVME_PREFIX$PART : start= $START, size= $SIZE, Id=$ID" >> $TMPFILE + # Ordenamos las líneas de los dispositivos + UNIT=$(grep unit $TMPFILE) + grep ^/dev $TMPFILE|sort -o $TMPFILE + sed -i "1i $UNIT\n" $TMPFILE + # Guardamos nueva configuración en el disco. + sfdisk --no-reread $DISK < $TMPFILE + rm -f $TMPFILE + ;; +esac +# Actualiza la tabla de particiones en el kernel. +ogUpdatePartitionTable +} + + +#/** +# ogDeleteCache +#@brief Elimina la partición de caché local. +#@return (nada, por determinar) +#@exception OG_ERR_FORMAT formato incorrecto. +#@note Requisitos: fdisk, sgdisk, partprobe +#@version 0.91 - Definición de caché local. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2010/03/11 +#@version 1.0.4 - Soporte para discos GPT. +#@author Universidad de Huelva +#@date 2012/03/13 +#@version 1.0.6b - llamada correcta a ogUpdatePartitionTable +#@author Antonio Doblas Universidad de Málaga +#@date 2016/11/16 +#@version 1.1.0 - Sustituir "sfdisk" por "fdisk" para discos MSDOS. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2016/05/25 +#*/ ## +function ogDeleteCache () +{ +# Variables locales. +local NDISK NPART DISK +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME" + return +fi +# Error si no se encuentra partición de caché. +read NDISK NPART <<<"$(ogFindCache)" +[ -n "$NDISK" -a -n "$NPART" ] || ogRaiseError $OG_ERR_PARTITION "$MSG_NOCACHE" || return $? +DISK=$(ogDiskToDev $NDISK) + +# Desmontar todos los sistemas de archivos del disco. +ogUnmountAll $NDISK 2>/dev/null +case "$(ogGetPartitionTableType $NDISK)" in + GPT) + # Si la tabla de particiones no es valida, volver a generarla. + [ ! $(sgdisk -p $DISK 2>&1 >/dev/null) ] || echo -e "2\nw\nY\n" | gdisk $DISK + sgdisk $DISK -d$NPART 2>/dev/null + ;; + MSDOS) + # Si la tabla de particiones no es valida, volver a generarla. + parted -s $DISK print &>/dev/null || fdisk $DISK <<< "w" + # Eliminar la partición de caché. + echo -e "d\n$NPART\nw" | fdisk $DISK 2>/dev/null + ;; +esac +# Borrar etiqueta de la caché. +rm -f /dev/disk/by-label/CACHE +#Actualiza la tabla de particiones en el kernel. +ogUpdatePartitionTable $NDISK +} + + +#/** +# ogFindCache +#@brief Detecta la partición caché local. +#@param No requiere parametros +#@return int_ndisk int_npart - devuelve el par nº de disco-nº de partición . +#@warning Si no hay cache no devuelve nada +#@version 0.1 - Integracion para Opengnsys - EAC: FindCache() en ATA.lib - HIDRA: DetectarCache.sh +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@Date 2008/06/19 +#@author Antonio J. Doblas Viso. Universidad de Malaga +#@Date 2008/10/27 +#@version 0.91 - Adaptacion a la cache local de OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2010/03/16 +#@version 1.0.5 - Obtener caché en discos GPT. +#@author Alberto García, Universidad de Málaga y Ramon Gomez, ETSII Universidad de Sevilla +#@date 2014/05/28 +#*/ ## +function ogFindCache () +{ +# Variables locales +local DISK PART +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME" "$FUNCNAME => 1 4" + return +fi +# Obtener el dispositivo del sistema de archivos etiquetado como "CACHE". +PART=$(blkid -L "CACHE") +# En discos nvme con particiones GPT la partición se detecta usando el tag PARTLABEL +PART=${PART:-$(blkid -t PARTLABEL=CACHE | awk -F: '{print $1}')} +# Si no se detecta, obtener particiones marcadas de tipo caché en discos MSDOS. +PART=${PART:-$(sfdisk -l 2>/dev/null | awk '$6~/ca|a7/ {print $1}')} + +# Por último revisar todos los discos GPT y obtener las particiones etiquetadas como caché. +if [ -z "$PART" ]; then + for DISK in $(ogDiskToDev); do + # Nota: se añade espacio separador solo si existe valor previo. + PART="${PART:+"$PART "}$(sgdisk -p $DISK 2>/dev/null | awk -v d=$DISK '$7~/CACHE/ {printf "%s%s",d,$1;}')" + done +fi + +# Devolver número de disco y número de partición de la 1ª partición encontrada. +ogDevToDisk ${PART%% *} 2>/dev/null +} + + +#/** +# ogFormatCache +#@brief Formatea el sistema de ficheros para la caché local. +#@return (por determinar) +#@warning Prueba con formato Reiser. +#@attention +#@note El sistema de archivos de la caché se queda montado. +#@version 0.1 - Integracion para Opengnsys - EAC: FormatCache() en ATA.lib +#@author Antonio J. Doblas Viso. Universidad de Malaga +#@date 2008/10/27 +#@version 0.91 - Creacion cache local. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2010-03-11 +#@version 1.1.0 - llamada a updateBootCache. +#@author Antonio J. Doblas Viso. Universidad de Malaga +#@date 2018-01-21 + +#*/ ## +function ogFormatCache () +{ +# Variables locales. +local DEV MNTDIR OPTIONS +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME" + return +fi + +# Error si no hay definida partición de caché. +DEV=$(ogFindCache) || ogRaiseError $OG_ERR_PARTITION "$MSG_NOCACHE" || return $? +DEV=$(ogDiskToDev $DEV) || return $? + +# Formatear sistema de ficheros. +ogUnmountCache 2>/dev/null +OPTIONS="extent,large_file" +[[ $(uname -r) =~ ^5 ]] && OPTIONS+=",uninit_bg,^metadata_csum,^64bit" +mkfs.ext4 -q -F $DEV -L "CACHE" -O "$OPTIONS" 2>/dev/null || ogRaiseError $OG_ERR_PARTITION "CACHE" || return $? + +# Crear estructura básica. +MNTDIR=$(ogMountCache) +mkdir -p $MNTDIR/$OGIMG + +# Incluir kernel e Initrd del ogLive +updateBootCache 2>&1>/dev/null +} + + +#/** +# ogGetCacheSize +#@brief Devuelve el tamaño definido para la partición de caché. +#@return int_partsize tamaño de la partición (en KB) +#@exception OG_ERR_PARTITION No existe partición de caché. +#@version 0.1 - Integracion para Opengnsys - EAC: InfoCache() en FileSystem.lib +#@author Antonio J. Doblas Viso. Universidad de Malaga +#@date 2008/10/27 +#@version 0.91 - Definicion de cache local. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2010/03/09 +#*/ ## +function ogGetCacheSize () +{ +# Variables locales +local PART + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME" "$FUNCNAME => 10000000" + return +fi +# Error si no se encuentra partición de caché. +PART=$(ogFindCache) || ogRaiseError $OG_ERR_PARTITION "$MSG_NOCACHE" || return $? + +# Devuelve tamaño de la partición de caché. +ogGetPartitionSize $PART +} + + +#/** +# ogGetCacheSpace +#@brief Devuelve el espacio de disco disponible para la partición de caché. +#@return int_size tamaño disponible (en KB) +#@note El espacio disponible es el que hay entre el límite superior de la partición 3 del disco 1 y el final de dicho disco, y no puede ser superior a la mitad de dicho disco. +#@version 0.1 - Integracion para Opengnsys - EAC: InfoCache() en FileSystem.lib +#@author Antonio J. Doblas Viso. Universidad de Malaga +#@date 2008/10/27 +#@version 0.91 - Definicion de cache local. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2010/03/09 +#@version 1.0.5 - Uso de ogFindCache para detectar disco y particion +#@author Universidad de Huelva +#@date 2012/09/18 +#*/ ## +function ogGetCacheSpace () +{ +# Variables locales. +local NDISK DISK NPART SECTORS CYLS ENDPART3 +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME" "$FUNCNAME => 23165386" + return +fi +# Parche UHU para usar ogFindCache en lugar de 1 +# Error si no se encuentra partición de caché. +read NDISK NPART <<<"$(ogFindCache)" +[ -n "$NDISK" -a -n "$NPART" ] || ogRaiseError $OG_ERR_PARTITION "$MSG_NOCACHE" || return $? +DISK=$(ogDiskToDev $NDISK) || return $? + +SECTORS=$(awk -v D=${DISK#/dev/} '{if ($4==D) {print $3*2}}' /proc/partitions) +CYLS=$(sfdisk -g $DISK | cut -f2 -d" ") +SECTORS=$[SECTORS/CYLS*CYLS-1] +ENDPART3=$(sfdisk -uS -l $DISK | awk -v P="${DISK}3" '{if ($1==P) print $3}') +# Mostrar espacio libre en KB (1 KB = 2 sectores) +if [ $ENDPART3 -gt $[SECTORS/2] ]; then + echo $[(SECTORS-ENDPART3)/2] +else + echo $[SECTORS/4] +fi +} + + +#/** +# ogMountCache +#@brief Monta la partición Cache y exporta la variable $OGCAC +#@param sin parametros +#@return path_mountpoint - Punto de montaje del sistema de archivos de cache. +#@warning Salidas de errores no determinada +#@version 0.1 - Integracion para Opengnsys - EAC: MountCache() en FileSystem.lib - HIDRA: MontarCache.sh +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2008/06/19 +#@author Antonio J. Doblas Viso. Universidad de Malaga +#@Date 2008/10/27 +#@version 0.91 - Adaptacion a la cache local de OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2010/03/16 +#@version 1.0 - Correccion multiples montajes de cache. +#@author Antonio J. Doblas Viso, Universidad de Malaga +#@date 2011/02/24 +#*/ ## +function ogMountCache () +{ +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME" "$FUNCNAME ==> /mnt/sda4" + return +fi + +ogMountFs $(ogFindCache) 2>/dev/null || ogRaiseError $OG_ERR_PARTITION "$MSG_NOCACHE" || return $? +} + + +#/** +# ogUnmountCache +#@brief Desmonta la particion Cache y elimina la variable $OGCAC +#@param sin parametros +#@return nada +#@warning Salidas de errores no determinada +#@version 0.1 - Integracion para Opengnsys - EAC: UmountCache() en FileSystem.lib +#@author Antonio J. Doblas Viso. Universidad de Malaga +#@Date 2008/10/27 +#@version 0.91 - Adaptacion a la cache local de OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2010/03/16 +#@version 1.0 - Correccion multiples montajes de cache. +#@author Antonio J. Doblas Viso, Universidad de Malaga +#@date 2011/02/24 +#*/ ## +function ogUnmountCache () +{ +# Variables locales. +local CACHE +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME" + return +fi + +CACHE=$(ogFindCache) || ogRaiseError $OG_ERR_PARTITION "$MSG_NOCACHE" +ogIsMounted $CACHE || return 0 +ogUnmountFs $CACHE +# Borrar enlace simbólico de /mnt/ParticiónCache. +rm -f $(ogDiskToDev $CACHE | sed 's/dev/mnt/') +} + diff --git a/client/lib/engine/bin/CacheLib.py b/client/lib/engine/bin/CacheLib.py deleted file mode 100755 index 5e8d9d5..0000000 --- a/client/lib/engine/bin/CacheLib.py +++ /dev/null @@ -1,361 +0,0 @@ -import os -import re -import subprocess -import shutil -import sys -import platform - -import ogGlobals -import SystemLib -import DiskLib -import FileSystemLib -import CacheLib - -#/** -# ogCreateCache [int_ndisk] int_partsize -#@brief Define la caché local, por defecto en partición 4 del disco 1. -#@param int_ndisk numero de disco donde crear la cache, si no se indica es el 1 por defecto -#@param int_npart número de partición (opcional, 4 por defecto) -#@param int_partsize tamaño de la partición (en KB) -#@return (nada, por determinar) -#@exception OG_ERR_FORMAT formato incorrecto. -#@note Requisitos: sfdisk, parted, awk, sed -#@warning El tamaño de caché debe estar entre 50 MB y la mitad del disco. -#@warning La caché no puede solaparse con las particiones de datos. -#*/ ## -def ogCreateCache (ndsk=1, part=4, sizecache=0): - if not sizecache: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, '') - return None - sizecache = int (sizecache) - - DISK = DiskLib.ogDiskToDev (ndsk) - if not DISK: return None - - # PATCH Para discos nvme la particion debe ser p1, p2, etc...en lugar de 1,2, sino falla sfdisk - NVME_PREFIX = '' - if 'nvme' in DISK: - NVME_PREFIX = 'p' - - END = DiskLib.ogGetLastSector (ndsk) - SIZE = 2 * sizecache -# Inicio partición cache según el disco tenga sectores de 4k o menores - IOSIZE = 0 - fdisk_out = subprocess.run (['fdisk', '-l', DISK], capture_output=True, text=True).stdout - for l in fdisk_out.splitlines(): - items = l.split() - if len(items) < 4: continue - if 'I/O' == items[0]: - IOSIZE = int (items[3]) - break - START = 0 - if 4096 == IOSIZE: - END -= 8192 - START = END - SIZE + 2048 - (END-SIZE)%2048 - else: - START = END - SIZE + 1 - - ENDPREVPART = None - i = 1 - while True: - prev_part = part - i - if prev_part <= 0: break - ENDPREVPART = DiskLib.ogGetLastSector (ndsk, prev_part) - if ENDPREVPART: break - i += 1 - if not ENDPREVPART: - ENDPREVPART=0 - #SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, ndsk) - #return None -# Error si tamaño no está entre límites permitidos o si se solapa con la partición anterior. - MINSIZE = 25000 - MAXSIZE = END - if SIZE < MINSIZE or SIZE > MAXSIZE or START < ENDPREVPART: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, ndsk) - return None - -# Desmontar todos los sistemas de archivos del disco. - FileSystemLib.ogUnmountAll (ndsk) -# Definir particiones y notificar al kernel. -# En el caso de ser disco GPT, de momento se borra la particion y se vuelve a crear, -# por lo que se pierden los datos. - pttype = DiskLib.ogGetPartitionTableType (ndsk) - if not pttype: - pttype = 'MSDOS' - DiskLib.ogCreatePartitionTable (ndsk, pttype) - - get_ptt = DiskLib.ogGetPartitionTableType (ndsk) - if 'GPT' == get_ptt: - # Si la tabla de particiones no es valida, volver a generarla. - if subprocess.run (['sgdisk', '-p', DISK]).returncode: - subprocess.run (['gdisk', DISK], input='2\nw\nY\n', text=True) - # Si existe la cache se borra previamente - if ogFindCache(): ogDeleteCache() - # Capturamos el codigo de particion GPT para cache - # PATCH - Cuando es GPT, la particion con codigo CACHE (CA00) no existe y no puede crearse, se cambia por LINUX (8300) - ID = DiskLib.ogTypeToId ('LINUX', 'GPT') - subprocess.run (['sgdisk', DISK, f'-n{part}:{START}:{END}', f'-c{part}:CACHE', f'-t{part}:{ID}']) - elif 'MSDOS' == get_ptt: - # Si la tabla de particiones no es valida, volver a generarla. - if subprocess.run (['parted', '-s', DISK, 'print']).returncode: - subprocess.run (['fdisk', DISK], input='w\n', text=True) - # Definir particiones y notificar al kernel. - ID = DiskLib.ogTypeToId ('CACHE', 'MSDOS') - # Salvamos la configuración de las particiones e incluimos la cache. - tmp = subprocess.run (['sfdisk', '--dump', DISK], capture_output=True, text=True).stdout.splitlines() - tmp = [ x for x in tmp if f'{DISK}{part}' not in x ] - tmp.append (f'{DISK}{NVME_PREFIX}{part} : start= {START}, size= {SIZE}, Id={ID}') - # Ordenamos las líneas de los dispositivos - UNIT = [ x for x in tmp if 'unit' in x ][0] - tmp = sorted ([ x for x in tmp if re.match ('^/dev', x) ]) - tmp = [UNIT, ''] + tmp - # Guardamos nueva configuración en el disco. - i = '\n'.join(tmp) - subprocess.run (['sfdisk', '--no-reread', DISK], input=i, text=True) -# Actualiza la tabla de particiones en el kernel. - DiskLib.ogUpdatePartitionTable() - - - -#/** -# ogDeleteCache -#@brief Elimina la partición de caché local. -#@return (nada, por determinar) -#@exception OG_ERR_FORMAT formato incorrecto. -#@note Requisitos: fdisk, sgdisk, partprobe -#*/ ## -def ogDeleteCache(): - cachepart = ogFindCache() - if not cachepart: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, ogGlobals.lang.MSG_NOCACHE) - return None - - ndisk, npart = cachepart.split() - disk = DiskLib.ogDiskToDev (ndisk) - -# Desmontar todos los sistemas de archivos del disco. - FileSystemLib.ogUnmountAll (ndisk) - - ptt = DiskLib.ogGetPartitionTableType (ndisk) - if 'GPT' == ptt: - # Si la tabla de particiones no es valida, volver a generarla. - if subprocess.run (['sgdisk', '-p', disk]).returncode: - subprocess.run (['gdisk', disk], input='2\nw\nY\n', text=True) - subprocess.run (['sgdisk', disk, f'-d{npart}']) - elif 'MSDOS' == ptt: - # Si la tabla de particiones no es valida, volver a generarla. - if subprocess.run (['parted', '-s', disk, 'print']).returncode: - subprocess.run (['fdisk', disk], input='w', text=True) - # Eliminar la partición de caché. - subprocess.run (['fdisk', disk], input=f'd\n{npart}\nw', text=True) -# Borrar etiqueta de la caché. - if os.path.exists ('/dev/disk/by-label/CACHE'): - os.unlink ('/dev/disk/by-label/CACHE') -#Actualiza la tabla de particiones en el kernel. - DiskLib.ogUpdatePartitionTable() - -#/** -# ogFindCache -#@brief Detecta la partición caché local. -#@param No requiere parametros -#@return int_ndisk int_npart - devuelve el par nº de disco-nº de partición . -#@warning Si no hay cache no devuelve nada -#*/ ## -def ogFindCache(): - # Obtener el dispositivo del sistema de archivos etiquetado como "CACHE". - PART = subprocess.run (['blkid', '-L', 'CACHE'], capture_output=True, text=True).stdout.strip() - - # En discos nvme con particiones GPT la partición se detecta usando el tag PARTLABEL - if not PART: - out = subprocess.run (['blkid', '-t', 'PARTLABEL=CACHE'], capture_output=True, text=True).stdout.strip() - PART = out.split (':')[0] - - # Si no se detecta, obtener particiones marcadas de tipo caché en discos MSDOS. - if not PART: - out = subprocess.run (['sfdisk', '-l'], capture_output=True, text=True).stdout.splitlines() - for l in out: - elems = l.split (maxsplit=5) - if 6 > len (elems): continue - if 'ca' in elems[5] or 'a7' in elems[5]: - PART=elems[0] - break - - # Por último revisar todos los discos GPT y obtener las particiones etiquetadas como caché. - if not PART: - PART = '' - for d in DiskLib.ogDiskToDev(): - out = subprocess.run (['sgdisk', '-p', d], capture_output=True, text=True).stdout.splitlines() - for l in out: - elems = l.split (maxsplit=6) - if 7 > len (elems): continue - if 'CACHE' in elems[6]: - p = 'p' if 'nvme' in d else '' - PART += f' {d}{p}{elems[0]}' - - if not PART: return - return DiskLib.ogDevToDisk (PART.split()[0]) # usar la 1ª partición encontrada. - - -#/** -# ogFormatCache -#@brief Formatea el sistema de ficheros para la caché local. -#@return (por determinar) -#@warning Prueba con formato Reiser. -#@attention -#@note El sistema de archivos de la caché se queda montado. -#*/ ## -def ogFormatCache(): - cachepart = ogFindCache() - if cachepart is None: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, ogGlobals.lang.MSG_NOCACHE) - return - - cachepart = cachepart.split() - disk = DiskLib.ogDiskToDev (cachepart[0], cachepart[1]) - if not disk: return - - ogUnmountCache() - options = "extent,large_file" - if re.match("^5", platform.release()): - options += ",uninit_bg,^metadata_csum,^64bit" - - try: - subprocess.run(["mkfs.ext4", "-q", "-F", disk, "-L", "CACHE", "-O", options], check=True) - except subprocess.CalledProcessError as e: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, "CACHE") - return - - # Crear estructura básica. - mntdir = ogMountCache() - j = '/'.join ([mntdir, ogGlobals.OGIMG]) ## os.path.join doesn't work: "If a segment […] is an absolute path, all previous segments are ignored" - #print (f'cucu mntdir ({mntdir}) OGIMG ({ogGlobals.OGIMG}) j ({j})') - os.makedirs (j, exist_ok=True) - - # Incluir kernel e Initrd del ogLive - ## como lo llamo sin especificar el path entero? - #subprocess.run (['scripts/updateBootCache.py']) ## TODO - - -#/** -# ogGetCacheSize -#@brief Devuelve el tamaño definido para la partición de caché. -#@return int_partsize tamaño de la partición (en KB) -#@exception OG_ERR_PARTITION No existe partición de caché. -#*/ ## -def ogGetCacheSize(): - cachepart = ogFindCache() - if cachepart is None: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, ogGlobals.lang.MSG_NOCACHE) - return None - - disk, par = cachepart.split() - return DiskLib.ogGetPartitionSize (disk, par) - -#/** -# ogGetCacheSpace -#@brief Devuelve el espacio de disco disponible para la partición de caché. -#@return int_size tamaño disponible (en KB) -#@note El espacio disponible es el que hay entre el límite superior de la partición 3 del disco 1 y el final de dicho disco, y no puede ser superior a la mitad de dicho disco. -#*/ ## -def ogGetCacheSpace(): - cachepart = ogFindCache() - if not cachepart: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, ogGlobals.lang.MSG_NOCACHE) - return None - cachepart = cachepart.split() - - disk = DiskLib.ogDiskToDev (cachepart[0]) - if not disk: - return None - - sectors = 0 - disk_bn = os.path.basename (disk) - with open ('/proc/partitions', 'r') as fd: - proc_parts = fd.read() - for l in proc_parts.splitlines(): - items = l.split() - if len(items) < 4: continue - if items[3] == disk_bn: - sectors = 2 * int (items[2]) - if not sectors: return None - - sfdisk_out = subprocess.run (['sfdisk', '-g', disk], capture_output=True, text=True).stdout - cyls = int (sfdisk_out.split()[1]) - sectors = sectors/cyls * cyls - 1 - - ## the original code has a hard dependency on the existence of a third partition - ## if the disk has sda1, sda2 and sda4, the code fails. - ## this is an improved version - endpart3 = 0 - for trypart in [3, 2, 1]: - sfdisk_out = subprocess.run (['sfdisk', '-uS', '-l', disk], capture_output=True, text=True).stdout - for l in sfdisk_out.splitlines(): - items = l.split() - if len(items) < 6: continue - if f'{disk}{trypart}' == items[0]: - endpart3 = int (items[2]) - break - if endpart3: break - if not endpart3: return None - -# Mostrar espacio libre en KB (1 KB = 2 sectores) - if endpart3 > sectors // 2: - return (sectors - endpart3) // 2 - else: - return sectors // 4 - - -#/** -# ogMountCache -#@brief Monta la partición Cache y exporta la variable $OGCAC -#@param sin parametros -#@return path_mountpoint - Punto de montaje del sistema de archivos de cache. -#@warning Salidas de errores no determinada -#*/ ## -def ogMountCache(): - c = ogFindCache() - if not c: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, ogGlobals.lang.MSG_NOCACHE) - return None - - c = c.split() - m = FileSystemLib.ogMountFs (c[0], c[1]) - if not m: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, ogGlobals.lang.MSG_NOCACHE) - return None - return m - - -#/** -# ogUnmountCache -#@brief Desmonta la particion Cache y elimina la variable $OGCAC -#@param sin parametros -#@return nada -#@warning Salidas de errores no determinada -#*/ ## -def ogUnmountCache(): - cachepart = ogFindCache() - if cachepart is None: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, ogGlobals.lang.MSG_NOCACHE) - return - - cachepart = cachepart.split() - if not FileSystemLib.ogIsMounted (cachepart[0], cachepart[1]): return True - FileSystemLib.ogUnmountFs (cachepart[0], cachepart[1]) - - # Eliminar el enlace simbólico de /mnt/ParticiónCache. - dev = DiskLib.ogDiskToDev (cachepart[0], cachepart[1]) - dev = dev.replace ('dev', 'mnt') - if os.path.exists (dev): os.remove (dev) - - -#/** -# initCache -#@brief Simplemente llama al script initCache -#@brief Es necesario tener una función para poder pasársela a ogExecAndLog -#@param los mismos parametros que initCache -#@return lo mismo que devuelve initCache -#*/ ## -def initCache (*args): - p = subprocess.run (['/opt/opengnsys/images/nati/client/shared/scripts/initCache.py'] + list(args)) - return p.returncode diff --git a/client/lib/engine/bin/Disk.lib b/client/lib/engine/bin/Disk.lib new file mode 100755 index 0000000..f7def42 --- /dev/null +++ b/client/lib/engine/bin/Disk.lib @@ -0,0 +1,1715 @@ +#!/bin/bash +#/** +#@file Disk.lib +#@brief Librería o clase Disk +#@class Disk +#@brief Funciones para gestión de discos y particiones. +#@version 1.1.1 +#@warning License: GNU GPLv3+ +#*/ + + +# Función ficticia para lanzar parted con timeout, evitando cuelgues del programa. +function parted () +{ +timeout -k 5s -s KILL 3s $(which parted) "$@" +} + + +#/** +# ogCreatePartitions int_ndisk str_parttype:int_partsize ... +#@brief Define el conjunto de particiones de un disco. +#@param int_ndisk nº de orden del disco +#@param str_parttype mnemónico del tipo de partición +#@param int_partsize tamaño de la partición (en KB) +#@return (nada, por determinar) +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND disco o partición no detectado (no es un dispositivo). +#@exception OG_ERR_PARTITION error en partición o en tabla de particiones. +#@attention El nº de partición se indica por el orden de los párametros \c parttype:partsize +#@attention Pueden definirse particiones vacías de tipo \c EMPTY +#@attention No puede definirse partición de cache y no se modifica si existe. +#@note Requisitos: sfdisk, parted, partprobe, awk +#@todo Definir atributos (arranque, oculta) y tamaños en MB, GB, etc. +#@version 0.9 - Primera versión para OpenGnSys +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2009/09/09 +#@version 0.9.1 - Corrección del redondeo del tamaño del disco. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2010/03/09 +#@version 1.0.4 - Llamada a función específica para tablas GPT. +#@author Universidad de Huelva +#@date 2012/03/30 +#@version 1.1.1 - El inicio de la primera partición logica es el de la extendida más 4x512 +#@author Irina Gomez, ETSII Universidad de Sevilla +#@date 2016/07/11 +#*/ ## +function ogCreatePartitions () +{ +# Variables locales. +local ND DISK PTTYPE PART SECTORS START SIZE TYPE CACHEPART IODISCO IOSIZE CACHESIZE +local EXTSTART EXTSIZE NVME_PREFIX tmpsfdisk +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk str_parttype:int_partsize ..." \ + "$FUNCNAME 1 NTFS:10000000 EXT3:5000000 LINUX-SWAP:1000000" + return +fi +# Error si no se reciben al menos 2 parámetros. +[ $# -ge 2 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +# Nº total de sectores, para evitar desbordamiento (evitar redondeo). +ND="$1" +DISK=$(ogDiskToDev "$ND") || return $? +PTTYPE=$(ogGetPartitionTableType $1) +PTTYPE=${PTTYPE:-"MSDOS"} # Por defecto para discos vacíos. +case "$PTTYPE" in + GPT) ogCreateGptPartitions "$@" + return $? ;; + MSDOS) ;; + *) ogRaiseError $OG_ERR_PARTITION "$PTTYPE" + return $? ;; +esac +SECTORS=$(ogGetLastSector $1) +# Se recalcula el nº de sectores del disco 1, si existe partición de caché. +CACHEPART=$(ogFindCache 2>/dev/null) +[ "$ND" = "${CACHEPART% *}" ] && CACHESIZE=$(ogGetCacheSize 2>/dev/null | awk '{print $0*2}') + +# Sector de inicio (la partición 1 empieza en el sector 63). +IODISCO=$(ogDiskToDev $1) +IOSIZE=$(fdisk -l $IODISCO | awk '/I\/O/ {print $4}') +if [ "$IOSIZE" == "4096" ]; then + START=4096 + SECTORS=$[SECTORS-8192] + [ -n "$CACHESIZE" ] && SECTORS=$[SECTORS-CACHESIZE+2048-(SECTORS-CACHESIZE)%2048-1] +else + START=63 + [ -n "$CACHESIZE" ] && SECTORS=$[SECTORS-CACHESIZE] +fi +PART=1 + +# Fichero temporal de entrada para "sfdisk" +tmpsfdisk=/tmp/sfdisk$$ +trap "rm -f $tmpsfdisk" 1 2 3 9 15 + +echo "unit: sectors" >$tmpsfdisk +echo >>$tmpsfdisk + +NVME_PREFIX="" +if [[ $DISK == *"nvme"* ]]; then + NVME_PREFIX="p" +fi + + +# Generar fichero de entrada para "sfdisk" con las particiones. +shift +while [ $# -gt 0 ]; do + # Conservar los datos de la partición de caché. + if [ "$ND $PART" == "$CACHEPART" -a -n "$CACHESIZE" ]; then + echo "$DISK$NVME_PREFIX$PART : start=$[SECTORS+1], size=$CACHESIZE, Id=ca" >>$tmpsfdisk + PART=$[PART+1] + fi + # Leer formato de cada parámetro - Tipo:Tamaño + TYPE="${1%%:*}" + SIZE="${1#*:}" + # Obtener identificador de tipo de partición válido. + ID=$(ogTypeToId "$TYPE" MSDOS) + [ "$TYPE" != "CACHE" -a -n "$ID" ] || ogRaiseError $OG_ERR_PARTITION "$TYPE" || return $? + # Comprobar tamaño numérico y convertir en sectores de 512 B. + [[ "$SIZE" == *([0-9]) ]] || ogRaiseError $OG_ERR_FORMAT "$SIZE" || return $? + SIZE=$[SIZE*2] + # Comprobar si la partición es extendida. + if [ $ID = 5 ]; then + [ $PART -le 4 ] || ogRaiseError $OG_ERR_FORMAT || return $? + # El inicio de la primera partición logica es el de la extendida más 4x512 + let EXTSTART=$START+2048 + let EXTSIZE=$SIZE-2048 + fi + # Incluir particiones lógicas dentro de la partición extendida. + if [ $PART = 5 ]; then + [ -n "$EXTSTART" ] || ogRaiseError $OG_ERR_FORMAT || return $? + START=$EXTSTART + SECTORS=$[EXTSTART+EXTSIZE] + fi + # Generar datos para la partición. + echo "$DISK$NVME_PREFIX$PART : start=$START, size=$SIZE, Id=$ID" >>$tmpsfdisk + # Error si se supera el nº total de sectores. + START=$[START+SIZE] + if [ "$IOSIZE" == "4096" -a $PART -gt 4 ]; then + START=$[START+2048] + fi + [ $START -le $SECTORS ] || ogRaiseError $OG_ERR_FORMAT "$[START/2] > $[SECTORS/2]" || return $? + PART=$[PART+1] + shift +done +# Si no se indican las 4 particiones primarias, definirlas como vacías, conservando la partición de caché. +while [ $PART -le 4 ]; do + if [ "$ND $PART" == "$CACHEPART" -a -n "$CACHESIZE" ]; then + echo "$DISK$NVME_PREFIX$PART : start=$[SECTORS+1], size=$CACHESIZE, Id=ca" >>$tmpsfdisk + else + echo "$DISK$NVME_PREFIX$PART : start=0, size=0, Id=0" >>$tmpsfdisk + fi + PART=$[PART+1] +done +# Si se define partición extendida sin lógicas, crear particion 5 vacía. +if [ $PART = 5 -a -n "$EXTSTART" ]; then + echo "${DISK}5 : start=$EXTSTART, size=$EXTSIZE, Id=0" >>$tmpsfdisk +fi + +# Desmontar los sistemas de archivos del disco antes de realizar las operaciones. +ogUnmountAll $ND 2>/dev/null +[ -n "$CACHESIZE" ] && ogUnmountCache 2>/dev/null + +# Si la tabla de particiones no es valida, volver a generarla. +ogCreatePartitionTable $ND +# Definir particiones y notificar al kernel. +sfdisk -f $DISK < $tmpsfdisk 2>/dev/null && partprobe $DISK +rm -f $tmpsfdisk +[ -n "$CACHESIZE" ] && ogMountCache 2>/dev/null || return 0 +} + + +#/** +# ogCreateGptPartitions int_ndisk str_parttype:int_partsize ... +#@brief Define el conjunto de particiones de un disco GPT +#@param int_ndisk nº de orden del disco +#@param str_parttype mnemónico del tipo de partición +#@param int_partsize tamaño de la partición (en KB) +#@return (nada, por determinar) +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND disco o partición no detectado (no es un dispositivo). +#@exception OG_ERR_PARTITION error en partición o en tabla de particiones. +#@attention El nº de partición se indica por el orden de los párametros \c parttype:partsize +#@attention Pueden definirse particiones vacías de tipo \c EMPTY +#@attention No puede definirse partición de caché y no se modifica si existe. +#@note Requisitos: sfdisk, parted, partprobe, awk +#@todo Definir atributos (arranque, oculta) y tamaños en MB, GB, etc. +#@version 1.0.4 - Primera versión para OpenGnSys +#@author Universidad de Huelva +#@date 2012/03/30 +#*/ ## +function ogCreateGptPartitions () +{ +# Variables locales. +local ND DISK PART SECTORS ALIGN START SIZE TYPE CACHEPART CACHESIZE DELOPTIONS OPTIONS +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk str_parttype:int_partsize ..." \ + "$FUNCNAME 1 NTFS:10000000 EXT3:5000000 LINUX-SWAP:1000000" + return +fi +# Error si no se reciben menos de 2 parámetros. +[ $# -ge 2 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +# Nº total de sectores, para evitar desbordamiento (evitar redondeo). +ND="$1" +DISK=$(ogDiskToDev "$ND") || return $? +# Se calcula el ultimo sector del disco (total de sectores usables) +SECTORS=$(ogGetLastSector $1) +# Se recalcula el nº de sectores del disco si existe partición de caché. +CACHEPART=$(ogFindCache 2>/dev/null) +[ "$ND" = "${CACHEPART% *}" ] && CACHESIZE=$(ogGetCacheSize 2>/dev/null | awk '{print $0*2}') +[ -n "$CACHESIZE" ] && SECTORS=$[SECTORS-CACHESIZE] +# Si el disco es GPT empieza en el sector 2048 por defecto, pero podria cambiarse +ALIGN=$(sgdisk -D $DISK 2>/dev/null) +START=$ALIGN +PART=1 + +# Leer parámetros con definición de particionado. +shift + +while [ $# -gt 0 ]; do + # Si PART es la cache, nos la saltamos y seguimos con el siguiente numero para conservar los datos de la partición de caché. + if [ "$ND $PART" == "$CACHEPART" -a -n "$CACHESIZE" ]; then + PART=$[PART+1] + fi + # Leer formato de cada parámetro - Tipo:Tamaño + TYPE="${1%%:*}" + SIZE="${1#*:}" + # Error si la partición es extendida (no válida en discos GPT). + if [ "$TYPE" == "EXTENDED" ]; then + ogRaiseError $OG_ERR_PARTITION "EXTENDED" + return $? + fi + # Comprobar si existe la particion actual, capturamos su tamaño para ver si cambio o no + PARTSIZE=$(ogGetPartitionSize $ND $PART 2>/dev/null) + # En sgdisk no se pueden redimensionar las particiones, es necesario borrarlas y volver a crealas + [ $PARTSIZE ] && DELOPTIONS="$DELOPTIONS -d$PART" + # Creamos la particion + # Obtener identificador de tipo de partición válido. + ID=$(ogTypeToId "$TYPE" GPT) + [ "$TYPE" != "CACHE" -a -n "$ID" ] || ogRaiseError $OG_ERR_PARTITION "$TYPE" || return $? + # Comprobar tamaño numérico y convertir en sectores de 512 B. + [[ "$SIZE" == *([0-9]) ]] || ogRaiseError $OG_ERR_FORMAT "$SIZE" || return $? + SIZE=$[SIZE*2] + # SIZE debe ser múltiplo de ALIGN, si no gdisk lo mueve automáticamente. + DIV=$[$SIZE/$ALIGN] + SIZE=$[$DIV*$ALIGN] + # En el caso de que la partición sea EMPTY no se crea nada + if [ "$TYPE" != "EMPTY" ]; then + OPTIONS="$OPTIONS -n$PART:$START:+$SIZE -t$PART:$ID " + fi + START=$[START+SIZE] + # Error si se supera el nº total de sectores. + [ $START -le $SECTORS ] || ogRaiseError $OG_ERR_FORMAT "$[START/2] > $[SECTORS/2]" || return $? + PART=$[PART+1] + shift +done + +# Desmontar los sistemas de archivos del disco antes de realizar las operaciones. +ogUnmountAll $ND 2>/dev/null +[ -n "$CACHESIZE" ] && ogUnmountCache 2>/dev/null + +# Si la tabla de particiones no es valida, volver a generarla. +ogCreatePartitionTable $ND +# Definir particiones y notificar al kernel. +# Borramos primero las particiones y luego creamos las nuevas +sgdisk $DELOPTIONS $OPTIONS $DISK 2>/dev/null && partprobe $DISK +[ -n "$CACHESIZE" ] && ogMountCache 2>/dev/null || return 0 +} + + +#/** +# ogCreatePartitionTable int_ndisk [str_tabletype] +#@brief Genera una tabla de particiones en caso de que no sea valida, si es valida no hace nada. +#@param int_ndisk nº de orden del disco +#@param str_tabletype tipo de tabla de particiones (opcional) +#@return (por determinar) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@note tabletype: { MSDOS, GPT }, MSDOS por defecto +#@note Requisitos: fdisk, gdisk, parted +#@version 1.0.4 - Primera versión compatible con OpenGnSys. +#@author Universidad de Huelva +#@date 2012/03/06 +#@version 1.0.6a - Adaptar creación de nueva tabla MSDOS. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2016/01/29 +#*/ ## +function ogCreatePartitionTable () +{ +# Variables locales. +local DISK PTTYPE CREATE CREATEPTT + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME int_ndisk [str_partype]" \ + "$FUNCNAME 1 GPT" "$FUNCNAME 1" + return +fi +# Error si no se reciben 1 o 2 parámetros. +case $# in + 1) CREATEPTT="" ;; + 2) CREATEPTT="$2" ;; + *) ogRaiseError $OG_ERR_FORMAT + return $? ;; +esac + +# Capturamos el tipo de tabla de particiones actual +DISK=$(ogDiskToDev $1) || return $? +PTTYPE=$(ogGetPartitionTableType $1) +PTTYPE=${PTTYPE:-"MSDOS"} # Por defecto para discos vacíos. +CREATEPTT=${CREATEPTT:-"$PTTYPE"} + +# Si la tabla actual y la que se indica son iguales, se comprueba si hay que regenerarla. +if [ "$CREATEPTT" == "$PTTYPE" ]; then + case "$PTTYPE" in + GPT) [ ! $(sgdisk -p $DISK 2>&1 >/dev/null) ] || CREATE="GPT" ;; + MSDOS) [ $(parted -s $DISK print >/dev/null) ] || CREATE="MSDOS" ;; + esac +else + CREATE="$CREATEPTT" +fi +# Dependiendo del valor de CREATE, creamos la tabla de particiones en cada caso. +case "$CREATE" in + GPT) + # Si es necesario crear una tabla GPT pero la actual es MSDOS + if [ "$PTTYPE" == "MSDOS" ]; then + sgdisk -go $DISK + else + echo -e "2\nw\nY\n" | gdisk $DISK + fi + partprobe $DISK 2>/dev/null + ;; + MSDOS) + # Si es necesario crear una tabla MSDOS pero la actual es GPT + if [ "$PTTYPE" == "GPT" ]; then + sgdisk -Z $DISK + fi + # Crear y borrar una partición para que la tabla se genere bien. + echo -e "o\nn\np\n\n\n\nd\n\nw" | fdisk $DISK + partprobe $DISK 2>/dev/null + ;; +esac +} + + +#/** +# ogDeletePartitionTable ndisk +#@brief Borra la tabla de particiones del disco. +#@param int_ndisk nº de orden del disco +#@return la informacion propia del fdisk +#@version 0.1 - Integracion para OpenGnSys +#@author Antonio J. Doblas Viso. Universidad de Malaga +#@date 2008/10/27 +#@version 1.0.4 - Adaptado para su uso con discos GPT +#@author Universidad de Huelva +#@date 2012/03/13 +#*/ ## +function ogDeletePartitionTable () +{ +# Variables locales. +local DISK + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME int_ndisk" "$FUNCNAME 1" + return +fi +# Error si no se reciben 1 parámetros. +[ $# == 1 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +# Obteniendo Identificador linux del disco. +DISK=$(ogDiskToDev $1) || return $? +# Crear una tabla de particiones vacía. +case "$(ogGetPartitionTableType $1)" in + GPT) sgdisk -o $DISK ;; + MSDOS) echo -ne "o\nw" | fdisk $DISK ;; +esac +} + + +#/** +# ogDevToDisk path_device | LABEL="str_label" | UUID="str_uuid" +#@brief Devuelve el nº de orden de dicso (y partición) correspondiente al nombre de fichero de dispositivo o a la etiqueta o UUID del sistema de archivos asociado. +#@param path_device Camino del fichero de dispositivo. +#@param str_label etiqueta de sistema de archivos. +#@param str_uuid UUID de sistema de archivos. +#@return int_ndisk (para dispositivo de disco) +#@return int_ndisk int_npartition (para dispositivo de partición). +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Dispositivo no detectado. +#@note Solo se acepta en cada llamada 1 de los 3 tipos de parámetros. +#@version 0.1 - Integracion para Opengnsys - EAC: DiskEAC() en ATA.lib +#@author Antonio J. Doblas Viso, Universidad de Malaga +#@date 2008/10/27 +#@version 0.9 - Primera version para OpenGnSys +#@author Ramon Gomez, ETSII Universidad Sevilla +#@date 2009/07/20 +#@version 1.0.6 - Soporta parámetro con UIID o etiqueta. +#@author Ramon Gomez, ETSII Universidad Sevilla +#@date 2014/07/13 +#*/ ## +function ogDevToDisk () +{ +# Variables locales. +local CACHEFILE DEV PART NVME_PREFIX d n +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME path_device | LABEL=str_label | UUID=str_uuid" \ + "$FUNCNAME /dev/sda => 1" \ + "$FUNCNAME /dev/sda1 => 1 1" \ + "$FUNCNAME LABEL=CACHE => 1 4" + return +fi + +# Error si no se recibe 1 parámetro. +[ $# == 1 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +# Obtener dispositivo a partir de camino, etiqueta o UUID. +DEV="$1" +case "$DEV" in + LABEL=*) DEV=$(blkid -L "${1#*=}") ;; + PARTLABEL=*) DEV=$(realpath "/dev/disk/by-partlabel/${1#*=}" 2>/dev/null) ;; + PARTUUID=*) DEV=$(realpath "/dev/disk/by-partuuid/${1#*=}" 2>/dev/null) ;; + UUID=*) DEV=$(blkid -U "${1#*=}") ;; +esac + +# Error si no es fichero de bloques o directorio (para LVM). +[ -b "$DEV" -o -d "$DEV" ] || ogRaiseError $OG_ERR_NOTFOUND "$1" || return $? + +# Buscar en fichero de caché de discos. +CACHEFILE=/var/cache/disks.cfg +PART=$(awk -F: -v d="$DEV" '{if ($2==d) {print $1}}' $CACHEFILE 2>/dev/null) +if [ -n "$PART" ]; then + echo "$PART" + return +fi +# Si no se encuentra, procesa todos los discos para devolver su nº de orden y de partición. +n=1 +for d in $(ogDiskToDev); do +NVME_PREFIX="" +if [[ $d == *"nvme"* ]]; then + NVME_PREFIX="p" +fi + + + [ -n "$(echo $DEV | grep $d)" ] && echo "$n ${DEV#$d$NVME_PREFIX}" && return + n=$[n+1] +done +ogRaiseError $OG_ERR_NOTFOUND "$1" +return $OG_ERR_NOTFOUND +} + + +#/** +# ogDiskToDev [int_ndisk [int_npartition]] +#@brief Devuelve la equivalencia entre el nº de orden del dispositivo (dicso o partición) y el nombre de fichero de dispositivo correspondiente. +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@return Para 0 parametros: Devuelve los nombres de ficheros de los dispositivos sata/ata/usb linux encontrados. +#@return Para 1 parametros: Devuelve la ruta del disco duro indicado. +#@return Para 2 parametros: Devuelve la ruta de la particion indicada. +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Dispositivo no detectado. +#@note Requisitos: awk, lvm +#@version 0.1 - Integracion para Opengnsys - EAC: Disk() en ATA.lib; HIDRA: DetectarDiscos.sh +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@Date 2008/06/19 +#@author Antonio J. Doblas Viso, Universidad de Malaga +#@date 2008/10/27 +#@version 0.9 - Primera version para OpenGnSys +#@author Ramon Gomez, ETSII Universidad Sevilla +#@date 2009-07-20 +#@version 1.0.5 - Comprobación correcta de parámetros para soportar valores > 9. +#@author Ramon Gomez, ETSII Universidad Sevilla +#@date 2013-05-07 +#@version 1.0.6 - Soportar RAID hardware y Multipath. +#@author Ramon Gomez, ETSII Universidad Sevilla +#@date 2014-09-23 +#@version 1.1.0 - Usar caché de datos y soportar pool de volúmenes ZFS. +#@author Ramon Gomez, ETSII Universidad Sevilla +#@date 2016-05-27 +#*/ ## +function ogDiskToDev () +{ +# Variables locales +local CACHEFILE ALLDISKS MPATH VOLGROUPS ZFSVOLS DISK PART ZPOOL i + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk [int_npartition]" \ + "$FUNCNAME => /dev/sda /dev/sdb" \ + "$FUNCNAME 1 => /dev/sda" \ + "$FUNCNAME 1 1 => /dev/sda1" + return +fi + +# Borrar fichero de caché de configuración si hay cambios en las particiones. +CACHEFILE=/var/cache/disks.cfg +if ! diff -q <(cat /proc/partitions) /tmp/.partitions &>/dev/null; then + # Guardar copia de las particiones definidas para comprobar cambios. + cp -a /proc/partitions /tmp/.partitions + rm -f $CACHEFILE +fi + +# Si existe una correspondencia con disco/dispositivo en el caché; mostrarlo y salir. +PART=$(awk -F: -v d="$*" '{if ($1==d) {print $2}}' $CACHEFILE 2>/dev/null) +if [ -n "$PART" ]; then + echo "$PART" + return +fi + +# Continuar para detectar nuevos dispositivos. +# Listar dispositivos de discos. +ALLDISKS=$((lsblk -n -e 1,2 -x MAJ:MIN 2>/dev/null || lsblk -n -e 1,2) | \ + awk '$6~/^disk$/ {gsub(/!/,"/"); printf "/dev/%s ",$1}') +#ALLDISKS=$(lsblk -Jdp | jq -r '.blockdevices[] | select(.type=="disk").name') +# Listar volúmenes lógicos. +VOLGROUPS=$(vgs -a --noheadings 2>/dev/null | awk '{printf "/dev/%s ",$1}') +ALLDISKS="$ALLDISKS $VOLGROUPS" + +# Detectar caminos múltiples (ignorar mensaje si no está configurado Multipath). +if MPATH=$(multipath -l -v 1 2>/dev/null | awk '{printf "/dev/mapper/%s ",$1}'; exit ${PIPESTATUS[0]}); then + # Quitar de la lista los discos que forman parte de Multipath. + for i in $(multipath -ll | awk '$6=="ready" {printf "/dev/%s ",$3}'); do + ALLDISKS="${ALLDISKS//$i/}" + done + # Añadir caminos múltiples a los discos detectados. + ALLDISKS="$ALLDISKS $MPATH" +fi + +# Detectar volúmenes ZFS. +ZFSVOLS=$(blkid | awk -F: '/zfs/ {print $1}') +ALLDISKS="$ALLDISKS $ZFSVOLS" + +# Mostrar salidas segun el número de parametros. +case $# in + 0) # Muestra todos los discos, separados por espacios. + echo $ALLDISKS + ;; + 1) # Error si el parámetro no es un número positivo. + [[ "$1" =~ ^[1-9][0-9]*$ ]] || ogRaiseError $OG_ERR_FORMAT "$1" || return $? + DISK=$(echo "$ALLDISKS" | awk -v n=$1 '{print $n}') + # Error si el fichero no existe. + [ -e "$DISK" ] || ogRaiseError $OG_ERR_NOTFOUND "$1" || return $? + # Actualizar caché de configuración y mostrar dispositivo. + echo "$*:$DISK" >> $CACHEFILE + echo "$DISK" + ;; + 2) # Error si los 2 parámetros no son números positivos. + [[ "$1" =~ ^[1-9][0-9]*$ ]] && [[ "$2" =~ ^[1-9][0-9]*$ ]] || ogRaiseError $OG_ERR_FORMAT "$1 $2" || return $? + DISK=$(echo "$ALLDISKS" | awk -v n=$1 '{print $n}') + [ -e "$DISK" ] || ogRaiseError $OG_ERR_NOTFOUND "$1" || return $? + PART="$DISK$2" + # Comprobar si es partición. + if [ -b "$PART" ]; then + # Actualizar caché de configuración y mostrar dispositivo. + echo "$*:$PART" >> $CACHEFILE + echo "$PART" + else + # Comprobar si RAID o Multipath (tener en cuenta enlace simbólico). + PART="${DISK}p$2" + if [ "$(stat -L -c "%A" "$PART" 2>/dev/null | cut -c1)" == "b" ]; then + # Actualizar caché de configuración y mostrar dispositivo. + echo "$*:$PART" >> $CACHEFILE + echo "$PART" + else + PART="" + # Comprobar si volumen lógico. /* (comentario Doxygen) + if ogCheckStringInGroup "$DISK" "$VOLGROUPS"; then + PART=$(lvscan -a 2>/dev/null | \ + awk -F\' -v n=$2 "\$2~/^${DISK//\//\\/}\// {if (NR==n) print \$2}") + [ -e "$PART" ] || ogRaiseError $OG_ERR_NOTFOUND "$1 $2" || return $? + # (comentario Doxygen) */ + fi + # Comprobar si volumen ZFS que puede ser montado. + if ogCheckStringInGroup "$DISK" "$ZFSVOLS"; then + zpool import -f -R /mnt -N -a 2>/dev/null + ZPOOL=$(blkid -s LABEL -o value $DISK) + PART=$(zfs list -Hp -o name,canmount,mountpoint -r $ZPOOL | \ + awk -v n=$2 '$2=="on" && $3!="none" {c++; if (c==n) print $1}') + fi + # Salir si no se encuentra dispositivo. + [ -n "$PART" ] || ogRaiseError $OG_ERR_NOTFOUND "$1 $2" || return $? + # Devolver camino al dispositivo. + # Actualizar caché de configuración y mostrar dispositivo. + echo "$*:$PART" >> $CACHEFILE + echo "$PART" + fi + fi + ;; + *) # Formato erroneo. + ogRaiseError $OG_ERR_FORMAT + return $OG_ERR_FORMAT + ;; +esac +} + + +#/** +# ogGetDiskSize int_ndisk +#@brief Muestra el tamaño en KB de un disco. +#@param int_ndisk nº de orden del disco +#@return int_size - Tamaño en KB del disco. +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND disco o particion no detectado (no es un dispositivo). +#@note Requisitos: sfdisk, awk +#@version 0.9.2 - Primera version para OpenGnSys +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2010/09/15 +#@version 1.0.6 - Soportar LVM. +#@author Universidad de Huelva +#@date 2014/09/04 +#*/ ## +function ogGetDiskSize () +{ +# Variables locales. +local DISK SIZE + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk" "$FUNCNAME 1 => 244198584" + return +fi +# Error si no se recibe 1 parámetro. +[ $# == 1 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +# Obtener el tamaño del disco. +DISK="$(ogDiskToDev $1)" || return $? +SIZE=$(awk -v D=${DISK#/dev/} '{if ($4==D) {print $3}}' /proc/partitions) +# Si no, obtener tamaño del grupo de volúmenes. +[ -z "$SIZE" ] && SIZE=$(vgs --noheadings --units=B -o dev_size $DISK 2>/dev/null | \ + awk '{print $1/1024}') + +# Mostrar salida. +[ -n "$SIZE" ] && echo "$SIZE" +} + + +#/** +# ogGetDiskType path_device +#@brief Muestra el tipo de disco (real, RAID, meta-disco, USB, etc.). +#@param path_device Dispositivo +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND disco no detectado o no es un dispositivo de bloques. +#@note Requisitos: udevadm +#@version 1.1.1 - Primera version para OpenGnsys +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2018-02-27 +#*/ ## +function ogGetDiskType () +{ +# Variables locales +local DEV MAJOR TYPE + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME path_device" \ + "$FUNCNAME /dev/sdb => USB" + return +fi +# Error si no se recibe 1 parámetro. +[ $# == 1 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +# Obtener el driver del dispositivo de bloques. +[ -b "$1" ] || ogRaiseError $OG_ERR_NOTFOUND "$1" || return $? +DEV=${1#/dev/} +MAJOR=$(awk -v D="$DEV" '{if ($4==D) print $1;}' /proc/partitions) +TYPE=$(awk -v D=$MAJOR '/Block/ {bl=1} {if ($1==D&&bl) print toupper($2)}' /proc/devices) +# Devolver mnemónico del driver de dispositivo. +case "$TYPE" in + SD) + TYPE="DISK" + udevadm info -q property $1 2>/dev/null | grep -q "^ID_BUS=usb" && TYPE="USB" + ;; + BLKEXT) + TYPE="NVM" + ;; + SR|IDE*) + TYPE="CDROM" # FIXME Comprobar discos IDE. + ;; + MD|CCISS*) + TYPE="RAID" + ;; + DEVICE-MAPPER) + TYPE="MAPPER" # FIXME Comprobar LVM y RAID. + ;; +esac +echo $TYPE +} + + +#/** +# ogGetEsp +#@brief Devuelve números de disco y partición para la partición EFI (ESP). +#*/ ## +function ogGetEsp () +{ +local PART d +for d in $(blkid -o device|sort); do + # Previene error para /dev/loop0 + PART="$(ogDevToDisk $d 2>/dev/null)" || 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=$(echo $PART | awk '{ print length($0) }') + if [ $LEN -gt 1 ]; then + if [ "$(ogGetPartitionId $PART)" == "$(ogTypeToId EFI GPT)" ]; then + echo $PART + break + fi + fi +done +} + + +#/** +# ogGetLastSector int_ndisk [int_npart] +#@brief Devuelve el último sector usable del disco o de una partición. +#@param int_ndisk nº de orden del disco +#@param int_npart nº de orden de la partición (opcional) +#@return Último sector usable. +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o partición no corresponde con un dispositivo. +#@note Requisitos: sfdisk, sgdisk +#@version 1.0.4 - Primera versión compatible con OpenGnSys. +#@author Universidad de Huelva +#@date 2012-06-03 +#@version 1.0.6b - uso de sgdisk para todo tipo de particiones. Incidencia #762 +#@author Universidad de Málaga +#@date 2016-11-10 +#*/ ## +function ogGetLastSector () +{ +# Variables locales +local DISK PART LASTSECTOR + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk [int_npart]" \ + "$FUNCNAME 1 => 488392064" \ + "$FUNCNAME 1 1 => 102400062" + return +fi + +# Obtener último sector. +case $# in + 1) # Para un disco. + DISK=$(ogDiskToDev $1) || return $? + LASTSECTOR=$(LANG=C sgdisk -p $DISK | awk '/last usable sector/ {print($(NF))}') + ;; + 2) # Para una partición. + DISK=$(ogDiskToDev $1) || return $? + PART=$(ogDiskToDev $1 $2) || return $? + LASTSECTOR=$(LANG=C sgdisk -p $DISK | awk -v P="$2" '{if ($1==P) print $3}') + ;; + *) # Error si se reciben más parámetros. + ogRaiseError $OG_ERR_FORMAT + return $? ;; +esac +echo $LASTSECTOR +} + + +#/** +# ogGetPartitionActive int_ndisk +#@brief Muestra que particion de un disco esta marcada como de activa. +#@param int_ndisk nº de orden del disco +#@return int_npart Nº de partición activa +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@note Requisitos: parted +#@todo Queda definir formato para atributos (arranque, oculta, ...). +#@version 0.9 - Primera version compatible con OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2009/09/17 +#*/ ## +function ogGetPartitionActive () +{ +# Variables locales +local DISK + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk" "$FUNCNAME 1 => 1" + return +fi +# Error si no se recibe 1 parámetro. +[ $# == 1 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +# Comprobar que el disco existe y listar su partición activa. +DISK="$(ogDiskToDev $1)" || return $? +LANG=C parted -sm $DISK print 2>/dev/null | awk -F: '$7~/boot/ {print $1}' +} + + +#/** +# 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 +#@version 0.9 - Primera versión compatible con OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2009-03-25 +#@version 1.0.2 - Detectar partición vacía. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2011-12-23 +#@version 1.0.6 - Soportar LVM. +#@author Universidad de Huelva +#@date 2014-09-04 +#@version 1.1.0 - Soportar pool de volúmenes ZFS. +#@author Ramon Gomez, ETSII Universidad Sevilla +#@date 2014-11-14 +#*/ ## +function ogGetPartitionId () +{ +# Variables locales. +local DISK ID + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_npartition" \ + "$FUNCNAME 1 1 => 7" + return +fi +# Error si no se reciben 2 parámetros. +[ $# == 2 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +# Detectar y mostrar el id. de tipo de partición. +DISK=$(ogDiskToDev $1) || return $? +case "$(ogGetPartitionTableType $1)" in + GPT) ID=$(sgdisk -p $DISK 2>/dev/null | awk -v p="$2" '{if ($1==p) print $6;}') || ogRaiseError $OG_ERR_NOTFOUND "$1,$2" || return $? + [ "$ID" == "8300" -a "$1 $2" == "$(ogFindCache)" ] && ID=CA00 + ;; + MSDOS) ID=$(sfdisk --id $DISK $2 2>/dev/null) || ogRaiseError $OG_ERR_NOTFOUND "$1,$2" || return $? ;; + LVM) ID=10000 ;; + ZPOOL) ID=10010 ;; +esac +echo $ID +} + + +#/** +# ogGetPartitionSize int_ndisk int_npartition +#@brief Muestra el tamano en KB de una particion determinada. +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@return int_partsize - Tamaño en KB de la partición. +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND disco o particion no detectado (no es un dispositivo). +#@note Requisitos: sfdisk, awk +#@version 0.1 - Integracion para Opengnsys - EAC: SizePartition () en ATA.lib +#@author Antonio J. Doblas Viso, Universidad de Malaga +#@date 2008/10/27 +#@version 0.9 - Primera version para OpenGnSys +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2009/07/24 +#@version 1.1.0 - Sustituir "sfdisk" por "partx". +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2016/05/04 +#*/ ## +function ogGetPartitionSize () +{ +# Variables locales. +local PART SIZE + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_npartition" \ + "$FUNCNAME 1 1 => 10000000" + return +fi +# Error si no se reciben 2 parámetros. +[ $# == 2 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +# Devolver tamaño de partición, del volumen lógico o del sistema de archivos (para ZFS). +PART="$(ogDiskToDev $1 $2)" || return $? +SIZE=$(partx -gbo SIZE $PART 2>/dev/null | awk '{print int($1/1024)}') +[ -z "$SIZE" ] && SIZE=$(lvs --noheadings -o lv_size --units k $PART | awk '{printf "%d",$0}') +[ -z "$SIZE" ] && SIZE=$(ogGetFsSize $1 $2) +echo ${SIZE:-0} +} + + +#/** +# ogGetPartitionsNumber int_ndisk +#@brief Detecta el numero de particiones del disco duro indicado. +#@param int_ndisk nº de orden del disco +#@return Devuelve el numero paritiones del disco duro indicado +#@warning Salidas de errores no determinada +#@attention Requisitos: parted +#@note Notas sin especificar +#@version 0.1 - Integracion para Opengnsys - EAC: DetectNumberPartition () en ATA.lib +#@author Antonio J. Doblas Viso. Universidad de Malaga +#@date Date: 27/10/2008 +#@version 1.0 - Uso de sfdisk Primera version para OpenGnSys +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2009-07-24 +#@version 1.0.4 - Uso de /proc/partitions para detectar el numero de particiones +#@author Universidad de Huelva +#@date 2012-03-28 +#@version 1.0.6 - Soportar LVM. +#@author Universidad de Huelva +#@date 2014-09-04 +#@version 1.1.0 - Soportar ZFS y sustituir "sfdisk" por "partx". +#@author Ramon Gomez, ETSII Universidad Sevilla +#@date 2016-04-28 +#*/ ## +function ogGetPartitionsNumber () +{ +# Variables locales. +local DISK +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk" \ + "$FUNCNAME 1 => 3" + return +fi +# Error si no se recibe 1 parámetro. +[ $# == 1 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +# Contar el nº de veces que aparece el disco en su lista de particiones. +DISK=$(ogDiskToDev $1) 2>/dev/null +case "$(ogGetPartitionTableType $1)" in + GPT|MSDOS) + partx -gso NR $DISK 2>/dev/null | awk -v p=0 '{p=$1} END {print p}' ;; + LVM) lvs --noheadings $DISK 2>/dev/null | wc -l ;; + ZPOOL) zpool list &>/dev/null || modprobe zfs + zpool import -f -R /mnt -N -a 2>/dev/null + zfs list -Hp -o name,canmount,mountpoint -r $(blkid -s LABEL -o value $DISK) | \ + awk '$2=="on" && $3!="none" {c++} + END {print c}' + ;; +esac +} + + +#/** +# 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 +#@version 1.0.4 - Primera versión para OpenGnSys +#@author Universidad de Huelva +#@date 2012/03/01 +#@version 1.0.6 - Soportar LVM. +#@author Universidad de Huelva +#@date 2014-09-04 +#@version 1.1.0 - Mejorar rendimiento y soportar ZFS. +#@author Ramon Gomez, ETSII Universidad Sevilla +#@date 2014-11-14 +#*/ ## +function ogGetPartitionTableType () +{ +# Variables locales. +local DISK TYPE + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk" \ + "$FUNCNAME 1 => MSDOS" + return +fi +# Error si no se recibe 1 parámetro. +[ $# == 1 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +# Sustituye n de disco por su dispositivo. +DISK=$(ogDiskToDev $1) || return $? + +# Comprobar tabla de particiones. +if [ -b $DISK ]; then + TYPE=$(parted -sm $DISK print 2>/dev/null | awk -F: -v D=$DISK '{ if($1 == D) print toupper($6)}') + [ -z "$TYPE" ] && TYPE=$(parted -sm $DISK print 2>/dev/null | awk -F: -v D=$DISK '{ if($1 == D) print toupper($6)}') +fi +# Comprobar si es volumen lógico. +[ -d $DISK ] && vgs $DISK &>/dev/null && TYPE="LVM" +# Comprobar si es pool de ZFS. +[ -z "$TYPE" -o "$TYPE" == "UNKNOWN" ] && [ -n "$(blkid -s TYPE $DISK | grep zfs)" ] && TYPE="ZPOOL" + +# Mostrar salida. +[ -n "$TYPE" ] && echo "$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. +#@version 0.1 - Integracion para Opengnsys - EAC: TypeFS() en ATA.lib +#@author Antonio J. Doblas Viso. Universidad de Malaga +#@date 2008-10-27 +#@version 0.9 - Primera adaptacion para OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2009-07-21 +#@version 1.0.3 - Código trasladado de antigua función ogGetFsType. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2011-12-01 +#@version 1.0.5 - Usar función ogIdToType para hacer la conversión id. a tipo. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2013-09-19 +#*/ ## +function ogGetPartitionType () +{ +# Variables locales. +local ID TYPE + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_npartition" \ + "$FUNCNAME 1 1 => NTFS" + return +fi +# Error si no se reciben 2 parámetros. +[ $# == 2 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +# Detectar id. de tipo de partición y codificar al mnemonico. +ID=$(ogGetPartitionId "$1" "$2") || return $? +TYPE=$(ogIdToType "$ID") +echo "$TYPE" +} + + +#/** +# ogHidePartition int_ndisk int_npartition +#@brief Oculta un apartición visible. +#@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. +#@version 1.0 - Versión en pruebas. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2010/01/12 +#@version 1.1.1 - Se incluye tipo Windows para UEFI (ticket #802) +#@author Irina Gomez, ETSII Universidad de Sevilla +#@date 2019/01/18 +#*/ ## +function ogHidePartition () +{ +# Variables locales. +local PART TYPE NEWTYPE +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_npartition" \ + "$FUNCNAME 1 1" + return +fi +# Error si no se reciben 2 parámetros. +[ $# == 2 ] || ogRaiseError $OG_ERR_FORMAT || return $? +PART=$(ogDiskToDev "$1" "$2") || return $? + +# Obtener tipo de partición. +TYPE=$(ogGetPartitionType "$1" "$2") +case "$TYPE" in + NTFS) NEWTYPE="HNTFS" ;; + FAT32) NEWTYPE="HFAT32" ;; + FAT16) NEWTYPE="HFAT16" ;; + FAT12) NEWTYPE="HFAT12" ;; + WINDOWS)NEWTYPE="WIN-RESERV";; + *) ogRaiseError $OG_ERR_PARTITION "$TYPE" + return $? ;; +esac +# Cambiar tipo de partición. +ogSetPartitionType $1 $2 $NEWTYPE +} + + +#/** +# ogIdToType int_idpart +#@brief Devuelve el identificador correspondiente a un tipo de partición. +#@param int_idpart identificador de tipo de partición. +#@return str_parttype mnemónico de tipo de partición. +#@exception OG_ERR_FORMAT Formato incorrecto. +#@version 1.0.5 - Primera version para OpenGnSys +#@author Ramon Gomez, ETSII Universidad Sevilla +#@date 2013-02-07 +#*/ ## +function ogIdToType () +{ +# Variables locales +local ID TYPE + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_idpart" \ + "$FUNCNAME 83 => LINUX" + return +fi +# Error si no se recibe 1 parámetro. +[ $# == 1 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +# Obtener valor hexadecimal de 4 caracteres rellenado con 0 por delante. +ID=$(printf "%4s" "$1" | tr ' ' '0') +case "${ID,,}" in + 0000) TYPE="EMPTY" ;; + 0001) TYPE="FAT12" ;; + 0005|000f) TYPE="EXTENDED" ;; + 0006|000e) TYPE="FAT16" ;; + 0007) TYPE="NTFS" ;; + 000b|000c) TYPE="FAT32" ;; + 0011) TYPE="HFAT12" ;; + 0012) TYPE="COMPAQDIAG" ;; + 0016|001e) TYPE="HFAT16" ;; + 0017) TYPE="HNTFS" ;; + 001b|001c) TYPE="HFAT32" ;; + 0042) TYPE="WIN-DYNAMIC" ;; + 0082|8200) TYPE="LINUX-SWAP" ;; + 0083|8300) TYPE="LINUX" ;; + 008e|8E00) TYPE="LINUX-LVM" ;; + 00a5|a503) TYPE="FREEBSD" ;; + 00a6) TYPE="OPENBSD" ;; + 00a7) TYPE="CACHE" ;; # (compatibilidad con Brutalix) + 00af|af00) TYPE="HFS" ;; + 00be|be00) TYPE="SOLARIS-BOOT" ;; + 00bf|bf0[0145]) TYPE="SOLARIS" ;; + 00ca|ca00) TYPE="CACHE" ;; + 00da) TYPE="DATA" ;; + 00ee) TYPE="GPT" ;; + 00ef|ef00) TYPE="EFI" ;; + 00fb) TYPE="VMFS" ;; + 00fd|fd00) TYPE="LINUX-RAID" ;; + 0700) TYPE="WINDOWS" ;; + 0c01) TYPE="WIN-RESERV" ;; + 7f00) TYPE="CHROMEOS-KRN" ;; + 7f01) TYPE="CHROMEOS" ;; + 7f02) TYPE="CHROMEOS-RESERV" ;; + 8301) TYPE="LINUX-RESERV" ;; + a500) TYPE="FREEBSD-DISK" ;; + a501) TYPE="FREEBSD-BOOT" ;; + a502) TYPE="FREEBSD-SWAP" ;; + ab00) TYPE="HFS-BOOT" ;; + af01) TYPE="HFS-RAID" ;; + bf02) TYPE="SOLARIS-SWAP" ;; + bf03) TYPE="SOLARIS-DISK" ;; + ef01) TYPE="MBR" ;; + ef02) TYPE="BIOS-BOOT" ;; + 10000) TYPE="LVM-LV" ;; + 10010) TYPE="ZFS-VOL" ;; + *) TYPE="UNKNOWN" ;; +esac +echo "$TYPE" +} + + +# ogIsDiskLocked int_ndisk +#@brief Comprueba si un disco está bloqueado por una operación de uso exclusivo. +#@param int_ndisk nº de orden del disco +#@return Código de salida: 0 - bloqueado, 1 - sin bloquear o error. +#@note Los ficheros de bloqueo se localizan en \c /var/lock/dev, siendo \c dev el dispositivo de la partición o de su disco, sustituyendo el carácter "/" por "-". +#@version 1.1.0 - Primera versión para OpenGnsys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2016-04-08 +#*/ ## +function ogIsDiskLocked () +{ +# Variables locales +local DISK LOCKFILE + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk" \ + "if $FUNCNAME 1; then ... ; fi" + return +fi +# Falso, en caso de error. +[ $# == 1 ] || return 1 +DISK="$(ogDiskToDev $1 2>/dev/null)" || return 1 + +# Comprobar existencia de fichero de bloqueo para el disco. +LOCKFILE="/var/lock/lock${DISK//\//-}" +test -f $LOCKFILE +} + + +#/** +# ogListPartitions int_ndisk +#@brief Lista las particiones definidas en un disco. +#@param int_ndisk nº de orden del disco +#@return str_parttype:int_partsize ... +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND disco o particion no detectado (no es un dispositivo). +#@note Requisitos: \c parted \c awk +#@attention El nº de partición se indica por el orden de los párametros \c parttype:partsize +#@attention Las tuplas de valores están separadas por espacios. +#@version 0.9 - Primera versión para OpenGnSys +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2009/07/24 +#*/ ## +function ogListPartitions () +{ +# Variables locales. +local DISK PART NPARTS TYPE SIZE + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk" \ + "$FUNCNAME 1 => NTFS:10000000 EXT3:5000000 LINUX-SWAP:1000000" + return +fi +# Error si no se recibe 1 parámetro. +[ $# == 1 ] || ogRaiseError $OG_ERR_FORMAT "$FORMAT" || return $? + +# Procesar la salida de \c parted . +DISK="$(ogDiskToDev $1)" || return $? +NPARTS=$(ogGetPartitionsNumber $1) +for (( PART = 1; PART <= NPARTS; PART++ )); do + TYPE=$(ogGetPartitionType $1 $PART 2>/dev/null); TYPE=${TYPE:-EMPTY} + SIZE=$(ogGetPartitionSize $1 $PART 2>/dev/null); SIZE=${SIZE:-0} + echo -n "$TYPE:$SIZE " +done +echo +} + + +#/** +# ogListPrimaryPartitions int_ndisk +#@brief Metafunción que lista las particiones primarias no vacías de un disco. +#@param int_ndisk nº de orden del disco +#@see ogListPartitions +#*/ ## +function ogListPrimaryPartitions () +{ +# Variables locales. +local PTTYPE PARTS + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk" \ + "$FUNCNAME 1 => NTFS:10000000 EXT3:5000000 EXTENDED:1000000" + return +fi + +PTTYPE=$(ogGetPartitionTableType $1) || return $? +PARTS=$(ogListPartitions "$@") || return $? +case "$PTTYPE" in + GPT) echo $PARTS | sed 's/\( EMPTY:0\)*$//' ;; + MSDOS) echo $PARTS | cut -sf1-4 -d" " | sed 's/\( EMPTY:0\)*$//' ;; +esac +} + + +#/** +# ogListLogicalPartitions int_ndisk +#@brief Metafunción que lista las particiones lógicas de una tabla tipo MSDOS. +#@param int_ndisk nº de orden del disco +#@see ogListPartitions +#*/ ## +function ogListLogicalPartitions () +{ +# Variables locales. +local PTTYPE PARTS + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk" \ + "$FUNCNAME 1 => LINUX-SWAP:999998" + return +fi +PTTYPE=$(ogGetPartitionTableType $1) || return $? +[ "$PTTYPE" == "MSDOS" ] || ogRaiseError $OG_ERR_PARTITION "" || return $? +PARTS=$(ogListPartitions "$@") || return $? +echo $PARTS | cut -sf5- -d" " +} + + +#/** +# ogLockDisk int_ndisk +#@brief Genera un fichero de bloqueo para un disco en uso exlusivo. +#@param int_ndisk nº de orden del disco +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@note El fichero de bloqueo se localiza en \c /var/lock/disk, siendo \c disk el dispositivo del disco, sustituyendo el carácter "/" por "-". +#@version 1.1.0 - Primera versión para OpenGnsys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2016-04-07 +#*/ ## +function ogLockDisk () +{ +# Variables locales +local DISK LOCKFILE + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk" \ + "$FUNCNAME 1" + return +fi +# Error si no se recibe 1 parámetro. +[ $# == 1 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +# Obtener partición. +DISK="$(ogDiskToDev $1)" || return $? + +# Crear archivo de bloqueo exclusivo. +LOCKFILE="/var/lock/lock${DISK//\//-}" +touch $LOCKFILE +} + + +#/** +# ogSetPartitionActive int_ndisk int_npartition +#@brief Establece cual es la partición activa de un disco. +#@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 partición no corresponden con un dispositivo. +#@note Requisitos: parted +#@version 0.1 - Integracion para Opengnsys - EAC: SetPartitionActive() en ATA.lib +#@author Antonio J. Doblas Viso, Universidad de Malaga +#@date 2008/10/27 +#@version 0.9 - Primera version compatible con OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2009/09/17 +#*/ ## +function ogSetPartitionActive () +{ +# Variables locales +local DISK PART + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_npartition" \ + "$FUNCNAME 1 1" + return +fi + +# Si el EFI esta activo me salgo. +ogIsEfiActive && ogEcho session log warning "EFI: $MSG_DONTUSE $FUNCNAME" && return + +# Error si no se reciben 2 parámetros. +[ $# == 2 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +# Comprobar que el disco existe y activar la partición indicada. +DISK="$(ogDiskToDev $1)" || return $? +PART="$(ogDiskToDev $1 $2)" || return $? +parted -s $DISK set $2 boot on 2>/dev/null +} + + +#/** +# ogSetPartitionId int_ndisk int_npartition hex_partid +#@brief Cambia el identificador de la partición. +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@param hex_partid identificador de tipo de partición +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o partición no corresponden con un dispositivo. +#@exception OG_ERR_OUTOFLIMIT Valor no válido. +#@exception OG_ERR_PARTITION Error al cambiar el id. de partición. +#@attention Requisitos: fdisk, sgdisk +#@version 0.1 - Integracion para Opengnsys - SetPartitionType() en ATA.lib +#@author Antonio J. Doblas Viso. Universidad de Malaga +#@date 2008/10/27 +#@version 1.0.4 - Soporte para discos GPT. +#@author Universidad de Huelva +#@date 2012/03/13 +#@version 1.0.5 - Utiliza el id. de tipo de partición (no el mnemónico) +#@author Universidad de Huelva +#@date 2012/05/14 +#*/ ## +function ogSetPartitionId () +{ +# Variables locales +local DISK PART PTTYPE ID + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_npartition hex_partid" \ + "$FUNCNAME 1 1 7" + return +fi +# Error si no se reciben 3 parámetros. +[ $# == 3 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +# Sustituye nº de disco y nº partición por su dispositivo. +DISK=$(ogDiskToDev $1) || return $? +PART=$(ogDiskToDev $1 $2) || return $? +# Error si el id. de partición no es hexadecimal. +ID="${3^^}" +[[ "$ID" =~ ^[0-9A-F]+$ ]] || ogRaiseError $OG_ERR_OUTOFLIMIT "$3" || return $? + +# Elección del tipo de partición. +PTTYPE=$(ogGetPartitionTableType $1) +case "$PTTYPE" in + GPT) sgdisk -t$2:$ID $DISK 2>/dev/null ;; + MSDOS) sfdisk --id $DISK $2 $ID 2>/dev/null ;; + *) ogRaiseError $OG_ERR_OUTOFLIMIT "$1,$PTTYPE" + return $? ;; +esac + +# MSDOS) Correcto si fdisk sin error o con error pero realiza Syncing +if [ "${PIPESTATUS[1]}" == "0" -o $? -eq 0 ]; then + partprobe $DISK 2>/dev/null + return 0 +else + ogRaiseError $OG_ERR_PARTITION "$1,$2,$3" + return $? +fi +} + + +#/** +# ogSetPartitionSize int_ndisk int_npartition int_size +#@brief Muestra el tamano en KB de una particion determinada. +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@param int_size tamaño de la partición (en KB) +#@return (nada) +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND disco o particion no detectado (no es un dispositivo). +#@note Requisitos: sfdisk, awk +#@todo Compruebar que el tamaño sea numérico positivo y evitar que pueda solaparse con la siguiente partición. +#@version 0.9 - Primera versión para OpenGnSys +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2009/07/24 +#*/ ## +function ogSetPartitionSize () +{ +# Variables locales. +local DISK PART SIZE + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_npartition int_size" \ + "$FUNCNAME 1 1 10000000" + return +fi +# Error si no se reciben 3 parámetros. +[ $# == 3 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +# Obtener el tamaño de la partición. +DISK="$(ogDiskToDev $1)" || return $? +PART="$(ogDiskToDev $1 $2)" || return $? +# Convertir tamaño en KB a sectores de 512 B. +SIZE=$[$3*2] || ogRaiseError $OG_ERR_FORMAT || return $? +# Redefinir el tamaño de la partición. +sfdisk -f -uS -N$2 $DISK <<< ",$SIZE" &>/dev/null || ogRaiseError $OG_ERR_PARTITION "$1,$2" || return $? +partprobe $DISK 2>/dev/null +} + + +#/** +# ogSetPartitionType int_ndisk int_npartition str_type +#@brief Cambia el identificador de la partición. +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@param str_type mnemónico de tipo de partición +#@return (nada) +#@attention Requisitos: fdisk, sgdisk +#@version 0.1 - Integracion para Opengnsys - SetPartitionType() en ATA.lib +#@author Antonio J. Doblas Viso. Universidad de Malaga +#@date 2008/10/27 +#@version 1.0.4 - Soporte para discos GPT. +#@author Universidad de Huelva +#@date 2012/03/13 +#@version 1.0.5 - Renombrada de ogSetPartitionId. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2013/03/07 +#*/ ## +function ogSetPartitionType () +{ +# Variables locales +local DISK PART PTTYPE ID + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_npartition str_type" \ + "$FUNCNAME 1 1 NTFS" + return +fi +# Error si no se reciben 3 parámetros. +[ $# == 3 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +# Sustituye nº de disco por su dispositivo. +DISK=`ogDiskToDev $1` || return $? +PART=`ogDiskToDev $1 $2` || return $? + +# Elección del tipo de partición. +PTTYPE=$(ogGetPartitionTableType $1) +ID=$(ogTypeToId "$3" "$PTTYPE") +[ -n "$ID" ] || ogRaiseError $OG_ERR_FORMAT "$3,$PTTYPE" || return $? +ogSetPartitionId $1 $2 $ID +} + + +#/** +# 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) +#@version 0.1 - Integracion para Opengnsys - EAC: TypeFS () en ATA.lib +#@author Antonio J. Doblas Viso, Universidad de Malaga +#@date 2008/10/27 +#@version 0.9 - Primera version para OpenGnSys +#@author Ramon Gomez, ETSII Universidad Sevilla +#@date 2009-12-14 +#@version 1.0.4 - Soportar discos GPT (sustituye a ogFsToId). +#@author Universidad de Huelva +#@date 2012/03/30 +#*/ ## +function ogTypeToId () +{ +# Variables locales +local PTTYPE ID="" + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME str_parttype [str_tabletype]" \ + "$FUNCNAME LINUX => 83" \ + "$FUNCNAME LINUX MSDOS => 83" + return +fi +# Error si no se reciben 1 o 2 parámetros. +[ $# -lt 1 -o $# -gt 2 ] && (ogRaiseError $OG_ERR_FORMAT; return $?) + +# Asociar id. de partición para su mnemónico. +PTTYPE=${2:-"MSDOS"} +case "$PTTYPE" in + GPT) # Se incluyen mnemónicos compatibles con tablas MSDOS. + case "$1" in + EMPTY) ID=0 ;; + WINDOWS|NTFS|EXFAT|FAT32|FAT16|FAT12|HNTFS|HFAT32|HFAT16|HFAT12) + ID=0700 ;; + WIN-RESERV) ID=0C01 ;; + CHROMEOS-KRN) ID=7F00 ;; + CHROMEOS) ID=7F01 ;; + CHROMEOS-RESERV) ID=7F02 ;; + LINUX-SWAP) ID=8200 ;; + LINUX|EXT[234]|REISERFS|REISER4|XFS|JFS) + ID=8300 ;; + LINUX-RESERV) ID=8301 ;; + LINUX-LVM) ID=8E00 ;; + FREEBSD-DISK) ID=A500 ;; + FREEBSD-BOOT) ID=A501 ;; + FREEBSD-SWAP) ID=A502 ;; + FREEBSD) ID=A503 ;; + HFS-BOOT) ID=AB00 ;; + HFS|HFS+) ID=AF00 ;; + HFSPLUS) ID=AF00 ;; + HFS-RAID) ID=AF01 ;; + SOLARIS-BOOT) ID=BE00 ;; + SOLARIS) ID=BF00 ;; + SOLARIS-SWAP) ID=BF02 ;; + SOLARIS-DISK) ID=BF03 ;; + CACHE) ID=CA00;; + EFI) ID=EF00 ;; + LINUX-RAID) ID=FD00 ;; + esac + ;; + MSDOS) + case "$1" in + EMPTY) ID=0 ;; + FAT12) ID=1 ;; + EXTENDED) ID=5 ;; + FAT16) ID=6 ;; + WINDOWS|NTFS|EXFAT) + ID=7 ;; + FAT32) ID=b ;; + HFAT12) ID=11 ;; + HFAT16) ID=16 ;; + HNTFS) ID=17 ;; + HFAT32) ID=1b ;; + LINUX-SWAP) ID=82 ;; + LINUX|EXT[234]|REISERFS|REISER4|XFS|JFS) + ID=83 ;; + LINUX-LVM) ID=8e ;; + FREEBSD) ID=a5 ;; + OPENBSD) ID=a6 ;; + HFS|HFS+) ID=af ;; + SOLARIS-BOOT) ID=be ;; + SOLARIS) ID=bf ;; + CACHE) ID=ca ;; + DATA) ID=da ;; + GPT) ID=ee ;; + EFI) ID=ef ;; + VMFS) ID=fb ;; + LINUX-RAID) ID=fd ;; + esac + ;; + LVM) + case "$1" in + LVM-LV) ID=10000 ;; + esac + ;; + ZVOL) + case "$1" in + ZFS-VOL) ID=10010 ;; + esac + ;; +esac +echo $ID +} + + +#/** +# 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. +#@version 1.0 - Versión en pruebas. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2010/01/12 +#@version 1.1.1 - Se incluye tipo Windows Reserver para UEFI (ticket #802) +#@author Irina Gomez, ETSII Universidad de Sevilla +#@date 2019/01/18 +#*/ ## +function ogUnhidePartition () +{ +# Variables locales. +local PART TYPE NEWTYPE +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_npartition" \ + "$FUNCNAME 1 1" + return +fi +# Error si no se reciben 2 parámetros. +[ $# == 2 ] || ogRaiseError $OG_ERR_FORMAT || return $? +PART=$(ogDiskToDev "$1" "$2") || return $? + +# Obtener tipo de partición. +TYPE=$(ogGetPartitionType "$1" "$2") +case "$TYPE" in + HNTFS) NEWTYPE="NTFS" ;; + HFAT32) NEWTYPE="FAT32" ;; + HFAT16) NEWTYPE="FAT16" ;; + HFAT12) NEWTYPE="FAT12" ;; + WIN-RESERV) NEWTYPE="WINDOWS" ;; + *) ogRaiseError $OG_ERR_PARTITION "$TYPE" + return $? ;; +esac +# Cambiar tipo de partición. +ogSetPartitionType $1 $2 $NEWTYPE +} + + +#/** +# ogUnlockDisk int_ndisk +#@brief Elimina el fichero de bloqueo para un disco. +#@param int_ndisk nº de orden del disco +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@note El fichero de bloqueo se localiza en \c /var/lock/disk, siendo \c disk el dispositivo del disco, sustituyendo el carácter "/" por "-". +#@version 1.1.0 - Primera versión para OpenGnsys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2016-04-08 +#*/ ## +function ogUnlockDisk () +{ +# Variables locales +local DISK LOCKFILE + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk" \ + "$FUNCNAME 1" + return +fi +# Error si no se recibe 1 parámetro. +[ $# == 1 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +# Obtener partición. +DISK="$(ogDiskToDev $1)" || return $? + +# Borrar archivo de bloqueo exclusivo. +LOCKFILE="/var/lock/lock${DISK//\//-}" +rm -f $LOCKFILE +} + + +#/** +# ogUpdatePartitionTable +#@brief Fuerza al kernel releer la tabla de particiones de los discos duros +#@param no requiere +#@return informacion propia de la herramienta +#@note Requisitos: \c partprobe +#@warning pendiente estructurar la funcion a opengnsys +#@version 0.1 - Integracion para Opengnsys - EAC: UpdatePartitionTable() en ATA.lib +#@author Antonio J. Doblas Viso. Universidad de Malaga +#@date 27/10/2008 +#*/ ## +function ogUpdatePartitionTable () +{ +local i +for i in `ogDiskToDev` +do + partprobe $i +done +} diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py deleted file mode 100755 index ece1339..0000000 --- a/client/lib/engine/bin/DiskLib.py +++ /dev/null @@ -1,1417 +0,0 @@ -#/** -#@file DiskLib.py -#@brief Librería o clase Disk -#@class Disk -#@brief Funciones para gestión de discos y particiones. -#@warning License: GNU GPLv3+ -#*/ - -import filecmp -import subprocess -import shutil -import os -import re -import stat -from pathlib import Path - -import ogGlobals -import SystemLib -import CacheLib -import FileSystemLib -import InventoryLib - -# Función ficticia para lanzar parted con timeout, evitando cuelgues del programa. -def parted(*args): - parted_path = shutil.which("parted") - if parted_path: - try: - result = subprocess.run( - [parted_path] + list(args), - timeout=3, - capture_output=True, - text=True - ) - return result.stdout - except subprocess.TimeoutExpired: - return "Error: Command 'parted' timed out" - else: - return "Error: 'parted' command not found" - - -#/** -# ogCreatePartitions int_ndisk str_parttype:int_partsize ... -#@brief Define el conjunto de particiones de un disco. -#@param int_ndisk nº de orden del disco -#@param str_parttype mnemónico del tipo de partición -#@param int_partsize tamaño de la partición (en KB) -#@return (nada, por determinar) -#@exception OG_ERR_FORMAT formato incorrecto. -#@exception OG_ERR_NOTFOUND disco o partición no detectado (no es un dispositivo). -#@exception OG_ERR_PARTITION error en partición o en tabla de particiones. -#@attention El nº de partición se indica por el orden de los párametros \c parttype:partsize -#@attention Pueden definirse particiones vacías de tipo \c EMPTY -#@attention No puede definirse partición de cache y no se modifica si existe. -#@note Requisitos: sfdisk, parted, partprobe, awk -#@todo Definir atributos (arranque, oculta) y tamaños en MB, GB, etc. -#*/ ## -def ogCreatePartitions (disk, parts): - ND = disk - DISK = ogDiskToDev (ND) - if not DISK: return None - - PTTYPE = ogGetPartitionTableType (disk) - if not PTTYPE: PTTYPE = 'MSDOS' # Por defecto para discos vacíos. - - if 'GPT' == PTTYPE: - return ogCreateGptPartitions (disk, parts) - elif 'MSDOS' != PTTYPE: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, PTTYPE) - return None - - # Se calcula el ultimo sector del disco (total de sectores usables) - SECTORS = ogGetLastSector (disk) - - # Se recalcula el nº de sectores del disco si existe partición de caché. - CACHESIZE = 0 - CACHEPART = CacheLib.ogFindCache() - if CACHEPART: - cache_disk, cache_part = CACHEPART.split() - if ND == cache_disk: - CACHESIZE = int (CacheLib.ogGetCacheSize()) * 2 - # Sector de inicio (la partición 1 empieza en el sector 63). - IODISCO = ogDiskToDev (disk) - IOSIZE = 0 - fdisk_out = subprocess.run (['fdisk', '-l', IODISCO], capture_output=True, text=True).stdout - for l in fdisk_out.splitlines(): - if 'I/O' not in l: continue - items = l.split() - if len(items) < 4: continue - IOSIZE = items[3] - break - - if '4096' == IOSIZE: - START = 4096 - SECTORS -= 8192 - if CACHESIZE: - SECTORS = SECTORS - CACHESIZE + 2048 - (SECTORS - CACHESIZE) % 2048 - 1 - else: - START = 63 - if CACHESIZE: - SECTORS -= CACHESIZE - - PART = 1 - - sfdisk_input = 'unit: sectors\n\n' - NVME_PREFIX = 'p' if 'nvme' in DISK else '' - for p in parts: - # Conservar los datos de la partición de caché. - if f'{ND} {PART}' == CACHEPART and CACHESIZE: - sfdisk_input += f'{DISK}{NVME_PREFIX}{PART} : start={SECTORS+1}, size={CACHESIZE}, Id=ca\n' - PART += 1 - - # Leer formato de cada parámetro - Tipo:Tamaño - TYPE, SIZE = p.split (':') - try: - SIZE = int (SIZE) - except ValueError: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, SIZE) - return None - - # Obtener identificador de tipo de partición válido. - ID = ogTypeToId (TYPE, 'MSDOS') - if 'CACHE' == TYPE or not ID: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, TYPE) - return None - # Comprobar tamaño numérico y convertir en sectores de 512 B. - SIZE *= 2 - # Comprobar si la partición es extendida. - EXTSTART = EXTSIZE = 0 - if 5 == ID: - if PART > 4: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, '') - return None - # El inicio de la primera partición logica es el de la extendida más 4x512 - EXTSTART = START+2048 - EXTSIZE = SIZE-2048 - # Incluir particiones lógicas dentro de la partición extendida. - if 5 == PART: - if not EXTSTART: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, '') - return None - START = EXTSTART - SECTORS = EXTSTART+EXTSIZE - - # Generar datos para la partición. - # En el caso de que la partición sea EMPTY no se crea nada - if 'EMPTY' != TYPE: - sfdisk_input += f'{DISK}{NVME_PREFIX}{PART} : start={START}, size={SIZE}, Id={ID}\n' - - START += SIZE - - # Error si se supera el nº total de sectores. - if '4096' == IOSIZE and PART > 4: - START += 2048 - if START > SECTORS: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'{START//2} > {SECTORS//2}') - return None - PART += 1 - - # Si no se indican las 4 particiones primarias, definirlas como vacías, conservando la partición de caché. - while PART <= 4: - if f'{ND} {PART}' == CACHEPART and CACHESIZE: - sfdisk_input += f'{DISK}{NVME_PREFIX}{PART} : start={SECTORS+1}, size={CACHESIZE}, Id=ca\n' - else: - sfdisk_input += f'{DISK}{NVME_PREFIX}{PART} : start=0, size=0, Id=0\n' - PART += 1 - # Si se define partición extendida sin lógicas, crear particion 5 vacía. - if 5 == PART and EXTSTART: - sfdisk_input += f'{DISK}5 : start={EXTSTART}, SIZE={EXTSIZE}, Id=0\n' - - # Desmontar los sistemas de archivos del disco antes de realizar las operaciones. - FileSystemLib.ogUnmountAll (ND) - if CACHESIZE: CacheLib.ogUnmountCache() - - # Si la tabla de particiones no es valida, volver a generarla. - ogCreatePartitionTable (ND) - - # Definir particiones y notificar al kernel. - subprocess.run (['sfdisk', DISK], input=sfdisk_input, capture_output=True, text=True) - subprocess.run (['partprobe', DISK]) - if CACHESIZE: CacheLib.ogMountCache() - return True - - -#/** -# ogCreateGptPartitions int_ndisk str_parttype:int_partsize ... -#@brief Define el conjunto de particiones de un disco GPT -#@param int_ndisk nº de orden del disco -#@param str_parttype mnemónico del tipo de partición -#@param int_partsize tamaño de la partición (en KB) -#@return (nada, por determinar) -#@exception OG_ERR_FORMAT formato incorrecto. -#@exception OG_ERR_NOTFOUND disco o partición no detectado (no es un dispositivo). -#@exception OG_ERR_PARTITION error en partición o en tabla de particiones. -#@attention El nº de partición se indica por el orden de los párametros \c parttype:partsize -#@attention Pueden definirse particiones vacías de tipo \c EMPTY -#@attention No puede definirse partición de caché y no se modifica si existe. -#@note Requisitos: sfdisk, parted, partprobe, awk -#@todo Definir atributos (arranque, oculta) y tamaños en MB, GB, etc. -#*/ ## -def ogCreateGptPartitions (disk, parts): - ND = disk - DISK = ogDiskToDev (ND) - if not DISK: return None - - # Se calcula el ultimo sector del disco (total de sectores usables) - SECTORS = ogGetLastSector (disk) - - # Se recalcula el nº de sectores del disco si existe partición de caché. - CACHESIZE = 0 - CACHEPART = CacheLib.ogFindCache() - if CACHEPART: - cache_disk, cache_part = CACHEPART.split() - if ND == cache_disk: - CACHESIZE = int (CacheLib.ogGetCacheSize()) * 2 - if CACHESIZE: - SECTORS -= CACHESIZE - - # Si el disco es GPT empieza en el sector 2048 por defecto, pero podria cambiarse - ALIGN = int (subprocess.run (['sgdisk', '-D', DISK], capture_output=True, text=True).stdout) - START = ALIGN - PART = 1 - - # Leer parámetros con definición de particionado. - DELOPTIONS = [] - OPTIONS = [] - for p in parts: - # Conservar los datos de la partición de caché. - if f'{ND} {PART}' == CACHEPART and CACHESIZE: - PART += 1 - - # Leer formato de cada parámetro - Tipo:Tamaño - TYPE, SIZE = p.split (':') - try: - SIZE = int (SIZE) - except ValueError: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, SIZE) - return None - - # Error si la partición es extendida (no válida en discos GPT). - if 'EXTENDED' == TYPE: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, 'EXTENDED') - return None - - # Comprobar si existe la particion actual, capturamos su tamaño para ver si cambio o no - PARTSIZE = ogGetPartitionSize (ND, PART) - # En sgdisk no se pueden redimensionar las particiones, es necesario borrarlas y volver a crealas - if PARTSIZE: - DELOPTIONS.append (f'-d{PART}') - - # Creamos la particion - # Obtener identificador de tipo de partición válido. - ID = ogTypeToId (TYPE, 'GPT') - if 'CACHE' == TYPE or not ID: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, TYPE) - return None - # Comprobar tamaño numérico y convertir en sectores de 512 B. - SIZE *= 2 - # SIZE debe ser múltiplo de ALIGN, si no gdisk lo mueve automáticamente. - SIZE = (SIZE // ALIGN) * ALIGN - - # Generar datos para la partición. - # En el caso de que la partición sea EMPTY no se crea nada - if 'EMPTY' != TYPE: - OPTIONS += [f'-n{PART}:{START}:+{SIZE}', f'-t{PART}:{ID}'] - - START += SIZE - - # Error si se supera el nº total de sectores. - if START > SECTORS: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'{START//2} > {SECTORS//2}') - return None - - PART += 1 - - # Desmontar los sistemas de archivos del disco antes de realizar las operaciones. - FileSystemLib.ogUnmountAll (ND) - if CACHESIZE: CacheLib.ogUnmountCache() - - # Si la tabla de particiones no es valida, volver a generarla. - ogCreatePartitionTable (ND, 'GPT') - - # Definir particiones y notificar al kernel. - subprocess.run (['sgdisk'] + DELOPTIONS + OPTIONS + [DISK]) - subprocess.run (['partprobe', DISK]) - if CACHESIZE: CacheLib.ogMountCache() - return True - - -#/** -# ogCreatePartitionTable int_ndisk [str_tabletype] -#@brief Genera una tabla de particiones en caso de que no sea valida, si es valida no hace nada. -#@param int_ndisk nº de orden del disco -#@param str_tabletype tipo de tabla de particiones (opcional) -#@return (por determinar) -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. -#@note tabletype: { MSDOS, GPT }, MSDOS por defecto -#@note Requisitos: fdisk, gdisk, parted -#*/ ## -def ogCreatePartitionTable (disk, createptt=None): - DISK = ogDiskToDev (disk) - if not DISK: return None - - pttype = ogGetPartitionTableType (disk) or 'MSDOS' # Por defecto para discos vacíos. - createptt = createptt or pttype - CREATE = None - -# Si la tabla actual y la que se indica son iguales, se comprueba si hay que regenerarla. - if createptt == pttype: - if 'GPT' == pttype: - try: - result = subprocess.run (['sgdisk', '-p', DISK], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) - if result.returncode: - CREATE = 'GPT' - except subprocess.CalledProcessError: - CREATE = 'GPT' - elif 'MSDOS' == pttype: - try: - result = subprocess.run (['parted', '-s', DISK, 'print'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) - if result.returncode: - CREATE = 'MSDOS' - except subprocess.CalledProcessError: - CREATE = 'MSDOS' - else: - CREATE = createptt.upper() - -# Dependiendo del valor de CREATE, creamos la tabla de particiones en cada caso. - if 'GPT' == CREATE: - if 'MSDOS' == pttype: - subprocess.run (['sgdisk', '-go', DISK]) - else: - subprocess.run (['gdisk', DISK], input='2\nw\nY\n', text=True) - subprocess.run (['partprobe', DISK]) - elif 'MSDOS' == CREATE: - if 'GPT' == pttype: - subprocess.run (['sgdisk', '-Z', DISK]) - # Crear y borrar una partición para que la tabla se genere bien. - subprocess.run (['fdisk', DISK], input='o\nn\np\n\n\n\nd\n\nw', text=True) - subprocess.run (['partprobe', DISK]) - - return None - - -#/** -# ogDeletePartitionTable ndisk -#@brief Borra la tabla de particiones del disco. -#@param int_ndisk nº de orden del disco -#@return la informacion propia del fdisk -#*/ ## -def ogDeletePartitionTable (disk): - DISK = ogDiskToDev (disk) - if not DISK: return None - - PTTYPE = ogGetPartitionTableType (disk) - if 'GPT' == PTTYPE: - subprocess.run (['sgdisk', '--clear', DISK]) - elif 'MSDOS' == PTTYPE: - subprocess.run (['fdisk', DISK], input='o\nw', text=True) - return - -#/** -# ogDevToDisk path_device | LABEL="str_label" | UUID="str_uuid" -#@brief Devuelve el nº de orden de dicso (y partición) correspondiente al nombre de fichero de dispositivo o a la etiqueta o UUID del sistema de archivos asociado. -#@param path_device Camino del fichero de dispositivo. -#@param str_label etiqueta de sistema de archivos. -#@param str_uuid UUID de sistema de archivos. -#@return int_ndisk (para dispositivo de disco) -#@return int_ndisk int_npartition (para dispositivo de partición). -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_NOTFOUND Dispositivo no detectado. -#@note Solo se acepta en cada llamada 1 de los 3 tipos de parámetros. -#*/ ## -def ogDevToDisk(arg_dev): - CACHEFILE = "/var/cache/disks.cfg" - - if '=' in arg_dev: - # arg_dev is "FOO=bar" - cmd = None - if arg_dev.startswith("LABEL="): cmd = ['blkid', '-L', arg_dev[6:]] - elif arg_dev.startswith("PARTLABEL="): cmd = ['realpath', '/dev/disk/by-partlabel/'+arg_dev[11:]] - elif arg_dev.startswith("PARTUUID="): cmd = ['realpath', '/dev/disk/by-partuuid/'+arg_dev[10:]] - elif arg_dev.startswith("UUID="): cmd = ['blkid', '-U', arg_dev[5:]] - if not cmd: - SystemLib.ogRaiseError([], ogGlobals.OG_ERR_FORMAT, arg_dev) - return - DEV = subprocess.run (cmd, capture_output=True, text=True).stdout.strip() - else: - # arg_dev is "/dev/something" - DEV = arg_dev - - if not os.path.exists(DEV): - SystemLib.ogRaiseError([], ogGlobals.OG_ERR_NOTFOUND, arg_dev) - return - - # Error si no es fichero de bloques o directorio (para LVM). - m = os.stat (DEV, follow_symlinks=True).st_mode - if not stat.S_ISBLK (m) and not stat.S_ISDIR (m): - SystemLib.ogRaiseError([], ogGlobals.OG_ERR_NOTFOUND, arg_dev) - return - - # Buscar en fichero de caché de discos. - PART = None - if os.path.exists(CACHEFILE): - with open(CACHEFILE, 'r') as f: - for line in f: - parts = line.strip().split(':') - if len(parts) == 2 and parts[1] == DEV: - PART = parts[0] - break - - if PART: return PART - - # Si no se encuentra, procesa todos los discos para devolver su nº de orden y de partición. - disks = ogDiskToDev() - n = 1 - for d in disks: - NVME_PREFIX = "p" if "nvme" in d else "" - if DEV.startswith(d): - return f"{n} {DEV[len(d) + len(NVME_PREFIX):]}" - n += 1 - - SystemLib.ogRaiseError([], ogGlobals.OG_ERR_NOTFOUND, arg_dev) - return - -def _getAllDisks(): - ret = [] - all_disks = subprocess.run("lsblk -n -e 1,2 -x MAJ:MIN 2>/dev/null || lsblk -n -e 1,2", shell=True, capture_output=True, text=True).stdout.splitlines() - for line in all_disks: - parts = line.split() - if parts[5] == "disk": - parts[0].replace ('!', '/') - ret.append(f"/dev/{parts[0]}") - return ret - -def _getAllVolGroups(): - vgs = subprocess.run(['vgs', '-a', '--noheadings'], capture_output=True, text=True).stdout.splitlines() - ret = [f"/dev/{line.split()[0]}" for line in vgs] - return ret - -def _getMPath(): - ret = alldisks2remove = [] - try: - mpath = subprocess.run(['multipath', '-l', '-v', '1'], capture_output=True, text=True).stdout.splitlines() - ret = [f"/dev/mapper/{line.split()[0]}" for line in mpath] - for line in subprocess.getoutput("multipath -ll").splitlines(): - if line.split()[5] == "ready": - alldisks2remove.append (f"/dev/{line.split()[2]}") - except FileNotFoundError: - pass - except subprocess.CalledProcessError: - pass - return ret, alldisks2remove - -def _getAllZFSVols(): - zfsvols = subprocess.run(['blkid'], capture_output=True, text=True).stdout.splitlines() - return [line.split(":")[0] for line in zfsvols if "zfs" in line] - -#/** -# ogDiskToDev [int_ndisk [int_npartition]] -#@brief Devuelve la equivalencia entre el nº de orden del dispositivo (dicso o partición) y el nombre de fichero de dispositivo correspondiente. -#@param int_ndisk nº de orden del disco -#@param int_npartition nº de orden de la partición -#@return Para 0 parametros: Devuelve los nombres de ficheros de los dispositivos sata/ata/usb linux encontrados. -#@return Para 1 parametros: Devuelve la ruta del disco duro indicado. -#@return Para 2 parametros: Devuelve la ruta de la particion indicada. -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_NOTFOUND Dispositivo no detectado. -#*/ ## -def ogDiskToDev (arg_disk=None, arg_part=None): - CACHEFILE = "/var/cache/disks.cfg" - - try: - if arg_part != None: - arg_part = int (arg_part) - except: - SystemLib.ogRaiseError([], ogGlobals.OG_ERR_FORMAT, f"{arg_disk} {arg_part}") - return - - try: - if arg_disk != None: - arg_disk = int (arg_disk) - except: - SystemLib.ogRaiseError([], ogGlobals.OG_ERR_FORMAT, arg_disk) - return - - # Borrar fichero de caché de configuración si hay cambios en las particiones. - proc_partitions = Path ('/proc/partitions').read_text() - tmp_partitions = Path ('/tmp/.partitions').read_text() if os.path.exists ('/tmp/.partitions') else '' - if proc_partitions != tmp_partitions: - # Guardar copia de las particiones definidas para comprobar cambios. - shutil.copy2('/proc/partitions', '/tmp/.partitions') - try: - os.remove(CACHEFILE) - except FileNotFoundError: - pass - - # Si existe una correspondencia con disco/dispositivo en el caché; mostrarlo y salir. - if arg_disk and os.path.exists (CACHEFILE): - with open(CACHEFILE, 'r') as f: - args_joined = ' '.join (map (str, filter (None, [arg_disk,arg_part]))) - for line in f: - parts = line.strip().split(':') - if len(parts) == 2 and parts[0] == args_joined: - return parts[1] - - # Continuar para detectar nuevos dispositivos. - - ALLDISKS = _getAllDisks() - - VOLGROUPS = _getAllVolGroups() - ALLDISKS += VOLGROUPS - - MPATH, ALLDISKS_to_remove =_getMPath() - for d in ALLDISKS_to_remove: - if d in ALLDISKS: ALLDISKS.remove (d) - - ZFSVOLS = _getAllZFSVols() - ALLDISKS += ZFSVOLS - - # No params: return all disks - if arg_disk is None: - return ALLDISKS - - # arg_disk is set: return it - if arg_part is None: - 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) - return - # Actualizar caché de configuración y mostrar dispositivo. - with open(CACHEFILE, 'a') as f: - f.write(f"{arg_disk}:{disk}\n") - 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) - return - - # Plain partition - part = f"{disk}{arg_part}" - if os.path.exists(part): - # Actualizar caché de configuración y mostrar dispositivo. - with open(CACHEFILE, 'a') as f: - f.write(f"{arg_disk} {arg_part}:{part}\n") - return part - - # RAID/Multipath (tener en cuenta enlace simbólico). - part = f"{disk}p{arg_part}" - if os.path.exists(part) and stat.S_ISBLK (os.stat (part, follow_symlinks=True).st_mode): - # Actualizar caché de configuración y mostrar dispositivo. - with open(CACHEFILE, 'a') as f: - f.write(f"{arg_disk} {arg_part}:{part}\n") - return part - - part = "" - # Logical volume - if disk in VOLGROUPS: - lvscan = subprocess.run (['lvscan', '-a'], capture_output=True, text=True).stdout.splitlines() - i = 0 - for line in lvscan: - parts = line.split("'") - if parts[1].startswith(f"{disk}/") and i == arg_part: - part = parts[1] - break - i += 1 - - # ZFS volume - if disk in ZFSVOLS: - subprocess.run(["zpool", "import", "-f", "-R", "/mnt", "-N", "-a"]) - zpool = subprocess.run(['blkid', '-s', 'LABEL', '-o', 'value', disk], capture_output=True, text=True).stdout - zfs_list = subprocess.run(['zfs', 'list', '-Hp', '-o', 'name,canmount,mountpoint', '-r', zpool], capture_output=True, text=True).stdout.splitlines() - i = 0 - for line in zfs_list: - parts = line.split() - if parts[1] == "on" and parts[2] != "none": - if i == int(args[1]): - part = parts[0] - break - i += 1 - - if not part: - SystemLib.ogRaiseError([], ogGlobals.OG_ERR_NOTFOUND, f"{arg_disk} {arg_part}") - return - - # Actualizar caché de configuración y mostrar dispositivo. - with open(CACHEFILE, 'a') as f: - f.write(f"{arg_disk} {arg_part}:{part}\n") - - return part - - -#/** -# ogGetDiskSize int_ndisk -#@brief Muestra el tamaño en KB de un disco. -#@param int_ndisk nº de orden del disco -#@return int_size - Tamaño en KB del disco. -#@exception OG_ERR_FORMAT formato incorrecto. -#@exception OG_ERR_NOTFOUND disco o particion no detectado (no es un dispositivo). -#@note Requisitos: sfdisk, awk -#*/ ## -def ogGetDiskSize (disk): - DISK = ogDiskToDev (disk) - if not DISK: return None - - bn = os.path.basename (DISK) - SIZE = None - with open ('/proc/partitions', 'r') as fd: - while True: - l = fd.readline() - if not l: break - items = l.split() - if len(items) < 4: continue - if items[3] == bn: - SIZE = int (items[2]) - break - if not SIZE: - vgs_out = subprocess.run (['vgs', '--noheadings', '--units=B', '-o', 'dev_size', DISK], capture_output=True, text=True).stdout - items = vgs_out.split() - SIZE = int (items[0]) // 1024 - - return SIZE - - -#/** -# ogGetDiskType path_device -#@brief Muestra el tipo de disco (real, RAID, meta-disco, USB, etc.). -#@param path_device Dispositivo -#@exception OG_ERR_FORMAT formato incorrecto. -#@exception OG_ERR_NOTFOUND disco no detectado o no es un dispositivo de bloques. -#@note Requisitos: udevadm -#*/ ## -def ogGetDiskType (dev): - DEV = os.path.basename (dev) - - bn = os.path.basename (DEV) - MAJOR = None - with open ('/proc/partitions', 'r') as fd: - while True: - l = fd.readline() - if not l: break - items = l.split() - if len(items) < 4: continue - if items[3] == bn: - MAJOR = items[0] - break - - TYPE = None - with open ('/proc/devices', 'r') as fd: - within_block_section = False - while True: - l = fd.readline() - if not l: break - - if 'Block' in l: - within_block_section = True - continue - if not within_block_section: - continue - - items = l.split() - if len(items) < 2: continue - if items[0] == MAJOR: - TYPE = items[1].upper() - break - - # Devolver mnemónico del driver de dispositivo. - if 'SD' == TYPE: - TYPE = 'DISK' - udevadm_out = subprocess.run (['udevadm', 'info', '-q', 'property', dev], capture_output=True, text=True).stdout - for l in udevadm_out.splitlines(): - if 'ID_BUS=usb' == l[0:10]: - TYPE = 'USB' - elif 'BLKEXT' == TYPE: - TYPE = 'NVM' - elif 'SR' == TYPE or TYPE.startswith ('IDE'): - TYPE = 'CDROM' # FIXME Comprobar discos IDE. - elif 'MD' == TYPE or TYPE.startswith ('CCISS'): - TYPE = 'RAID' - elif 'DEVICE-MAPPER' == TYPE: - TYPE = 'MAPPER' # FIXME Comprobar LVM y RAID. - - return TYPE - - -#/** -# 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) - 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 - if len (PART) > 1: - disk, par = PART.split() - if ogGetPartitionId (disk, par) == ogTypeToId ('EFI', 'GPT'): - return PART - return None - - -#/** -# ogGetLastSector int_ndisk [int_npart] -#@brief Devuelve el último sector usable del disco o de una partición. -#@param int_ndisk nº de orden del disco -#@param int_npart nº de orden de la partición (opcional) -#@return Último sector usable. -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_NOTFOUND Disco o partición no corresponde con un dispositivo. -#@note Requisitos: sfdisk, sgdisk -#*/ ## -def ogGetLastSector (disk, par=None): - DISK = ogDiskToDev (disk) - if not DISK: return None - env = os.environ - env['LANG'] = 'C' - last = None - if par: - PART = ogDiskToDev (disk, par) - if not PART: return None - sgdisk_out = subprocess.run (['sgdisk', '-p', DISK], env=env, capture_output=True, text=True).stdout - for l in sgdisk_out.splitlines(): - items = l.split() - if len(items) < 3: continue - if str (par) != items[0]: continue - last = int (items[2]) - break - - else: - sgdisk_out = subprocess.run (['sgdisk', '-p', DISK], env=env, capture_output=True, text=True).stdout - for l in sgdisk_out.splitlines(): - if 'last usable sector' not in l: continue - items = l.split() - last = int (items[-1]) - - return last - - -#/** -# ogGetPartitionActive int_ndisk -#@brief Muestra que particion de un disco esta marcada como de activa. -#@param int_ndisk nº de orden del disco -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. -#@note Requisitos: parted -#@todo Queda definir formato para atributos (arranque, oculta, ...). -#*/ ## -def ogGetPartitionActive (disk): - DISK = ogDiskToDev (disk) - if DISK is None: return - - if 'LANG' in os.environ: - lang = os.environ['LANG'] - - ret = None - os.environ['LANG'] = 'C' - lines = subprocess.run (['parted', '--script', '--machine', DISK, 'print'], capture_output=True, text=True).stdout.splitlines() - for line in lines: - parts = line.split (':') - if len (parts) < 6: continue - if 'boot' in parts[6]: - ret = parts[0] - break - - if lang is None: - del os.environ['LANG'] - else: - os.environ['LAMG'] = lang - - return ret - - -#/** -# 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 - fsid = None - - 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 == str(par): - fsid = code - break - if fsid == '8300' and f'{disk} {par}' == CacheLib.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' - - return fsid - - -#/** -# ogGetPartitionSize int_ndisk int_npartition -#@brief Muestra el tamano en KB de una particion determinada. -#@param int_ndisk nº de orden del disco -#@param int_npartition nº de orden de la partición -#@return int_partsize - Tamaño en KB de la partición. -#@exception OG_ERR_FORMAT formato incorrecto. -#@exception OG_ERR_NOTFOUND disco o particion no detectado (no es un dispositivo). -#@note Requisitos: sfdisk, awk -#*/ ## -def ogGetPartitionSize (disk, par): - PART = ogDiskToDev (disk, par) - if PART is None: return - - sz = subprocess.run (['partx', '-gbo', 'SIZE', PART], capture_output=True, text=True).stdout.strip() - if sz: return int (int (sz) / 1024) - - sz = subprocess.run (['lvs', '--noheadings', '-o', 'lv_size', '--units', 'k', PART], capture_output=True, text=True).stdout.strip() - if sz: return int (sz) - - return FileSystemLib.ogGetFsSize (disk, par) - - -#/** -# ogGetPartitionsNumber int_ndisk -#@brief Detecta el numero de particiones del disco duro indicado. -#@param int_ndisk nº de orden del disco -#@return Devuelve el numero paritiones del disco duro indicado -#@warning Salidas de errores no determinada -#@attention Requisitos: parted -#@note Notas sin especificar -#*/ ## -def ogGetPartitionsNumber (disk): - DISK = ogDiskToDev (disk) - if not DISK: return None - out = 0 - - pttype = ogGetPartitionTableType (disk) - if pttype in ['GPT', 'MSDOS']: - partx_out = subprocess.run (['partx', '-gso', 'NR', DISK], capture_output=True, text=True).stdout - lines = partx_out.splitlines() - if len(lines): - out = lines[-1].strip() - elif 'LVM' == pttype: - lvs_out = subprocess.run (['lvs', '--noheadings', DISK], capture_output=True, text=True).stdout - lines = lvs_out.splitlines() - out = len (lines) - elif 'ZPOOL' == pttype: - if subprocess.run (['zpool', 'list']).returncode: - subprocess.run (['modprobe', 'zfs']) - subprocess.run (['zpool', 'import', '-f', '-R', '/mnt', '-N', '-a']) - blkid = subprocess.run (['blkid', '-s', 'LABEL', '-o', 'value', DISK], capture_output=True, text=True).stdout - zfs_out = subprocess.run (['zfs', 'list', '-Hp', '-o', 'name,canmount,mountpoint', '-r', blkid], capture_output=True, text=True).stdout - out = 0 - for l in zfs_out.splitlines(): - items = l.split() - if len(items) < 3: continue - if 'on' == items[1] and 'none' != items[2]: out += 1 - - return int (out) - - -#/** -# 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 - - 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 - - # Comprobar si es volumen lógico. - if os.path.isdir (DISK) and 0 == subprocess.run (['vgs', DISK]).returncode: - type = 'LVM' - - # Comprobar si es pool de ZFS. - if not type or 'UNKNOWN' == type: - if 'zfs' in subprocess.run (['blkid', '-s', 'TYPE', DISK], capture_output=True, text=True).stdout: - type = 'ZPOOL' - - 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 (disk, par): - ID = ogGetPartitionId (disk, par) - if ID is None: return None - - return ogIdToType (ID) - - -#/** -# ogHidePartition int_ndisk int_npartition -#@brief Oculta un apartición visible. -#@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 ogHidePartition (disk, par): - PART = ogDiskToDev (disk, par) - if not PART: return None - - TYPE = ogGetPartitionType (disk, par) - if 'NTFS' == TYPE: NEWTYPE = 'HNTFS' - elif 'FAT32' == TYPE: NEWTYPE = 'HFAT32' - elif 'FAT16' == TYPE: NEWTYPE = 'HFAT16' - elif 'FAT12' == TYPE: NEWTYPE = 'HFAT12' - elif 'WINDOWS' == TYPE: NEWTYPE = 'WIN-RESERV' - else: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, TYPE) - return None - - ogSetPartitionType (disk, par, NEWTYPE) - - -#/** -# ogIdToType int_idpart -#@brief Devuelve el identificador correspondiente a un tipo de partición. -#@param int_idpart identificador de tipo de partición. -#@return str_parttype mnemónico de tipo de partición. -#@exception OG_ERR_FORMAT Formato incorrecto. -#*/ ## -def ogIdToType (ID): - # Obtener valor hexadecimal de 4 caracteres rellenado con 0 por delante. - ID = ID.zfill(4).lower() - - id2type = { - '0000': 'EMPTY', - '0001': 'FAT12', - '0005': 'EXTENDED', - '000f': 'EXTENDED', - '0006': 'FAT16', - '000e': 'FAT16', - '0007': 'NTFS', - '000b': 'FAT32', - '000c': 'FAT32', - '0011': 'HFAT12', - '0012': 'COMPAQDIAG', - '0016': 'HFAT16', - '001e': 'HFAT16', - '0017': 'HNTFS', - '001b': 'HFAT32', - '001c': 'HFAT32', - '0042': 'WIN-DYNAMIC', - '0082': 'LINUX-SWAP', - '8200': 'LINUX-SWAP', - '0083': 'LINUX', - '8300': 'LINUX', - '008e': 'LINUX-LVM', - '8E00': 'LINUX-LVM', - '00a5': 'FREEBSD', - 'a503': 'FREEBSD', - '00a6': 'OPENBSD', - '00a7': 'CACHE', # (compatibilidad con Brutalix) - '00af': 'HFS', - 'af00': 'HFS', - '00be': 'SOLARIS-BOOT', - 'be00': 'SOLARIS-BOOT', - '00bf': 'SOLARIS', - 'bf00145': 'SOLARIS', - '00ca': 'CACHE', - 'ca00': 'CACHE', - '00da': 'DATA', - '00ee': 'GPT', - '00ef': 'EFI', - 'ef00': 'EFI', - '00fb': 'VMFS', - '00fd': 'LINUX-RAID', - 'fd00': 'LINUX-RAID', - '0700': 'WINDOWS', - '0c01': 'WIN-RESERV', - '7f00': 'CHROMEOS-KRN', - '7f01': 'CHROMEOS', - '7f02': 'CHROMEOS-RESERV', - '8301': 'LINUX-RESERV', - 'a500': 'FREEBSD-DISK', - 'a501': 'FREEBSD-BOOT', - 'a502': 'FREEBSD-SWAP', - 'ab00': 'HFS-BOOT', - 'af01': 'HFS-RAID', - 'bf02': 'SOLARIS-SWAP', - 'bf03': 'SOLARIS-DISK', - 'ef01': 'MBR', - 'ef02': 'BIOS-BOOT', - '10000': 'LVM-LV', - '10010': 'ZFS-VOL', - } - if ID in id2type: - return id2type[ID] - return 'UNKNOWN' - - -# ogIsDiskLocked int_ndisk -#@brief Comprueba si un disco está bloqueado por una operación de uso exclusivo. -#@param int_ndisk nº de orden del disco -#@return Código de salida: 0 - bloqueado, 1 - sin bloquear o error. -#@note Los ficheros de bloqueo se localizan en \c /var/lock/dev, siendo \c dev el dispositivo de la partición o de su disco, sustituyendo el carácter "/" por "-". -#*/ ## -def ogIsDiskLocked (disk): - DISK = ogDiskToDev (disk) - if not DISK: return False - return os.path.isfile (f'/var/lock/lock{DISK.replace("/", "-")}') - - -#/** -# ogListPartitions int_ndisk -#@brief Lista las particiones definidas en un disco. -#@param int_ndisk nº de orden del disco -#@return str_parttype:int_partsize ... -#@exception OG_ERR_FORMAT formato incorrecto. -#@exception OG_ERR_NOTFOUND disco o particion no detectado (no es un dispositivo). -#@note Requisitos: \c parted \c awk -#@attention El nº de partición se indica por el orden de los párametros \c parttype:partsize -#@attention Las tuplas de valores están separadas por espacios. -#*/ ## -def ogListPartitions (disk): - DISK = ogDiskToDev (disk) - if not DISK: return None - - p = [] - NPARTS = ogGetPartitionsNumber (disk) - for PART in range (1, NPARTS + 1): - t = ogGetPartitionType (disk, PART) - TYPE = ogGetPartitionType (disk, PART) or 'EMPTY' - SIZE = ogGetPartitionSize (disk, PART) or 0 - p.append (f'{TYPE}:{SIZE}') - - return p - - -#/** -# ogListPrimaryPartitions int_ndisk -#@brief Metafunción que lista las particiones primarias no vacías de un disco. -#@param int_ndisk nº de orden del disco -#@see ogListPartitions -#*/ ## -def ogListPrimaryPartitions (disk): - PTTYPE = ogGetPartitionTableType (disk) - if not PTTYPE: return None - - PARTS = ogListPartitions (disk) - if not PARTS: return None - - if 'GPT' == PTTYPE: - res = [] - for idx in range (len(PARTS),0,-1): - item = PARTS[idx-1] - if 0==len(res) and 'EMPTY:0' == item: continue - res.insert (0, item) - return res - elif 'MSDOS' == PTTYPE: - return PARTS[0:4] - - -#/** -# ogListLogicalPartitions int_ndisk -#@brief Metafunción que lista las particiones lógicas de una tabla tipo MSDOS. -#@param int_ndisk nº de orden del disco -#@see ogListPartitions -#*/ ## -def ogListLogicalPartitions (disk): - PTTYPE = ogGetPartitionTableType (disk) - if not PTTYPE: return None - - PARTS = ogListPartitions (disk) - if not PARTS: return None - - return PARTS[4:] - - -#/** -# ogLockDisk int_ndisk -#@brief Genera un fichero de bloqueo para un disco en uso exlusivo. -#@param int_ndisk nº de orden del disco -#@return (nada) -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. -#@note El fichero de bloqueo se localiza en \c /var/lock/disk, siendo \c disk el dispositivo del disco, sustituyendo el carácter "/" por "-". -#*/ ## -def ogLockDisk (disk): - DISK = ogDiskToDev (disk) - if not DISK: return None - open (f'/var/lock/lock{DISK.replace("/", "-")}', 'a').close() - - -#/** -# ogSetPartitionActive int_ndisk int_npartition -#@brief Establece cual es la partición activa de un disco. -#@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 partición no corresponden con un dispositivo. -#@note Requisitos: parted -#*/ ## -def ogSetPartitionActive (disk, par): - if InventoryLib.ogIsEfiActive(): - SystemLib.ogEcho (['session', 'log'], 'warning', f'EFI: {ogGlobals.lang.MSG_DONTUSE} ogSetPartitionActive') - return - - DISK = ogDiskToDev (disk) - if DISK is None: return - - PART = ogDiskToDev (disk, par) - if PART is None: return - - subprocess.run (["parted", "-s", DISK, "set", par, "boot", "on"]) - return - - -#/** -# ogSetPartitionId int_ndisk int_npartition hex_partid -#@brief Cambia el identificador de la partición. -#@param int_ndisk nº de orden del disco -#@param int_npartition nº de orden de la partición -#@param hex_partid identificador de tipo de partición -#@return (nada) -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_NOTFOUND Disco o partición no corresponden con un dispositivo. -#@exception OG_ERR_OUTOFLIMIT Valor no válido. -#@exception OG_ERR_PARTITION Error al cambiar el id. de partición. -#@attention Requisitos: fdisk, sgdisk -#*/ ## -def ogSetPartitionId (disk, par, id): - DISK = ogDiskToDev (disk) - if not DISK: return None - - PART = ogDiskToDev (disk, par) - if not PART: return None - -# Error si el id. de partición no es hexadecimal. - if not re.match ('^[0-9A-Fa-f]+$', id): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_OUTOFLIMIT, id) - return None - -# Elección del tipo de partición. - PTTYPE = ogGetPartitionTableType (disk) - if 'GPT' == PTTYPE: - p = subprocess.run (['sgdisk', f'-t{par}:{id.upper()}', DISK]) - elif 'MSDOS' == PTTYPE: - p = subprocess.run (['sfdisk', '--id', DISK, par, id.upper()]) - else: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_OUTOFLIMIT, f'{disk},{PTTYPE}') - return None - -# MSDOS) Correcto si fdisk sin error o con error pero realiza Syncing - if 0 == p.returncode: - subprocess.run (['partprobe', DISK]) - return True - else: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f'{disk},{part},{id}') - return None - - -#/** -# ogSetPartitionSize int_ndisk int_npartition int_size -#@brief Muestra el tamano en KB de una particion determinada. -#@param int_ndisk nº de orden del disco -#@param int_npartition nº de orden de la partición -#@param int_size tamaño de la partición (en KB) -#@return (nada) -#@exception OG_ERR_FORMAT formato incorrecto. -#@exception OG_ERR_NOTFOUND disco o particion no detectado (no es un dispositivo). -#@note Requisitos: sfdisk, awk -#@todo Compruebar que el tamaño sea numérico positivo y evitar que pueda solaparse con la siguiente partición. -#*/ ## -def ogSetPartitionSize (disk, par, size): - DISK = ogDiskToDev (disk) - if not DISK: return None - - PART = ogDiskToDev (disk, par) - if not PART: return None - -# Convertir tamaño en KB a sectores de 512 B. - SIZE = 2 * int (size) -# Redefinir el tamaño de la partición. - p = subprocess.run (['sfdisk', '-f', '-uS', f'-N{par}', DISK], input=f',{SIZE}', text=True) - if p.returncode: - ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f'{disk},{par}') - return None - subprocess.run (['partprobe', DISK]) - - -#/** -# ogSetPartitionType int_ndisk int_npartition str_type -#@brief Cambia el identificador de la partición. -#@param int_ndisk nº de orden del disco -#@param int_npartition nº de orden de la partición -#@param str_type mnemónico de tipo de partición -#@return (nada) -#@attention Requisitos: fdisk, sgdisk -#*/ ## -def ogSetPartitionType (disk, par, t): - DISK = ogDiskToDev (disk) - if not DISK: return None - - PART = ogDiskToDev (disk, par) - if not PART: return None - - PTTYPE = ogGetPartitionTableType (disk) - if not PTTYPE: return None - - ID = ogTypeToId (t, PTTYPE) - if not ID: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'{t},{PTTYPE}') - return None - - ogSetPartitionId (disk, par, ID) - - -#/** -# 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', - }, - } - - 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 (disk, par): - PART = ogDiskToDev (disk, par) - if not PART: return None - - TYPE = ogGetPartitionType (disk, par) - if 'HNTFS' == TYPE: NEWTYPE = 'NTFS' - elif 'HFAT32' == TYPE: NEWTYPE = 'FAT32' - elif 'HFAT16' == TYPE: NEWTYPE = 'FAT16' - elif 'HFAT12' == TYPE: NEWTYPE = 'FAT12' - elif 'WIN-RESERV' == TYPE: NEWTYPE = 'WINDOWS' - else: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, TYPE) - return None - - ogSetPartitionType (disk, par, NEWTYPE) - - -#/** -# ogUnlockDisk int_ndisk -#@brief Elimina el fichero de bloqueo para un disco. -#@param int_ndisk nº de orden del disco -#@return (nada) -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. -#@note El fichero de bloqueo se localiza en \c /var/lock/disk, siendo \c disk el dispositivo del disco, sustituyendo el carácter "/" por "-". -#*/ ## -def ogUnlockDisk (disk): - DISK = ogDiskToDev (disk) - if not DISK: return None - os.remove (f'/var/lock/lock{DISK.replace("/", "-")}') - - -#/** -# ogUpdatePartitionTable -#@brief Fuerza al kernel releer la tabla de particiones de los discos duros -#@param no requiere -#@return informacion propia de la herramienta -#@note Requisitos: \c partprobe -#@warning pendiente estructurar la funcion a opengnsys -#*/ ## -def ogUpdatePartitionTable(): - for disk in ogDiskToDev(): - subprocess.run(["partprobe", disk]) diff --git a/client/lib/engine/bin/File.lib b/client/lib/engine/bin/File.lib new file mode 100755 index 0000000..1be1a33 --- /dev/null +++ b/client/lib/engine/bin/File.lib @@ -0,0 +1,422 @@ +#!/bin/bash +#/** +#@file File.lib +#@brief Librería o clase File +#@class File +#@brief Funciones para gestión de archivos y directorios. +#@version 1.0.4 +#@warning License: GNU GPLv3+ +#*/ + + +#/** +# ogCalculateChecksum [ str_repo | int_ndisk int_npart ] path_filepath +#@brief Devuelve la suma de comprobación (checksum) de un fichero. +#@param path_filepath camino del fichero (independiente de mayúsculas) +#@param str_repo repositorio de ficheros +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@return hex_checksum Checksum del fichero +#@version 0.9.2 - Primera versión para OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2010-07-24 +#@version 1.0.4 - Calcula solo el checksum del último MB del fichero. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2012-03-16 +#*/ ## +function ogCalculateChecksum () +{ +# Variables locales. +local FILE +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_filepath" \ + "$FUNCNAME REPO ubuntu.img ==> ef899299caf8b517ce36f1157a93d8bf" + return +fi + +# Comprobar que existe el fichero y devolver sus datos. +FILE=$(ogGetPath "$@") +[ -n "$FILE" ] || ogRaiseError $OG_ERR_NOTFOUND "$*" || return $? +tail -c1M "$FILE" | md5sum -b 2>&1 | cut -f1 -d" " +} + + +#/** +# ogCompareChecksumFiles [ str_repo | int_ndisk int_npart ] path_source [ str_repo | int_ndisk int_npart ] path_target +#@brief Metafunción que compara las sumas de comprobación almacenadas de 2 ficheros. +#@return bool_compare Valor de comparación. +#@warning No es necesario especificar la extensión ".sum". +#@version 0.9.2 - Primera versión para OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2010-07-24 +#*/ ## +function ogCompareChecksumFiles () +{ +# Variables locales. +local ARGS SOURCE TARGET +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_filepath" \ + "if $FUNCNAME REPO ubuntu.img CACHE ubuntu.img; then ...; fi" + return +fi + +ARGS="$@" +case "$1" in + /*) # Camino completo. */ (Comentrio Doxygen) + SOURCE=$(ogGetPath "$1") + shift ;; + [1-9]*) # ndisco npartición. + SOURCE=$(ogGetPath "$1" "$2" "$3") + shift 3 ;; + *) # Otros: repo, cache, cdrom (no se permiten caminos relativos). + SOURCE=$(ogGetPath "$1" "$2") + shift 2 ;; +esac +TARGET=$(ogGetPath "$@") + +# Comparar los ficheros de checksum. +test "$(cat "$SOURCE.sum" 2>/dev/null)" == "$(cat "$TARGET.sum" 2>/dev/null)" +} + + +#/** +# ogCalculateFullChecksum [ str_repo | int_ndisk int_npart ] path_filepath +#@brief Devuelve la suma COMPLETA de comprobación (checksum) de un fichero. +#@param path_filepath camino del fichero (independiente de mayúsculas) +#@param str_repo repositorio de ficheros +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@return hex_checksum Checksum del fichero +#@version 1.0.5 - Primera versión para OpenGnSys. +#@author Antonio Doblas Viso, EVLT Universidad de Málaga +#@date 2014-07-09 +#*/ ## +function ogCalculateFullChecksum () +{ +# Variables locales. +local FILE +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_filepath" \ + "$FUNCNAME REPO ubuntu.img ==> ef899299caf8b517ce36f1157a93d8bf" + return +fi + +# Comprobar que existe el fichero y devolver sus datos. +FILE=$(ogGetPath "$@") +[ -n "$FILE" ] || ogRaiseError $OG_ERR_NOTFOUND "$*" || return $? +#ADV +md5sum "$FILE" -b 2>&1 | cut -f1 -d" " +# tail -c1M "$FILE" | md5sum -b 2>&1 | cut -f1 -d" " +} + + + + +#/** +# ogCopyFile [ str_repo | int_ndisk int_npart ] path_source [ str_repo | int_ndisk int_npart ] path_target +#@brief Metafunción para copiar un fichero de sistema OpenGnSys a un directorio. +#@see ogGetPath +#@return Progreso de la copia. +#@warning Deben existir tanto el fichero origen como el directorio destino. +#@version 0.9 - Pruebas con OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2009-10-20 +#@version 1.0.4 - Copiar usando rsync. +#@author Universidad de Huelva +#@date 2012-07-06 +#*/ ## +function ogCopyFile () +{ +# Variables locales. +local ARGS SOURCE TARGET +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_source [ str_repo | int_ndisk int_npartition ] path_target" \ + "$FUNCNAME REPO newfile.txt 1 2 /tmp/newfile.txt" + return +fi + +ARGS="$@" +case "$1" in + /*) # Camino completo. */ (Comentrio Doxygen) + SOURCE="$(ogGetPath "$1")" + shift ;; + [1-9]*) # ndisco npartición. + SOURCE="$(ogGetPath "$1" "$2" "$3")" + shift 3 ;; + *) # Otros: repo, cache, cdrom (no se permiten caminos relativos). + SOURCE="$(ogGetPath "$1" "$2")" + shift 2 ;; +esac +# Comprobar fichero origen y directorio destino. +[ -n "$SOURCE" ] || ogRaiseError $OG_ERR_NOTFOUND "${ARGS% $*}" || return $? +TARGET="$(ogGetPath "$@")" +[ -n "$TARGET" ] || ogRaiseError $OG_ERR_NOTFOUND "$*" || return $? +# Copiar fichero (para evitar problemas de comunicaciones las copias se hacen con rsync en vez de cp). +rsync --progress --inplace -avh "$SOURCE" "$TARGET" +} + + +#/** +# ogDeleteFile [ str_repo | int_ndisk int_npartition ] path_filepath +#@brief Metafunción que borra un fichero de un dispositivo. +#@see ogGetPath +#@version 0.9 - Pruebas con OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2009-09-29 +#*/ ## +function ogDeleteFile () +{ +# Variables locales. +local FILE +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_file" \ + "$FUNCNAME 1 2 /tmp/newfile.txt" + return +fi + +# Comprobar que existe el fichero y borrarlo. +FILE="$(ogGetPath "$@")" +[ -n "$FILE" ] || ogRaiseError $OG_ERR_NOTFOUND "$*" || return $? +rm -f "$FILE" || ogRaiseError $OG_ERR_NOTFOUND "$*" || return $? +} + + +#/** +# ogDeleteTree [ str_repo | int_ndisk int_npartition ] path_dirpath +#@brief Metafunción que borra todo un subárbol de directorios de un dispositivo. +#@see ogGetPath +#@version 0.9 - Pruebas con OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2009-09-29 +#*/ ## +function ogDeleteTree () +{ +# Variables locales. +local DIR +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_dir" \ + "$FUNCNAME 1 2 /tmp/newdir" + return +fi + +# Comprobar que existe el directorio y borrarlo con su contenido. +DIR="$(ogGetPath "$@")" +[ -n "$DIR" ] || ogRaiseError $OG_ERR_NOTFOUND "$*" || return $? +rm -fr "$DIR" || ogRaiseError $OG_ERR_NOTFOUND "$*" || return $? +} + + +#/** +# ogGetPath [ str_repo | int_ndisk int_npartition ] path_filepath +#@brief Inicia el proceso de arranque de un sistema de archivos. +#@param path_filepath camino del fichero (independiente de mayúsculas) +#@param str_repo repositorio de ficheros +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@return path_file - camino completo real del fichero. +#@note repo = { REPO, CACHE, CDROM } +#@note Requisitos: \c grep \c sed +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Fichero o dispositivo no encontrado. +#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. +#@warning En caso de error, sólo devuelve el código y no da mensajes. +#@todo Terminar de definir parámetros para acceso a repositorios. +#@version 0.1 - Integracion para Opengnsys - HIDRA: CaminoWindows.sh; EAC: GetPath(), FormatSintaxSpacePath(), FormatSintaxBackSlashPath (), en FileSystem.lib +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@Date 2008/10/10 +#@author Antonio J. Doblas Viso. Universidad de Malaga +#@date 2008/10/27 +#@version 0.9 - Pruebas con OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2009-09-15 +#@version 1.1.1 - Correccion comentarios autodocumentacion doxygen . +#@author Antonio J. Doblas Viso. Universidad de Malaga +#@date 2018-07-05 +#*/ ## + +function ogGetPath () +{ +# Variables locales. +local MNTDIR FILE PREVFILE FILEPATH CURRENTDIR + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_filepath" \ + "$FUNCNAME \"/mnt/sda1/windows/system32\" ==> /mnt/sda1/WINDOWS/System32" \ + "$FUNCNAME REPO /etc/fstab ==> /opt/opengnsys/images/etc/fstab" \ + "$FUNCNAME 1 1 \"/windows/system32\" ==> /mnt/sda1/WINDOWS/System32" + return +fi + +# Procesar camino según el número de parámetros. +case $# in + 1) FILE="$1" ;; + 2) case "${1^^}" in + REPO) + FILE="$OGIMG/$2" ;; + CACHE) + MNTDIR="$(ogMountCache)" || return $? + FILE="$MNTDIR/$OGIMG/$2" ;; + CDROM) + MNTDIR="$(ogMountCdrom)" || return $? + FILE="$MNTDIR/$2" ;; + *) ogRaiseError $OG_ERR_FORMAT + return $? ;; + esac ;; + 3) MNTDIR="$(ogMount $1 $2)" || return $? + FILE="$MNTDIR/$3" ;; + *) ogRaiseError $OG_ERR_FORMAT + return $? ;; +esac + +# Eliminar caracteres \c / duplicados y finales. + +FILE="$(echo $FILE|sed -e 's/\(\/\)*\1/\//g; s/\/$//')" +# Comprobar si existe el fichero para reducir tiempos. +if [ -e "$FILE" ]; then + FILEPATH="$FILE" +else + # Buscar el nombre correcto en cada subdirectorio del camino. + FILEPATH="/" + + while [ "$FILE" != "$PREVFILE" ]; do + FILEPATH="$(ls -d "${FILEPATH%/}/${FILE%%/*}" 2>/dev/null || find "$FILEPATH" -maxdepth 1 -iname "${FILE%%/*}" -print 2>/dev/null)" #*/ (Comentario Doxygen) + PREVFILE="$FILE" + FILE="${FILE#*/}" + done + +fi +[ -n "$FILEPATH" ] && echo "$FILEPATH" +return 0 +} + + +#/** +# ogGetParentPath [ str_repo | int_ndisk int_npartition ] path_filepath +#@brief Metafunción que devuelve el camino del directorio padre. +#@see ogGetPath +#@version 0.9 - Pruebas con OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2009-09-29 +#*/ ## + +function ogGetParentPath () +{ +local PARENT +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_filepath" \ + "$FUNCNAME \"/mnt/sda1/windows/system32\" ==> /mnt/sda1/WINDOWS" \ + "$FUNCNAME REPO /etc/fstab ==> /opt/opengnsys/images/etc" \ + "$FUNCNAME 1 1 \"/windows/system32\" ==> /mnt/sda1/WINDOWS" + return +fi + +case $# in + 1) PARENT="$(dirname "$1")" ;; + 2) PARENT="$1 $(dirname "/$2")" ;; + 3) PARENT="$1 $2 $(dirname "/$3")" ;; + *) ogRaiseError $OG_ERR_FORMAT + return $? ;; +esac +ogGetPath $PARENT +} + + +#/** +# ogIsNewerFile [ str_repo | int_ndisk int_npart ] path_source [ str_repo | int_ndisk int_npart ] path_target +#@brief Metafunción que indica se un fichero es más nuevo que otro. +#@see ogGetPath +#@return Código de salida: 0 - nuevo, 1 - antiguo o error +#@warning Deben existir tanto el fichero origen como el destino. +#@version 0.9.2 - Primera versión para OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2010-07-24 +#@version 1.0.1 - Devolver falso en caso de error. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2011-05-18 +#*/ ## +function ogIsNewerFile () +{ +# Variables locales. +local ARGS SOURCE TARGET +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_source [ str_repo | int_ndisk int_npartition ] path_target" \ + "if $FUNCNAME REPO ubuntu.img CACHE ubuntu.img; then ... fi" + return +fi + +ARGS="$@" +case "$1" in + /*) # Camino completo. */ (Comentrio Doxygen) + SOURCE="$(ogGetPath "$1")" + shift ;; + [1-9]*) # ndisco npartición. + SOURCE="$(ogGetPath "$1" "$2" "$3")" + shift 3 ;; + *) # Otros: repo, cache, cdrom (no se permiten caminos relativos). + SOURCE="$(ogGetPath "$1" "$2")" + shift 2 ;; +esac +# Comprobar que existen los ficheros origen y destino. +[ -n "$SOURCE" ] || ogRaiseError $OG_ERR_NOTFOUND "${ARGS% $*}" || return 1 +TARGET=$(ogGetPath "$@") +[ -n "$TARGET" ] || ogRaiseError $OG_ERR_NOTFOUND "$*" || return 1 +# Devolver si el primer fichero se ha modificado después que el segundo. +test "$SOURCE" -nt "$TARGET" +} + + +#/** +# ogMakeChecksumFile [ str_repo | int_ndisk int_npart ] path_filepath +#@brief Metafunción que guarda el valor de comprobación de un fichero. +#@see ogCalculateChecksum +#@warning Genera un fichero con extensión ".sum". +#@version 0.9.2 - Primera versión para OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2010-07-24 +#*/ ## +function ogMakeChecksumFile () +{ +# Variables locales. +local FILE +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_filepath" \ + "$FUNCNAME REPO ubuntu.img" + return +fi + +# Comprobar que existe el fichero y guardar su checksum. +FILE="$(ogGetPath "$@")" +[ -n "$FILE" ] || ogRaiseError $OG_ERR_NOTFOUND "$*" || return $? +ogCalculateChecksum "$FILE" > "$FILE.sum" +} + + +#/** +# ogMakeDir [ str_repo | int_ndisk int_npartition ] path_dirpath +#@brief Metafunción que crea un subdirectorio vacío en un dispositivo. +#@see ogGetParentPath +#@version 0.1 - Integracion para Opengnsys - HIDRA: CrearDirectorio.sh, EAC: MkdirPath() en FileSystem.lib +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@Date 2008/10/10 +#@author Antonio J. Doblas Viso. Universidad de Malaga +#@date 2008/10/27 +#@version 0.9 - Pruebas con OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2009-09-29 +#*/ ## +function ogMakeDir () +{ +local PARENT DIR +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_dir" \ + "$FUNCNAME 1 2 /tmp/newdir" + return +fi + +PARENT="$(ogGetParentPath "$@")" || return $? +DIR="$(basename "${!#}")" +mkdir -p "$PARENT/$DIR" || ogRaiseError $OG_ERR_NOTFOUND "$*" || return $? +} + diff --git a/client/lib/engine/bin/FileLib.py b/client/lib/engine/bin/FileLib.py deleted file mode 100755 index 2a4adf4..0000000 --- a/client/lib/engine/bin/FileLib.py +++ /dev/null @@ -1,517 +0,0 @@ -#/** -#@file FileLib.py -#@brief Librería o clase File -#@class File -#@brief Funciones para gestión de archivos y directorios. -#@warning License: GNU GPLv3+ -#*/ - -import subprocess -import os -import shutil -import hashlib - -import ogGlobals -import SystemLib -import CacheLib -import FileSystemLib - -#/** -# ogCalculateChecksum [ str_repo | int_ndisk int_npart ] path_filepath -#@brief Devuelve la suma de comprobación (checksum) de un fichero. -#@param path_filepath camino del fichero (independiente de mayúsculas) -#@param str_repo repositorio de ficheros -#@param int_ndisk nº de orden del disco -#@param int_npartition nº de orden de la partición -#@return hex_checksum Checksum del fichero -#*/ ## -#ogCalculateChecksum ([ str_repo | int_ndisk int_npartition ] path_filepath") -#ogCalculateChecksum (container='REPO', file='ubuntu.img') ==> ef899299caf8b517ce36f1157a93d8bf -#ogCalculateChecksum (disk=1, par=1, file='ubuntu.img') ==> ef899299caf8b517ce36f1157a93d8bf -def ogCalculateChecksum (disk=None, par=None, container=None, file=None): - if file is None: - raise TypeError ('missing required argument: "file"') - - if container is not None: - if disk is None and par is None: - ## we were given container= - f = ogGetPath (src=container, file=file) - dev_err = f'{container} {file}' - print (f'ogGetPath (src=({container}), file=({file})) = f ({f})') - else: - raise TypeError ('argument "container" can be specified along neither "disk" nor "par"') - - else: - if disk is not None and par is not None: - ## we were given disk= par= - f = ogGetPath (src=f'{disk} {par}', file=file) - dev_err = f'{disk} {par} {file}' - print (f'ogGetPath (src=({disk} {par}), file=({file})) = f ({f})') - elif disk is None and par is None: - ## we were given nothing - f = ogGetPath (file=file) - dev_err = file - print (f'ogGetPath (file=({file})) = f ({f})') - else: - raise TypeError ('if one of "disk" and "par" are specified, then both must be') - - if not f: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, dev_err) - return - - last_n_bytes = 1024*1024 - if last_n_bytes >= os.stat (f).st_size: - return ogCalculateFullChecksum (disk, par, container, file) - with open (f, 'rb') as fd: - fd.seek (-last_n_bytes, os.SEEK_END) - data = fd.read() - md5 = hashlib.md5(data).hexdigest() - - return md5 - - -#/** -# ogCompareChecksumFiles [ str_repo | int_ndisk int_npart ] path_source [ str_repo | int_ndisk int_npart ] path_target -#@brief Metafunción que compara las sumas de comprobación almacenadas de 2 ficheros. -#@return bool_compare Valor de comparación. -#@warning No es necesario especificar la extensión ".sum". -#*/ ## -def ogCompareChecksumFiles(*args): - # Variables locales. - ARGS = args - if "help" in args: - SystemLib.ogHelp("$FUNCNAME", "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_filepath", "if $FUNCNAME REPO ubuntu.img CACHE ubuntu.img; then ...; fi") - return - - ARGS = args - if args[0].startswith("/"): - # Camino completo. */ (Comentario Doxygen) - SOURCE = ogGetPath(*args[:1]) - args = args[1:] - elif args[0].isdigit(): - # ndisco npartición. - SOURCE = ogGetPath(*args[:3]) - args = args[3:] - else: - # Otros: repo, cache, cdrom (no se permiten caminos relativos). - SOURCE = ogGetPath(*args[:2]) - args = args[2:] - - TARGET = ogGetPath(*args) - - try: - with open(f"{SOURCE}.sum", "r") as source_file: - source_checksum = source_file.read().strip() - with open(f"{TARGET}.sum", "r") as target_file: - target_checksum = target_file.read().strip() - - return source_checksum == target_checksum - except FileNotFoundError: - return False - - -#/** -# ogCalculateFullChecksum [ str_repo | int_ndisk int_npart ] path_filepath -#@brief Devuelve la suma COMPLETA de comprobación (checksum) de un fichero. -#@param path_filepath camino del fichero (independiente de mayúsculas) -#@param str_repo repositorio de ficheros -#@param int_ndisk nº de orden del disco -#@param int_npartition nº de orden de la partición -#@return hex_checksum Checksum del fichero -#*/ ## -def ogCalculateFullChecksum (disk=None, par=None, container=None, file=None): - if file is None: - raise TypeError ('missing required argument: "file"') - - if container is not None: - if disk is None and par is None: - ## we were given container= - f = ogGetPath (src=container, file=file) - dev_err = f'{container} {file}' - print (f'ogGetPath (src=({container}), file=({file})) = f ({f})') - else: - raise TypeError ('argument "container" can be specified along neither "disk" nor "par"') - - else: - if disk is not None and par is not None: - ## we were given disk= par= - f = ogGetPath (src=f'{disk} {par}', file=file) - dev_err = f'{disk} {par} {file}' - print (f'ogGetPath (src=({disk} {par}), file=({file})) = f ({f})') - elif disk is None and par is None: - ## we were given nothing - f = ogGetPath (file=file) - dev_err = file - print (f'ogGetPath (file=({file})) = f ({f})') - else: - raise TypeError ('if one of "disk" and "par" are specified, then both must be') - - if not f: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, dev_err) - return - - md5 = hashlib.md5() - with open (f, 'rb') as fd: - for chunk in iter (lambda: fd.read (64*1024), b''): - md5.update (chunk) - return md5.hexdigest() - - - - -#/** -# ogCopyFile [ str_repo | int_ndisk int_npart ] path_source [ str_repo | int_ndisk int_npart ] path_target -#@brief Metafunción para copiar un fichero de sistema OpenGnSys a un directorio. -#@see ogGetPath -#@return Progreso de la copia. -#@warning Deben existir tanto el fichero origen como el directorio destino. -#*/ ## -#ogCopyFile (src, dst) -#ogCopyFile ({container='REPO', file='newfile.txt'}, {disk=1, par=2, file='/tmp/newfile.txt'}) -#ogCopyFile ({disk=1, par=2, file='/tmp/newfile.txt'}, {container='REPO', file='newfile.txt'}) -def ogCopyFile (src, dst): - for elem in src, dst: - if elem == src: which = 'source' - else: which = 'target' - - if 'file' not in elem: - raise TypeError ('missing required argument in {which} dict:: "file"') - - if 'container' in elem: - if 'disk' not in elem and 'par' not in elem: - ## we were given container= - path = ogGetPath (src=elem['container'], file=elem['file']) - dev_err = f'{elem["container"]} {elem["file"]}' - print (f'ogGetPath {which} (src=({elem["container"]}), file=({elem["file"]})) = path ({path})') - else: - raise TypeError ('argument "container" can be specified along neither "disk" nor "par"') - - else: - if 'disk' in elem and 'par' in elem: - ## we were given disk= par= - path = ogGetPath (src=f'{elem["disk"]} {elem["par"]}', file=elem['file']) - dev_err = f'{elem["disk"]} {elem["par"]} {elem["file"]}' - print (f'ogGetPath {which} (src=({elem["disk"]} {elem["par"]}), file=({elem["file"]})) = path ({path})') - elif 'disk' not in elem and 'par' not in elem: - ## we were given nothing - path = ogGetPath (file=elem['file']) - dev_err = elem['file'] - print (f'ogGetPath {which} (file=({elem["file"]})) = path ({path})') - else: - raise TypeError ('if one of "disk" and "par" are specified, then both must be') - - if elem == src: - SOURCE = path - src_dev_err = dev_err - else: - TARGET = path - dst_dev_err = dev_err - - if not SOURCE: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'device or file {src_dev_err} not found') - return - if not TARGET: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'device or file {dst_dev_err} not found') - return - print (f'nati: ogCopyFile: SOURCE ({SOURCE}) TARGET ({TARGET})') - - # Copiar fichero (para evitar problemas de comunicaciones las copias se hacen con rsync en vez de cp). - print (f'nati: ogCopyFile: rsync --progress --inplace -avh ({SOURCE}) ({TARGET})') - result = subprocess.run(["rsync", "--progress", "--inplace", "-avh", SOURCE, TARGET], capture_output=True, text=True) - return result.returncode - - -#/** -# ogDeleteFile [ str_repo | int_ndisk int_npartition ] path_filepath -#@brief Metafunción que borra un fichero de un dispositivo. -#@see ogGetPath -#@version 0.9 - Pruebas con OpenGnSys. -#@author Ramon Gomez, ETSII Universidad de Sevilla -#@date 2009-09-29 -#*/ ## -#ogDeleteFile ([ str_repo | int_ndisk int_npartition ] path_file) -#ogDeleteFile (container='REPO', file='/tmp/newfile.txt') -#ogDeleteFile (disk=1, par=2, file='/tmp/newfile.txt') -def ogDeleteFile (disk=None, par=None, container=None, file=None): - if file is None: - raise TypeError ('missing required argument: "file"') - - if container is not None: - if disk is None and par is None: - ## we were given container= - src = container - else: - raise TypeError ('argument "container" can be specified along neither "disk" nor "par"') - else: - if disk is not None and par is not None: - ## we were given disk= par= - src = f'{disk} {par}' - else: - ## we were given nothing - raise TypeError ('either "container" or both "disk" and "par" must be specified') - - f = ogGetPath (src=src, file=file) - if not f: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'{src} {file}') - return - - try: - os.remove (f) - except OSError as e: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_GENERIC, str (e)) - return - - -#/** -# ogDeleteTree [ str_repo | int_ndisk int_npartition ] path_dirpath -#@brief Metafunción que borra todo un subárbol de directorios de un dispositivo. -#@see ogGetPath -#*/ ## -#ogDeleteTree (container='REPO', file='/tmp/newdir') -#ogDeleteTree (disk=1, par=2, file='/tmp/newdir') -def ogDeleteTree (disk=None, par=None, container=None, file=None): - if file is None: - raise TypeError ('missing required argument: "file"') - - if container is not None: - if disk is None and par is None: - ## we were given container= - src = container - else: - raise TypeError ('argument "container" can be specified along neither "disk" nor "par"') - else: - if disk is not None and par is not None: - ## we were given disk= par= - src = f'{disk} {par}' - else: - ## we were given nothing - raise TypeError ('either "container" or both "disk" and "par" must be specified') - - f = ogGetPath (src=src, file=file) - if not f: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'{src} {file}') - return - - try: - shutil.rmtree (f) - except OSError as e: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, e) - return - - -#/** -# ogGetPath [ str_repo | int_ndisk int_npartition ] path_filepath -#@brief Inicia el proceso de arranque de un sistema de archivos. -#@param path_filepath camino del fichero (independiente de mayúsculas) -#@param str_repo repositorio de ficheros -#@param int_ndisk nº de orden del disco -#@param int_npartition nº de orden de la partición -#@return path_file - camino completo real del fichero. -#@note repo = { REPO, CACHE, CDROM } -#@note Requisitos: \c grep \c sed -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_NOTFOUND Fichero o dispositivo no encontrado. -#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. -#@warning En caso de error, sólo devuelve el código y no da mensajes. -#@todo Terminar de definir parámetros para acceso a repositorios. -#*/ ## -#ogGetPath (file='/mnt/sda1/windows/system32') ==> '/mnt/sda1/WINDOWS/System32' -#ogGetPath (src='REPO', file='/etc/fstab') ==> '/opt/opengnsys/images/etc/fstab' -#ogGetPath (src='1 1', file='/windows/system32') ==> '/mnt/sda1/WINDOWS/System32' -def ogGetPath (src=None, file=None): - if file is None: - raise TypeError ('missing required argument: "file"') - - f = file - if src is not None: - if 'REPO' == src: - f = os.path.join (ogGlobals.OGIMG, file.strip('/')) - elif 'CACHE' == src: - mntdir = CacheLib.ogMountCache() - if not mntdir: return None - f = os.path.join (mntdir, ogGlobals.OGIMG.strip('/'), file.strip('/')) - elif 'CDROM' == src: - mntdir = FileSystemLib.ogMountCdrom() - if not mntdir: return None - f = os.path.join (mntdir, file.strip('/')) - else: - try: - disk, part = src.split() - except ValueError: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, '') - return - mntdir = FileSystemLib.ogMount (disk, part) - if not mntdir: return None - f = os.path.join (mntdir, file.strip('/')) - - f = os.path.normpath (f) - - if os.path.exists (f): - filepath = f - #print (f'f ({f}) existe, filepath=f ({filepath})') - else: - # Buscar el nombre correcto en cada subdirectorio del camino. - prevfile = '' - filepath = '/' - #print (f'f ({f}) prevfile ({prevfile})') - while f != prevfile: - #print ('\nno son iguales, nueva iteracion...') - f_first_component = f.split ('/')[0] ## take 1st component - ls_path = os.path.join (filepath, f_first_component) ## "ls" makes reference to the original bash version - #print (f'f_first_component ({f_first_component}) ls_path ({ls_path})') - - ## build filepath to return - if os.path.exists (ls_path): - filepath = ls_path - #print (f'ls_path existe, filepath ({filepath})') - else: - filepath = subprocess.run (['find', filepath, '-maxdepth', '1', '-iname', f_first_component, '-print'], capture_output=True, text=True).stdout.strip() - #print (f'ls_path no existe, filepath ({filepath})') - - prevfile = f - if '/' in f: - f = '/'.join (f.split('/')[1:]) ## remove 1st component - #print (f'f ({f}) prevfile ({prevfile})') - - return filepath - - -#/** -# ogGetParentPath [ str_repo | int_ndisk int_npartition ] path_filepath -#@brief Metafunción que devuelve el camino del directorio padre. -#@see ogGetPath -#*/ ## - -#ogGetParentPath ([ str_repo | int_ndisk int_npartition ] path_filepath -#ogGetParentPath ( file='/mnt/sda1/windows/system32') ==> '/mnt/sda1/WINDOWS' -#ogGetParentPath (src='REPO', file='/etc/fstab') ==> '/opt/opengnsys/images/etc' -#ogGetParentPath (src='1 1', file='/windows/system32') ==> '/mnt/sda1/WINDOWS' -def ogGetParentPath (src=None, file=None): - if file is None: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, '') - return - - if src is None: - return ogGetPath (file=os.path.dirname (file)) - else: - return ogGetPath (src=src, file=os.path.dirname('/'+file)) - -#/** -# ogIsNewerFile [ str_repo | int_ndisk int_npart ] path_source [ str_repo | int_ndisk int_npart ] path_target -#@brief Metafunción que indica se un fichero es más nuevo que otro. -#@see ogGetPath -#@return Código de salida: 0 - nuevo, 1 - antiguo o error -#@warning Deben existir tanto el fichero origen como el destino. -#*/ ## -def ogIsNewerFile(*args): - # Variables locales. - ARGS = args - if "help" in args: - SystemLib.ogHelp("$FUNCNAME", "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_source [ str_repo | int_ndisk int_npartition ] path_target", "if $FUNCNAME REPO ubuntu.img CACHE ubuntu.img; then ... fi") - return - - ARGS = args - if args[0].startswith("/"): - # Camino completo. */ (Comentrio Doxygen) - SOURCE = ogGetPath(*args[:1]) - args = args[1:] - elif args[0].isdigit(): - # ndisco npartición. - SOURCE = ogGetPath(*args[:3]) - args = args[3:] - else: - # Otros: repo, cache, cdrom (no se permiten caminos relativos). - SOURCE = ogGetPath(*args[:2]) - args = args[2:] - - TARGET = ogGetPath(*args) - - # Comprobar que existen los ficheros origen y destino. - if not SOURCE: - SystemLib.ogRaiseError( - "session", - ogGlobals.OG_ERR_NOTFOUND, - f"Not found: {args[:-1]}" - ) - return - if not TARGET: - SystemLib.ogRaiseError( - "session", - ogGlobals.OG_ERR_NOTFOUND, - f"Not found: {args[-1]}" - ) - return - - # Devolver si el primer fichero se ha modificado después que el segundo. - return os.path.getmtime(SOURCE) > os.path.getmtime(TARGET) - -#/** -# ogMakeChecksumFile [ str_repo | int_ndisk int_npart ] path_filepath -#@brief Metafunción que guarda el valor de comprobación de un fichero. -#@see ogCalculateChecksum -#@warning Genera un fichero con extensión ".sum". -#*/ ## -def ogMakeChecksumFile(*args): - # Variables locales. - FILE = None - if "help" in args: - SystemLib.ogHelp("$FUNCNAME", "$FUNCNAME [ str_repo | int_ndisk int_npartition ] path_filepath", "$FUNCNAME REPO ubuntu.img") - return - - # Comprobar que existe el fichero y guardar su checksum. - FILE = ogGetPath(*args) - if not FILE: - SystemLib.ogRaiseError( - "session", - ogGlobals.OG_ERR_NOTFOUND, - f"Not found: {args}" - ) - return - checksum = ogCalculateChecksum(FILE) - with open(f"{FILE}.sum", "w") as f: - f.write(checksum) - - -#/** -# ogMakeDir [ str_repo | int_ndisk int_npartition ] path_dirpath -#@brief Metafunción que crea un subdirectorio vacío en un dispositivo. -#@see ogGetParentPath -#*/ ## -#ogMakeDir (container='REPO', file='/tmp/newdir') -#ogMakeDir (disk='1', par='2', file='/tmp/newdir') -def ogMakeDir (container=None, disk=None, par=None, file=None): - if file is None: - raise TypeError ('missing required argument: "file"') - - if container is not None: - if disk is None and par is None: - ## we were given container= - parent = ogGetParentPath (src=container, file=file) - dev_err = f'{container} {file}' - print (f'ogGetParentPath (src=({container}), file=({file})) = parent ({parent})') - else: - raise TypeError ('argument "container" can be specified along neither "disk" nor "par"') - - else: - if disk is not None and par is not None: - ## we were given disk= par= - parent = ogGetParentPath (src=f'{disk} {par}', file=file) - dev_err = f'{disk} {par} {file}' - print (f'ogGetParentPath (src=({disk} {par}), file=({file})) = parent ({parent})') - elif disk is None and par is None: - ## we were given nothing - parent = ogGetParentPath (file=file) - dev_err = file - print (f'ogGetParentPath (file=({file})) = parent ({parent})') - else: - raise TypeError ('if one of "disk" and "par" are specified, then both must be') - - print (f'nati: ogMakeDir: parent ({parent})') - if not parent: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'device or file {dev_err} not found') - return None - - dst = os.path.basename (file) - print (f'nati: ogMakeDir: dst ({dst})') - os.makedirs (os.path.join (parent, dst), exist_ok=True) - return True diff --git a/client/lib/engine/bin/FileSystem.lib b/client/lib/engine/bin/FileSystem.lib new file mode 100755 index 0000000..560250d --- /dev/null +++ b/client/lib/engine/bin/FileSystem.lib @@ -0,0 +1,1205 @@ +#!/bin/bash +#/** +#@file FileSystem.lib +#@brief Librería o clase FileSystem +#@class FileSystem +#@brief Funciones para gestión de sistemas de archivos. +#@version 1.1.0 +#@warning License: GNU GPLv3+ +#*/ + + +#/** +# ogCheckFs int_ndisk int_nfilesys +#@brief Comprueba el estado de un sistema de archivos. +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden del sistema de archivos +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@exception OG_ERR_PARTITION Partición desconocida o no accesible. +#@note Requisitos: *fsck* +#@warning No se comprueban sistemas de archivos montados o bloqueados. +#@todo Definir salidas. +#@version 0.9 - Primera adaptación para OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2009-10-07 +#@version 1.0.2 - Ignorar códigos de salida de comprobación (no erróneos). +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2011-09-23 +#@version 1.0.4 - Soportar HFS/HFS+. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2012-05-21 +#@version 1.0.5 - Desmontar antes de comprobar, soportar Btrfs y ExFAT. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2012-09-05 +#@version 1.1.0 - Soportar F2FS. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2016-05-03 +#*/ ## +function ogCheckFs () +{ +# Variables locales. +local PART TYPE PROG PARAMS CODES ERRCODE +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_nfilesys" \ + "$FUNCNAME 1 1" + return +fi + +# Error si no se reciben 2 parámetros. +[ $# == 2 ] || ogRaiseError $OG_ERR_FORMAT || return $? +# Obtener partición. +PART="$(ogDiskToDev $1 $2)" || return $? + +TYPE=$(ogGetFsType $1 $2) +case "$TYPE" in + EXT[234]|CACHE) PROG="e2fsck"; PARAMS="-y"; CODES=(1 2) ;; + BTRFS) PROG="btrfsck"; CODES=(1) ;; + REISERFS) PROG="fsck.reiserfs"; PARAMS="<<<\"Yes\""; CODES=(1 2) ;; + REISER4) PROG="fsck.reiser4"; PARAMS="-ay" ;; + JFS) PROG="fsck.jfs"; CODES=(1 2) ;; + XFS) PROG="xfs_repair" ;; + F2FS) PROG="fsck.f2fs" ;; + NTFS) PROG="ntfsfix" ;; + EXFAT) PROG="fsck.exfat" ;; + FAT32) PROG="dosfsck"; PARAMS="-a"; CODES=(1) ;; + FAT16) PROG="dosfsck"; PARAMS="-a"; CODES=(1) ;; + FAT12) PROG="dosfsck"; PARAMS="-a"; CODES=(1) ;; + HFS) PROG="fsck.hfs"; PARAMS="-f" ;; + HFSPLUS) PROG="fsck.hfs"; PARAMS="-f" ;; + UFS) PROG="fsck.ufs" ;; + ZFS) PROG="fsck.zfs" ;; + *) ogRaiseError $OG_ERR_PARTITION "$1, $2, $TYPE" + return $? ;; +esac +# Error si el sistema de archivos esta montado o bloqueado. +ogUnmount $1 $2 +if ogIsMounted $1 $2; then + ogRaiseError $OG_ERR_PARTITION "$1 $2" # Indicar nuevo error + return $? +fi +if ogIsLocked $1 $2; then + ogRaiseError $OG_ERR_LOCKED "$1 $2" + return $? +fi +# Comprobar en modo uso exclusivo. +ogLock $1 $2 +trap "ogUnlock $1 $2" 1 2 3 6 9 +eval $PROG $PARAMS $PART +ERRCODE=$? +case $ERRCODE in + 0|${CODES[*]}) + ERRCODE=0 ;; + 127) ogRaiseError $OG_ERR_NOTEXEC "$PROG" + ERRCODE=$OG_ERR_NOTEXEC ;; + *) ogRaiseError $OG_ERR_PARTITION "$1 $2" + ERRCODE=$OG_ERR_PARTITION ;; +esac +ogUnlock $1 $2 +return $ERRCODE +} + + +#/** +# ogExtendFs int_ndisk int_nfilesys +#@brief Extiende un sistema de archivos al tamaño de su partición. +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden del sistema de archivos +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@exception OG_ERR_PARTITION Partición desconocida o no accesible. +#@note Requisitos: *resize* +#@version 0.1 - Integracion para Opengnsys - EAC: EnlargeFileSystem() en ATA.lib +#@author Antonio J. Doblas Viso. Universidad de Malaga +#@date 2008-10-27 +#@version 0.9 - Primera adaptacion para OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2009-09-23 +#@version 1.0.5 - Soporte para BTRFS. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2012-06-28 +#*/ ## +function ogExtendFs () +{ +# Variables locales. +local PART TYPE PROG PARAMS ERRCODE DOMOUNT + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_nfilesys" \ + "$FUNCNAME 1 1" + return +fi +# Error si no se reciben 2 parámetros. +[ $# == 2 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +# Obtener partición. +PART="$(ogDiskToDev $1 $2)" || return $? + +# Redimensionar al tamano máximo según el tipo de partición. +TYPE=$(ogGetFsType $1 $2) +case "$TYPE" in + EXT[234]) PROG="resize2fs"; PARAMS="-f" ;; + BTRFS) PROG="btrfs"; PARAMS="filesystem resize max" + DOMOUNT=1 # Debe estar montado. + ;; + REISERFS|REISER4) + PROG="resize_reiserfs"; PARAMS="-f" ;; + F2FS) ;; # No se reduce (por el momento). + JFS) ;; # No se reduce (por el momento). + NILFS2) ;; # No se reduce (probar "nilfs-resize"). + XFS) ;; # No se reduce (por el momento). + NTFS) PROG="ntfsresize"; PARAMS="<<<\"y\" -f" ;; + EXFAT) ;; # No se reduce (por el momento). + FAT32|FAT16) ;; # No se reduce (probar "fatresize"). + HFS|HFSPLUS) ;; # No se reduce (por el momento). + UFS) ;; # No se reduce (por el momento). + *) ogRaiseError $OG_ERR_PARTITION "$1 $2 $TYPE" + return $? ;; +esac +# Salida normal si no se va a aplicar la operación. +[ -z "$PROG" ] && return +# Error si el sistema de archivos no se queda en el estado de montaje adecuado. +if [ "$DOMOUNT" ]; then + PART=$(ogMount $1 $2) || return $? # Indicar nuevo error +else + ogUnmount $1 $2 2>/dev/null + if ogIsMounted $1 $2; then + ogRaiseError $OG_ERR_PARTITION "$1 $2" # Indicar nuevo error + return $? + fi +fi +# Error si el sistema de archivos está bloqueado. +if ogIsLocked $1 $2; then + ogRaiseError $OG_ERR_LOCKED "$1 $2" + return $? +fi +# Redimensionar en modo uso exclusivo. +ogLock $1 $2 +trap "ogUnlock $1 $2" 1 2 3 6 9 +eval $PROG $PARAMS $PART &>/dev/null +ERRCODE=$? +case $ERRCODE in + 0) ;; + 127) ogRaiseError $OG_ERR_NOTEXEC "$PROG" + ERRCODE=$OG_ERR_NOTEXEC ;; + *) ogRaiseError $OG_ERR_PARTITION "$1 $2" + ERRCODE=$OG_ERR_PARTITION ;; +esac +ogUnlock $1 $2 +return $ERRCODE +} + + +#/** +# ogFormat int_ndisk int_nfilesys | CACHE +#@see ogFormatFs ogFormatCache +#*/ ## +function ogFormat () +{ +case "$*" in + CACHE|cache) ogFormatCache ;; + *) ogFormatFs "$@" ;; +esac +} + + +#/** +# ogFormatFs int_ndisk int_nfilesys [type_fstype] [str_label] +#@brief Formatea un sistema de ficheros según el tipo de su partición. +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden del sistema de archivos +#@param type_fstype mnemónico de sistema de ficheros a formatear (opcional al reformatear) +#@param str_label etiqueta de volumen (opcional) +#@return (por determinar) +#@exception OG_ERR_FORMAT Formato de ejecución incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@exception OG_ERR_PARTITION Partición no accesible o desconocida. +#@note Requisitos: mkfs* +#@warning No formatea particiones montadas ni bloqueadas. +#@todo Definir salidas. +#@version 0.9 - Primera versión para OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2009-10-08 +#@version 1.0.4 - Solucionado error cuando no se detecta tipo de sistema de ficheros pero si se indica. +#@author Universidad de Huelva +#@date 2012-04-11 +#@version 1.0.5 - Comprobar errores al inicio e independizar del tipo de tabla de particiones. +#@author Universidad de Huelva +#@date 2013-05-16 +#@version 1.1.0 - Soportar F2FS y NILFS. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2016-05-03 +#*/ ## +function ogFormatFs () +{ +# Variables locales +local PART ID TYPE LABEL PROG PARAMS LABELPARAM ERRCODE + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_nfilesys [str_label]" \ + "$FUNCNAME 1 1" \ + "$FUNCNAME 1 1 EXT4" \ + "$FUNCNAME 1 1 \"DATA\"" \ + "$FUNCNAME 1 1 EXT4 \"DATA\"" + return +fi +# Error si no se reciben entre 2 y 4 parámetros. +[ $# -ge 2 -a $# -le 4 ] || ogRaiseError $OG_ERR_FORMAT || return $? +# Obtener fichero de dispositivo. +PART="$(ogDiskToDev $1 $2)" || return $? +# Error si la partición está montada o bloqueada. +if ogIsMounted $1 $2; then + ogRaiseError $OG_ERR_DONTFORMAT "$MSG_MOUNT: $1 $2" + return $? +fi +if ogIsLocked $1 $2; then + ogRaiseError $OG_ERR_LOCKED "$1 $2" + return $? +fi +# Si no se indica el tipo de sisitema de archivos, intentar obtenerlo. +TYPE="${3:-$(ogGetFsType $1 $2)}" +# Error, si no especifica el tipo de sistema de archivos a formatear. +[ -n "$TYPE" ] || ogRaiseError $OG_ERR_FORMAT "$1 $2 ..." || return $? + +# Elegir tipo de formato. +case "$TYPE" in + EXT2) PROG="mkfs.ext2"; PARAMS="-F" ;; + EXT3) PROG="mkfs.ext3"; PARAMS="-F" ;; + EXT4) PROG="mkfs.ext4"; PARAMS="-F" ;; + BTRFS) PROG="mkfs.btrfs"; PARAMS="-f" ;; + REISERFS) PROG="mkfs.reiserfs"; PARAMS="-f"; LABELPARAM="-l" ;; + REISER4) PROG="mkfs.reiser4"; PARAMS="-f <<<\"y\"" ;; + XFS) PROG="mkfs.xfs"; PARAMS="-f" ;; + JFS) PROG="mkfs.jfs"; PARAMS="<<<\"y\"" ;; + F2FS) PROG="mkfs.f2fs"; LABELPARAM="-l" ;; + NILFS2) PROG="mkfs.nilfs2"; PARAMS="-f" ;; + LINUX-SWAP) PROG="mkswap" ;; + NTFS) PROG="mkntfs"; PARAMS="-f" ;; + EXFAT) PROG="mkfs.exfat"; LABELPARAM="-n" ;; + FAT32) PROG="mkdosfs"; PARAMS="-F 32"; LABELPARAM="-n" ;; + FAT16) PROG="mkdosfs"; PARAMS="-F 16"; LABELPARAM="-n" ;; + FAT12) PROG="mkdosfs"; PARAMS="-F 12"; LABELPARAM="-n" ;; + HFS) PROG="mkfs.hfs" ;; + HFSPLUS) PROG="mkfs.hfsplus"; LABELPARAM="-v" ;; + UFS) PROG="mkfs.ufs"; PARAMS="-O 2" ;; + *) ogRaiseError $OG_ERR_PARTITION "$1 $2 $TYPE" + return $? ;; +esac + +# Etiquetas de particion. +if [ -z "$LABEL" ]; then + [ "$4" != "CACHE" ] || ogRaiseError $OG_ERR_FORMAT "$MSG_RESERVEDVALUE: CACHE" || return $? + [ -n "$4" ] && PARAMS="$PARAMS ${LABELPARAM:-"-L"} $4" +else + PARAMS="$PARAMS ${LABELPARAM:-"-L"} $LABEL" +fi + +# Formatear en modo uso exclusivo (desmontar siempre). +ogLock $1 $2 +trap "ogUnlock $1 $2" 1 2 3 6 9 +umount $PART 2>/dev/null +eval $PROG $PARAMS $PART 2>/dev/null +ERRCODE=$? +case $ERRCODE in + 0) ;; + 127) ogRaiseError $OG_ERR_NOTEXEC "$PROG" ;; + *) ogRaiseError $OG_ERR_PARTITION "$1 $2" ;; +esac +ogUnlock $1 $2 +return $ERRCODE +} + + +#/** +# ogGetFsSize int_ndisk int_npartition [str_unit] +#@brief Muestra el tamanio del sistema de archivos indicado, permite definir la unidad de medida, por defecto GB +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@param str_unit unidad (opcional, por defecto: KB) +#@return float_size - Tamaño del sistema de archivos +#@note str_unit = { KB, MB, GB, TB } +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o partición no corresponden con un dispositivo. +#@version 0.1 - Integracion para Opengnsys - EAC: SizeFileSystem() en FileSystem.lib +#@author Antonio J. Doblas Viso. Universidad de Malaga +#@date 2008-10-27 +#@version 1.0.4 - Adaptación de las salidas. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2012-06-18 +#*/ ## +function ogGetFsSize () +{ +# Variables locales. +local MNTDIR UNIT VALUE FACTOR SIZE +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_npartition [str_unit]" \ + "$FUNCNAME 1 1 => 15624188" \ + "$FUNCNAME 1 1 KB => 15624188" + return +fi +# Error si no se reciben 2 o 3 parámetros. +[ $# == 2 ] || [ $# == 3 ] || ogRaiseError $OG_ERR_FORMAT || return $? +# Obtener unidad y factor de medida. +UNIT="$3" +UNIT=${UNIT:-"KB"} +case "$UNIT" in + [kK]B) + FACTOR=1 ;; + MB) FACTOR=1024 ;; + GB) FACTOR=$[1024*1024] ;; + TB) FACTOR=$[1024*1024*1024] ;; + *) ogRaiseError $OG_ERR_FORMAT "$3 != { KB, MB, GB, TB }" + return $? ;; +esac + +# Obtener el tamaño del sistema de archivo (si no está formateado; tamaño = 0). +MNTDIR="$(ogMount $1 $2 2>/dev/null)" +if [ -n "$MNTDIR" ]; then + VALUE=$(df -BK "$MNTDIR" | awk '{getline; print $2}') + SIZE=$(echo "$VALUE $FACTOR" | awk '{printf "%f\n", $1/$2}') +else + SIZE=0 +fi +# Devolver el tamaño (quitar decimales si son 0). +echo ${SIZE%.0*} +} + + +#/** +# ogGetFsType int_ndisk int_nfilesys +#@brief Devuelve el mnemonico con el tipo de sistema de archivos. +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden del sistema de archivos +#@return Mnemonico +#@note Mnemonico: { EXT2, EXT3, EXT4, BTRFS, REISERFS, XFS, JFS, FAT12, FAT16, FAT32, NTFS, LINUX-SWAP, LINUX-LVM, LINUX-RAID, HFS, HFSPLUS, CACHE } +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@version 0.1 - Integracion para Opengnsys - EAC: TypeFS() en ATA.lib +#@author Antonio J. Doblas Viso. Universidad de Malaga +#@date 2008-10-27 +#@version 0.9 - Primera adaptacion para OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2009-07-21 +#@version 1.0.2 - Obtención de datos reales de sistemas de ficheros. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2011-12-02 +#@version 1.0.5 - Usar "blkid" para detectar tipo de sistema de archivo. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2014-06-10 +#@version 1.1.0 - Detectar volumen ZFS. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2014-11-14 +#*/ ## +function ogGetFsType () +{ +# Variables locales. +local PART TYPE +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_nfilesys" \ + "$FUNCNAME 1 1 => NTFS" + return +fi +# Error si no se reciben 2 parámetros. +[ $# == 2 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +# Detectar tipo de sistema de archivo (independientemente del tipo de partición). +PART=$(ogDiskToDev "$1" "$2") || return $? +if [[ "$PART" =~ ^/ ]]; then + TYPE=$(blkid -o export $PART | awk -F= '$1~/^TYPE/ { print toupper($2) }') +else + zfs mount $PART 2>/dev/null + TYPE=$(mount | awk "\$1==\"$PART\" { print toupper(\$5) }") +fi + +# Componer valores correctos. +case "$TYPE" in + EXT4) # Comprobar si es caché o Ext4. + if [ "$1 $2" == "$(ogFindCache)" ]; then + ogIsFormated $1 $2 2>/dev/null && TYPE="CACHE" + fi + ;; + VFAT) TYPE="$(blkid -po export $PART | awk -F= '$1~/^VERSION$/ { print toupper($2) }')" ;; + SWAP) TYPE="LINUX-SWAP" ;; + LVM*) TYPE="LINUX-LVM" ;; + *RAID*) TYPE="LINUX-RAID" ;; + ZFS_MEMBER) TYPE="ZVOL" ;; + *_MEMBER) TYPE="${TYPE/_MEMBER/}" ;; +esac + +[ -n "$TYPE" ] && echo "$TYPE" +} + + +#/** +# ogGetMountPoint int_ndisk int_nfilesys +#@brief Devuelve el punto de montaje de un sistema de archivos. +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden del sistema de archivos +#@return Punto de montaje +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@note Requisitos: \c mount* \c awk +#@version 0.9 - Primera versión para OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2009-10-15 +#@version 1.0.6 - Usar comando findmnt. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2014-09-04 +#*/ ## +function ogGetMountPoint () +{ +# Variables locales +local PART +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_nfilesys" \ + "$FUNCNAME 1 1 => /mnt/sda1" + return +fi +# Error si no se reciben 2 parámetros. +[ $# == 2 ] || ogRaiseError $OG_ERR_FORMAT || return $? +# Obtener partición. +PART="$(ogDiskToDev $1 $2)" || return $? + +# Devolver punto de montaje. +findmnt -n -o TARGET $PART +} + + +#/** +# ogIsFormated int_ndisk int_nfilesys +#@brief Comprueba si un sistema de archivos está formateado. +#@param int_ndisk nº de orden del disco o volumen. +#@param int_nfilesys nº de orden del sistema de archivos +#@return Código de salida: 0 - formateado, 1 - sin formato o error. +#@version 0.91 - Adaptación inicial para comprobar que existe caché. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2010-03-18 +#@version 1.0.1 - Devolver falso en caso de error. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2011-05-18 +#@version 1.0.5 - Dejar de usar "parted". +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2012-09-04 +#@version 1.1.0 - Comprobar sin montar el sistema de ficheros. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2016-01-21 +#*/ ## +function ogIsFormated () +{ +# Variables locales +local PART +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_nfilesys" \ + "if $FUNCNAME 1 1; then ... ; fi" + return +fi +# Falso, en caso de error. +[ $# == 2 ] || return 1 +PART="$(ogDiskToDev $1 $2 2>/dev/null)" || return 1 + +# Revisar tipo de sistema de ficheros. +if [[ "$PART" =~ ^/ ]]; then + # Sistemas de ficheros genéricos. + test -n "$(blkid -s TYPE $PART | egrep -vi "swap|_member")" +else + # ZFS. + test "$(zfs list -Hp -o canmount $PART 2>/dev/null)" = "on" +fi +} + + +#/** +# ogIsLocked int_ndisk int_npartition +#@see ogIsPartitionLocked +#*/ +function ogIsLocked () +{ +ogIsPartitionLocked "$@" +} + +#/** +# ogIsPartitionLocked int_ndisk int_npartition +#@brief Comprueba si una partición o su disco están bloqueados por una operación de uso exclusivo. +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@return Código de salida: 0 - bloqueado, 1 - sin bloquear o error. +#@note Los ficheros de bloqueo se localizan en \c /var/lock/dev, siendo \c dev el dispositivo de la partición o de su disco, sustituyendo el carácter "/" por "-". +#@version 0.9 - Primera versión para OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2009-09-03 +#@version 1.0.1 - Devolver falso en caso de error. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2011-05-18 +#@version 1.1.0 - Comprobar si el disco está también bloqueado. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2016-04-08 +#*/ ## +function ogIsPartitionLocked () +{ +# Variables locales +local DISK PART LOCKDISK LOCKPART + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_npartition" \ + "if $FUNCNAME 1 1; then ... ; fi" + return +fi +# Falso, en caso de error. +[ $# == 2 ] || return 1 +PART="$(ogDiskToDev $1 $2 2>/dev/null)" || return 1 +DISK="$(ogDiskToDev $1)" + +# Comprobar existencia de fichero de bloqueo de la partición o de su disco. +LOCKDISK="/var/lock/lock${DISK//\//-}" +LOCKPART="/var/lock/lock${PART//\//-}" +test -f $LOCKDISK -o -f $LOCKPART +} + + +#/** +# ogIsMounted int_ndisk int_nfilesys +#@brief Comprueba si un sistema de archivos está montado. +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden del sistema de archivos +#@return Código de salida: 0 - montado, 1 - sin montar o error. +#@version 0.9 - Primera versión para OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2009-10-15 +#@version 1.0.1 - Devolver falso en caso de error. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2011-05-18 +#*/ ## +function ogIsMounted () +{ +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_nfilesys" \ + "if $FUNCNAME 1 1; then ... ; fi" + return +fi +# Falso, en caso de error. +[ $# == 2 ] || return 1 + +test -n "$(ogGetMountPoint $1 $2)" +} + + +#/** +# ogIsReadonly int_ndisk int_nfilesys +#@brief Comprueba si un sistema de archivos está montado solo de lectura. +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden del sistema de archivos +#@return Código de salida: 0 - montado solo de lectura, 1 - con escritura o no montado. +#@version 1.1.0 - Primera versión para OpenGnsys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2016-01-20 +#*/ ## + +function ogIsReadonly () +{ +# Variables locales +local PART + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_filesys" \ + "if $FUNCNAME 1 1; then ... ; fi" + return +fi +# Falso, en caso de error. +[ $# == 2 ] || return 1 +PART="$(ogDiskToDev $1 $2 2>/dev/null)" || return 1 + +test -n "$(findmnt -n -o OPTIONS $PART | awk 'BEGIN {RS=","} /^ro$/ {print}')" +} + + +#/** +# ogIsWritable int_ndisk int_nfilesys +#@brief Comprueba si un sistema de archivos está montado de lectura y escritura. +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden del sistema de archivos +#@return Código de salida: 0 - lectura y escritura, 1 - solo lectura o no montado. +#@version 1.0.5 - Primera versión para OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2013-10-09 +#*/ ## +function ogIsWritable () +{ +# Variables locales +local PART + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_filesys" \ + "if $FUNCNAME 1 1; then ... ; fi" + return +fi +# Falso, en caso de error. +[ $# == 2 ] || return 1 +PART="$(ogDiskToDev $1 $2 2>/dev/null)" || return 1 + +test -n "$(findmnt -n -o OPTIONS $PART | awk 'BEGIN {RS=","} /^rw$/ {print}')" +} + + +#/** +# ogLock int_ndisk int_npartition +#@see ogLockPartition +#*/ +function ogLock () +{ +ogLockPartition "$@" +} + +#/** +# ogLockPartition int_ndisk int_npartition +#@brief Genera un fichero de bloqueo para una partición en uso exlusivo. +#@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 corresponden con un dispositivo. +#@note El fichero de bloqueo se localiza en \c /var/lock/part, siendo \c part el dispositivo de la partición, sustituyendo el carácter "/" por "-". +#@version 0.9 - Primera versión para OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2009-09-03 +#*/ ## +function ogLockPartition () +{ +# Variables locales +local PART LOCKFILE + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_npartition" \ + "$FUNCNAME 1 1" + return +fi +# Error si no se reciben 2 parámetros. +[ $# == 2 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +# Obtener partición. +PART="$(ogDiskToDev $1 $2)" || return $? + +# Crear archivo de bloqueo exclusivo. +LOCKFILE="/var/lock/lock${PART//\//-}" +touch $LOCKFILE +} + + +#/** +# ogMount int_ndisk int_nfilesys +#@see ogMountFs ogMountCache ogMountCdrom +#*/ ## +function ogMount () +{ +case "$*" in + CACHE|cache) + ogMountCache ;; + CDROM|cdrom) + ogMountCdrom ;; + *) ogMountFs "$@" ;; +esac +} + + +#/** +# ogMountFirstFs int_ndisk +#@brief Monta el primer sistema de archivos disponible en el disco. +#@param int_ndisk nº de orden del disco +#@return Punto de montaje del primer sistema de archivos detectado +#*/ ## +function ogMountFirstFs () +{ +# Variables locales +local PART NPARTS MNTDIR + +# Error si no se recibe 1 parámetro. +[ $# == 1 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +# Obtener nº de particiones del disco. +NPARTS=$(ogGetPartitionsNumber "$1") || return $? +for (( PART = 1; PART <= NPARTS; PART++ )); do + MNTDIR=$(ogMount $1 $PART 2>/dev/null) + if [ -n "$MNTDIR" ]; then + echo "$MNTDIR" + return 0 + fi +done +ogRaiseError $OG_ERR_NOTFOUND "$1" +return $OG_ERR_NOTFOUND +} + + +#/** +# ogMountFs int_ndisk int_nfilesys +#@brief Monta un sistema de archivos. +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden del sistema de archivos +#@return Punto de montaje +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@exception OG_ERR_PARTITION Tipo de particion desconocido o no se puede montar. +#@version 0.1 - Integracion para Opengnsys - EAC: MountPartition() en FileSystem.lib +#@author Antonio J. Doblas Viso. Universidad de Malaga +#@date 2008-10-27 +#@version 0.9 - Primera version para OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2009-09-28 +#@version 1.0.5 - Independiente del tipo de sistema de ficheros. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2012-09-04 +#@version 1.1.0 - Montar sistema de archivos ZFS y NTFS hibernado. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2016-09-19 +#*/ ## +function ogMountFs () +{ +# Variables locales +local PART MNTDIR + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_nfilesys" \ + "$FUNCNAME 1 1 => /mnt/sda1" + return +fi +# Error si no se reciben 2 parámetros. +[ $# == 2 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +# Obtener partición. +PART="$(ogDiskToDev "$1" "$2")" || return $? + +# Comprobar si el sistema de archivos ya está montada. +MNTDIR="$(ogGetMountPoint $1 $2)" +# Si no, montarlo en un directorio de sistema. +if [ -z "$MNTDIR" ]; then + # Error si la particion esta bloqueada. + if ogIsLocked $1 $2; then + ogRaiseError $OG_ERR_LOCKED "$MSG_PARTITION, $1 $2" + return $? + fi + # El camino de un dispositivo normal comienza por el carácter "/". + if [[ "$PART" =~ ^/ ]]; then + # Crear punto de montaje o enlace simbólico para caché local. + MNTDIR=${PART/dev/mnt} + DEBUG="no" + if [ "$(ogFindCache)" == "$1 $2" -a -n "$OGCAC" ]; then + mkdir -p $OGCAC + ln -fs $OGCAC $MNTDIR + else + mkdir -p $MNTDIR + fi + unset DEBUG + # Montar sistema de archivos. + mount $PART $MNTDIR &>/dev/null || \ + mount $PART $MNTDIR -o force,remove_hiberfile &>/dev/null + case $? in + 0) # Correcto. + ;; + 14) # Intentar limpiar hibernación NTFS y montar. + ntfsfix -d $PART &>/dev/null && mount $PART $MNTDIR &>/dev/null || \ + ogRaiseError $OG_ERR_PARTITION "$1, $2" || return $? + ;; + *) # Probar montaje de solo lectura. + mount $PART $MNTDIR -o ro &>/dev/null || \ + ogRaiseError $OG_ERR_PARTITION "$1, $2" || return $? + ;; + esac + # Aviso de montaje de solo lectura. + if ogIsReadonly $1 $2; then + ogEcho warning "$FUNCNAME: $MSG_MOUNTREADONLY: \"$1, $2\"" + fi + else + # Montar sistema de archivos ZFS (un ZPOOL no comienza por "/"). + zfs mount $PART 2>/dev/null + fi +fi +echo "$MNTDIR" +} + + +#/** +# ogMountCdrom +#@brief Monta dispositivo óptico por defecto +#@return Punto de montaje +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_PARTITION Tipo de particion desconocido o no se puede montar. +#@version +#@author +#@date +#*/ ## +function ogMountCdrom () +{ +local DEV MNTDIR +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME" "$FUNCNAME" + return +fi +# Error si se reciben parámetros. +[ $# == 0 ] || ogRaiseError $OG_ERR_FORMAT || return $? +DEV="/dev/cdrom" # Por defecto +MNTDIR=$(mount | awk -v D=$DEV '{if ($1==D) {print $3}}') +if [ -z "$MNTDIR" ]; then + MNTDIR=${DEV/dev/mnt} + mkdir -p $MNTDIR + mount -t iso9660 $DEV $MNTDIR || ogRaiseError $OG_ERR_PARTITION "cdrom" || return $? +fi +echo $MNTDIR +} + + +#/** +# ogReduceFs int_ndisk int_nfilesys +#@brief Reduce el tamaño del sistema de archivos, sin tener en cuenta el espacio libre. +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden del sistema de archivos +#@return int_tamañoKB - tamaño en KB +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@exception OG_ERR_PARTITION Partición desconocida o no accesible. +#@warning En Windows, se borran los ficheros de hiberanción y de paginación. +#@warning El sistema de archivos se amplía al mínimo + 10%. +#@note Requisitos: *resize* +#@version 0.1 - Integracion para Opengnsys - EAC: ReduceFileSystem() en ATA.lib +#@author Antonio J. Doblas Viso. Universidad de Malaga +#@date 2008-10-27 +#@version 0.9 - Primera version para OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2009-09-23 +#@version 0.9.2 - Añadir un 10% al tamaño mínimo requerido. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2010-09-27 +#@version 1.0 - Deteccion automatica del tamaño minimo adecuado +#@author Antonio J. Doblas Viso. Universidad de Malaga +#@date 2011-02-24 +#@version 1.0.6 - Integrar código de antigua función "ogReduceFsCheck". +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2014-10-28 +#@version 1.1.1b - Detectar metadispositivos. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2020-02-24 +#*/ ## +function ogReduceFs () +{ +# Variables locales +local PART BLKS SIZE MAXSIZE EXTRASIZE=0 RETVAL + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_nfilesys" \ + "$FUNCNAME 1 1" + return +fi +# Error si no se reciben 2 parámetros. +[ $# == 2 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +# Obtener partición. +PART="$(readlink -f "$(ogDiskToDev $1 $2)")" || return $? + +# Redimensionar según el tipo de particion. +case "$(ogGetFsType $1 $2)" in + EXT[234]) + ogUnmount $1 $2 &>/dev/null + resize2fs -fpM $PART &>/dev/null || ogRaiseError $OG_ERR_PARTITION "$1,$2" || return $? + ;; + + BTRFS) + MNTDIR=$(ogMount $1 $2) + # Calcular tamaño ocupado + 10%, redondeado + 1 (incluyendo letra de unidad). + SIZE=$(btrfs filesystem show $MNTDIR | awk -v P=$PART '{ d=""; "readlink -f "$8" 2>/dev/null"|getline d; if(d==P) printf("%d%s", $6*1.1+1, substr($6,match($6,/[A-Z]/),1)) }') + btrfs filesystem resize ${SIZE} $MNTDIR &>/dev/null + ;; + REISERFS|REISER4) + # Calcular tamaño ocupado + 10%. + MNTDIR=$(ogMount $1 $2) + SIZE=$[ $(df -k $MNTDIR | awk '{getline;print $3}') * 110 / 100 ] + ogUnmount $1 $2 2>/dev/null + resize_reiserfs -s${SIZE}K $PART <<<"y" + ;; + + F2FS) ;; # No se reduce (por el momento). + JFS) ;; # No se reduce (por el momento). + NILFS2) ;; # No se reduce (probar "nilfs-resize"). + XFS) ;; # No se reduce (por el momento). + + NTFS) + # Calcular tamaño ocupado + 10%. + ogUnmount $1 $2 &>/dev/null + read -e MAXSIZE SIZE <<<$(ntfsresize -fi $PART | \ + awk '/device size/ {d=$4} + /resize at/ {r=int($5*1.1/1024+1)*1024} + END { print d,r}') + # Error si no puede obtenerse el tamaño máximo del volumen. + [ -n "$MAXSIZE" -a -n "$SIZE" ] || ogRaiseError $OG_ERR_PARTITION "$1,$2" || return $? + # Simular la redimensión y comprobar si es necesario ampliarala. + RETVAL=1 + while [ $RETVAL != 0 -a $[ SIZE+=EXTRASIZE ] -lt $MAXSIZE ]; do + # Obtener espacio de relocalización y devolver código de salida + # (ntfsresize devuelve 0 si no necesita relocalizar). + EXTRASIZE=$(ntfsresize -fns $SIZE $PART 2>/dev/null | \ + awk '/Needed relocations/ {print int($4*1.1/1024+1)*1024}' + exit ${PIPESTATUS[0]}) + RETVAL=$? + done + # Redimensionar solo si hace falta. + if [ $SIZE -lt $MAXSIZE ]; then + ntfsresize -fs $SIZE $PART <<<"y" >/dev/null || ogRaiseError $OG_ERR_PARTITION "$1,$2" || return $? + fi + ;; + + EXFAT) ;; # No se reduce (por el momento). + FAT32|FAT16) # Se deja comentado por no haber un método seguro para extender el SF. + # Calcular tamaño ocupado + 10%. + #ogUnmount $1 $2 &>/dev/null + #SIZE=$(fatresize --info $PART | awk -F: '/Min size/ {printf("%d", $2*1.1)}') + #[ "$SIZE" ] && fatresize --size $SIZE $PART &>/dev/null + ;; + HFS|HFSPLUS) ;; # No se reduce (por el momento). + UFS) ;; # No se reduce (por el momento). + + *) ogRaiseError $OG_ERR_PARTITION "$1,$2" + return $? ;; +esac + +# Devuelve tamaño del sistema de ficheros. +ogGetFsSize $1 $2 +} + + +#/** +# ogUnlock int_ndisk int_npartition +#@see ogUnlockPartition +#*/ ## +function ogUnlock () +{ +ogUnlockPartition "$@" +} + +#/** +# ogUnlockPartition int_ndisk int_npartition +#@brief Elimina el fichero de bloqueo para una particion. +#@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 corresponden con un dispositivo. +#@note El fichero de bloqueo se localiza en \c /var/lock/part, siendo \c part el dispositivo de la partición, sustituyendo el carácter "/" por "-". +#@version 0.9 - Primera versión para OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2009-09-03 +#*/ ## +function ogUnlockPartition () +{ +# Variables locales +local PART LOCKFILE + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_npartition" \ + "$FUNCNAME 1 1" + return +fi +# Error si no se reciben 2 parámetros. +[ $# == 2 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +# Obtener partición. +PART="$(ogDiskToDev $1 $2)" || return $? + +# Borrar archivo de bloqueo exclusivo. +LOCKFILE="/var/lock/lock${PART//\//-}" +rm -f $LOCKFILE +} + + +#/** +# ogUnmount int_ndisk int_npartition +#@see ogUnmountFs +#*/ ## +function ogUnmount () +{ +ogUnmountFs "$@" +} + +#/** +# ogUnmountFs int_ndisk int_nfilesys +#@brief Desmonta un sistema de archivos. +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden del sistema de archivos +#@return Nada +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@warning La partición no está previamente montada o no se puede desmontar. +#@version 0.1 - Integracion para Opengnsys - EAC: UmountPartition() en FileSystem.lib +#@author Antonio J. Doblas Viso. Universidad de Malaga +#@date 2008-10-27 +#@version 0.9 - Primera version para OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2009-09-28 +#*/ ## +function ogUnmountFs () +{ +# Variables locales +local PART MNTDIR + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_npartition" "$FUNCNAME 1 1" + return +fi +# Error si no se reciben 2 parámetros. +[ $# == 2 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +# Obtener partición y punto de montaje. +PART="$(ogDiskToDev $1 $2)" || return $? +MNTDIR="$(ogGetMountPoint $1 $2)" + +# Si está montada, desmontarla. +if [ -n "$MNTDIR" ]; then + # Error si la particion está bloqueada. + if ogIsLocked $1 $2; then + ogRaiseError $OG_ERR_LOCKED "$MSG_PARTITION $1, $2" + return $? + fi + # Desmontar y borrar punto de montaje. + umount $PART 2>/dev/null || ogEcho warning "$FUNCNAME: $MSG_DONTUNMOUNT: \"$1, $2\"" + rmdir $MNTDIR 2>/dev/null || rm -f $MNTDIR 2>/dev/null +else + ogEcho warning "$MSG_DONTMOUNT: \"$1,$2\"" +fi +} + + +#/** +# ogUnmountAll int_ndisk +#@brief Desmonta todos los sistema de archivos de un disco, excepto el caché local. +#@param int_ndisk nº de orden del disco +#@return Nada +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@warning No se desmonta la partición marcada como caché local. +#@version 0.9 - Versión para OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2009-10-07 +#*/ ## +function ogUnmountAll () +{ +# Variables locales +local DISK PART +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk" "FUNCNAME 1" + return +fi +# Error si no se recibe 1 parámetro. +[ $# == 1 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +# Obtener partición y punto de montaje. +DISK="$(ogDiskToDev $1)" || return $? +for ((PART=1; PART<=$(ogGetPartitionsNumber $1); PART++)); do + case "$(ogGetFsType $1 $PART)" in + CACHE) ;; + *) ogUnmount $1 $PART 2>/dev/null ;; + esac +done +} + +#/** +# ogUnsetDirtyBit int_ndisk int_npart +#@brief Inhabilita el Dirty Bit del sistema de ficheros NTFS para evitar un CHKDSK en el primer arranque +#@param int_ndisk nº de orden del disco +#@param int_npart nº de orden de partición +#@return Nada +#@exception OG_ERR_FORMAT Formato incorrecto. +#@version 1.1.0 - Versión para OpenGnsys. +#@author Carmelo Cabezuelo, ASIC Universidad Politécnica de Valencia +#@date 2016-04-20 +#*/ ## +function ogUnsetDirtyBit () +{ +# Variables locales +local PART +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk" "FUNCNAME 1" + return +fi +# Error si no se reciben 2 parámetros. +[ $# == 2 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +# Obtener partición y punto de montaje. +case "$(ogGetFsType $1 $2)" in + NTFS) + ogUnmount $1 $2 2>/dev/null + PART="$(ogDiskToDev $1 $2)" || return $? + ntfsfix -d $PART ;; + *) ;; +esac +} + + +#/** +# ogGetFreeSize int_disco int_partition str_SizeOutput +#@brief muestra informacion del tamaño total, datos y libre. +#@param int_ndisk nº de orden del disco +#@param int_npart nº de orden de partición +#@param str_unitSize unidad mostrada +#@return int_size:int_data:int_free +#@TODO Componer corretcamente esta función. +#@exception OG_ERR_FORMAT Formato incorrecto. +#@version +#@author +#@date +#*/ ## + +function ogGetFreeSize () +{ +local particion unit factor valor +if [ $# = 0 ] +then + echo "sintaxis: ogGetFreeSize int_disco int_partition str_SizeOutput [ kB MB GB -default GB]-]" red + echo "devuelve int_size : int_data : int_free" red +return +fi +if [ $# -ge 2 ] +then + particion=`ogMount $1 $2 ` #1>/dev/null 2>&1 + if [ -z $3 ] + then + unit=kB # s B kB MB GB TB % + else + unit=$3 + fi + case $unit in + kB) + factor="1.024"; + #valor=`df | grep $particion | awk -F" " '{size=$2*1.024; used=$3*1.024; free=$4*1.024; printf "%d:%d:%d", size,used,free}'` + valor=`df | grep $particion | awk -F" " '{size=$2*1.024; used=$3*1.024; free=$4*1.024; printf "%d", free}'` + ;; + MB) + factor="1.024/1000"; + valor=`df | grep $particion | awk -F" " '{size=$2*1.024/1000; used=$3*1.024/1000; free=$4*1.024/1000; printf "%d:%d:%d", size,used,free}'` + ;; + GB) + factor="1.024/1000000"; + valor=`df | grep $particion | awk -F" " '{size=$2*1.024/1000000; used=$3*1.024/1000000; free=$4*1.024/1000000; printf "%f:%f:%f", size,used,free}'` + ;; + esac + #echo $valor + #NumberRound $valor + #valor=`NumberRound $valor`; + echo $valor +fi +} + diff --git a/client/lib/engine/bin/FileSystemLib.py b/client/lib/engine/bin/FileSystemLib.py deleted file mode 100755 index 15139f3..0000000 --- a/client/lib/engine/bin/FileSystemLib.py +++ /dev/null @@ -1,906 +0,0 @@ -#/** -#@file FileSystemLib.py -#@brief Librería o clase FileSystem -#@class FileSystem -#@brief Funciones para gestión de sistemas de archivos. -#@warning License: GNU GPLv3+ -#*/ - -import subprocess -import sys -import os.path - -import ogGlobals -import SystemLib -import DiskLib -import CacheLib -import FileSystemLib - - -#/** -# ogCheckFs int_ndisk int_nfilesys -#@brief Comprueba el estado de un sistema de archivos. -#@param int_ndisk nº de orden del disco -#@param int_nfilesys nº de orden del sistema de archivos -#@return (nada) -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. -#@exception OG_ERR_PARTITION Partición desconocida o no accesible. -#@note Requisitos: *fsck* -#@warning No se comprueban sistemas de archivos montados o bloqueados. -#@todo Definir salidas. -#*/ ## -def ogCheckFs (disk, par): - PART = DiskLib.ogDiskToDev (disk, par) - if not PART: return - - data = { - 'EXT2': { 'prog': 'e2fsck', 'params': '-y', 'codes': (1, 2), }, - 'EXT3': { 'prog': 'e2fsck', 'params': '-y', 'codes': (1, 2), }, - 'EXT4': { 'prog': 'e2fsck', 'params': '-y', 'codes': (1, 2), }, - 'CACHE': { 'prog': 'e2fsck', 'params': '-y', 'codes': (1, 2), }, - 'BTRFS': { 'prog': 'btrfsck', 'codes': (1), }, - 'REISERFS': { 'prog': 'fsck.reiserfs', 'codes': (1, 2), 'input': 'Yes' }, - 'REISER4': { 'prog': 'fsck.reiser4', 'params': '-ay', }, - 'JFS': { 'prog': 'fsck.jfs', 'codes': (1, 2), }, - 'XFS': { 'prog': 'xfs_repair', }, - 'F2FS': { 'prog': 'fsck.f2fs', }, - 'NTFS': { 'prog': 'ntfsfix', }, - 'EXFAT': { 'prog': 'fsck.exfat', }, - 'FAT32': { 'prog': 'dosfsck', 'params': '-a', 'codes': (1), }, - 'FAT16': { 'prog': 'dosfsck', 'params': '-a', 'codes': (1), }, - 'FAT12': { 'prog': 'dosfsck', 'params': '-a', 'codes': (1), }, - 'HFS': { 'prog': 'fsck.hfs', 'params': '-f', }, - 'HFSPLUS': { 'prog': 'fsck.hfs', 'params': '-f', }, - 'UFS': { 'prog': 'fsck.ufs', }, - 'ZFS': { 'prog': 'fsck.zfs', }, - } - type = ogGetFsType (disk, par) - if type in data: - prog = data[type]['prog'] - params = data[type]['params'] if 'params' in data[type] else '' - codes = data[type]['codes'] if 'codes' in data[type] else [] - input = data[type]['input'] if 'input' in data[type] else None - else: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f'{disk}, {par}, {type}') - return None - - ogUnmount (disk, par) - if ogIsMounted (disk, par): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f'{disk} {par}') - return None - if ogIsLocked (disk, par): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_LOCKED, f'{disk} {par}') - return None - - ogLock (disk, par) - rc = subprocess.run ([prog] + params.split() + [PART], input=input, text=True).returncode - if 0 == rc or rc in codes: - errcode = 0 - elif 127 == rc: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTEXEC, prog) - errcode = ogGlobals.OG_ERR_NOTEXEC - else: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f'{disk} {par}') - errcode = ogGlobals.OG_ERR_PARTITION - - ogUnlock (disk, par) - return not errcode ## reverse to indicate success - - -#/** -# ogExtendFs int_ndisk int_nfilesys -#@brief Extiende un sistema de archivos al tamaño de su partición. -#@param int_ndisk nº de orden del disco -#@param int_nfilesys nº de orden del sistema de archivos -#@return (nada) -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. -#@exception OG_ERR_PARTITION Partición desconocida o no accesible. -#@note Requisitos: *resize* -#*/ ## -def ogExtendFs (disk, par): - PART = DiskLib.ogDiskToDev (disk, par) - if not PART: return - - data = { - 'EXT2': { 'prog': 'resize2fs', 'params': '-f', }, - 'EXT3': { 'prog': 'resize2fs', 'params': '-f', }, - 'EXT4': { 'prog': 'resize2fs', 'params': '-f', }, - 'BTRFS': { 'prog': 'btrfs', 'params': 'filesystem resize max', 'domount': True }, - 'REISERFS': { 'prog': 'resize_reiserfs', 'params': '-f', }, - 'REISER4': { 'prog': 'resize_reiserfs', 'params': '-f', }, - 'NTFS': { 'prog': 'ntfsresize', 'params': '-f', 'input': 'y' }, - 'F2FS': { 'unsupported': True }, - 'JFS': { 'unsupported': True }, - 'NILFS2': { 'unsupported': True }, # try "nilfs-resize" - 'XFS': { 'unsupported': True }, - 'EXFAT': { 'unsupported': True }, - 'FAT32': { 'unsupported': True }, # try "fatresize" - 'FAT16': { 'unsupported': True }, # try "fatresize" - 'HFS': { 'unsupported': True }, - 'HFSPLUS': { 'unsupported': True }, - 'UFS': { 'unsupported': True }, - } - - type = ogGetFsType (disk, par) - if type in data: - prog = data[type]['prog'] if 'prog' in data[type] else None - params = data[type]['params'] if 'params' in data[type] else None - domount = data[type]['domount'] if 'domount' in data[type] else False - input = data[type]['input'] if 'input' in data[type] else None - else: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f'{disk} {par} {type}') - return - - if not prog: return None - - if domount: - PART = ogMount (disk, par) - if not PART: return None - else: - ogUnmount (disk, par) - if ogIsMounted (disk, par): - SystemLib.ogRaiseError([], ogGlobals.OG_ERR_PARTITION, f'{disk} {par}') - return None - -# Error si el sistema de archivos está bloqueado. - if ogIsLocked (disk, par): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_LOCKED, f'{disk} {par}') - return None - -# Redimensionar en modo uso exclusivo. - ogLock (disk, par) - try: - if input: - rc = subprocess.run ([prog] + params.split() + [PART], input=input, text=True).returncode - else: - rc = subprocess.run ([prog] + params.split() + [PART]).returncode - except FileNotFoundError: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTEXEC, prog) - rc = ogGlobals.OG_ERR_NOTEXEC - except: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f'{disk} {par}') - rc = ogGlobals.OG_ERR_PARTITION - - ogUnlock (disk, par) - return not rc ## reverse to indicate success - - -#/** -# ogFormat int_ndisk int_nfilesys | CACHE -#@see ogFormatFs ogFormatCache -#*/ ## - -def ogFormat (disk, par=None, fs=None, label=None): - if disk.lower() == "cache": - return CacheLib.ogFormatCache() - else: - return ogFormatFs (disk, par, fs=fs, label=label) - - -#/** -# ogFormatFs int_ndisk int_nfilesys [type_fstype] [str_label] -#@brief Formatea un sistema de ficheros según el tipo de su partición. -#@param int_ndisk nº de orden del disco -#@param int_nfilesys nº de orden del sistema de archivos -#@param type_fstype mnemónico de sistema de ficheros a formatear (opcional al reformatear) -#@param str_label etiqueta de volumen (opcional) -#@return (por determinar) -#@exception OG_ERR_FORMAT Formato de ejecución incorrecto. -#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. -#@exception OG_ERR_PARTITION Partición no accesible o desconocida. -#@note Requisitos: mkfs* -#@warning No formatea particiones montadas ni bloqueadas. -#@todo Definir salidas. -#*/ ## -def ogFormatFs (disk, par, fs=None, label=None): - PART = DiskLib.ogDiskToDev (disk, par) - if not PART: return - - if ogIsMounted (disk, par): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_DONTFORMAT, f'{ogGlobals.lang.MSG_MOUNT}: {disk} {par}') - return None - if ogIsLocked (disk, par): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_LOCKED, f"{disk} {par}") - return None - - if not fs: - fs = ogGetFsType (disk, par) - - if not fs: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f"{disk} {par} ...") - return None - - data = { - 'EXT2': { 'PROG': 'mkfs.ext2', 'PARAMS': '-F' }, - 'EXT3': { 'PROG': 'mkfs.ext3', 'PARAMS': '-F' }, - 'EXT4': { 'PROG': 'mkfs.ext4', 'PARAMS': '-F' }, - 'BTRFS': { 'PROG': 'mkfs.btrfs', 'PARAMS': '-f' }, - 'REISERFS': { 'PROG': 'mkfs.reiserfs', 'PARAMS': '-f', 'LABELPARAM': '-l' }, - 'REISER4': { 'PROG': 'mkfs.reiser4', 'PARAMS': '-f', 'INPUT': 'y\n' }, - 'XFS': { 'PROG': 'mkfs.xfs', 'PARAMS': '-f' }, - 'JFS': { 'PROG': 'mkfs.jfs', 'INPUT': 'y\n' }, - 'F2FS': { 'PROG': 'mkfs.f2fs', 'LABELPARAM': '-l' }, - 'NILFS2': { 'PROG': 'mkfs.nilfs2', 'PARAMS': '-f' }, - 'LINUX-SWAP': { 'PROG': 'mkswap' }, - 'NTFS': { 'PROG': 'mkntfs', 'PARAMS': '-f' }, - 'EXFAT': { 'PROG': 'mkfs.exfat', 'LABELPARAM': '-n' }, - 'FAT32': { 'PROG': 'mkdosfs', 'PARAMS': '-F 32', 'LABELPARAM': '-n' }, - 'FAT16': { 'PROG': 'mkdosfs', 'PARAMS': '-F 16', 'LABELPARAM': '-n' }, - 'FAT12': { 'PROG': 'mkdosfs', 'PARAMS': '-F 12', 'LABELPARAM': '-n' }, - 'HFS': { 'PROG': 'mkfs.hfs' }, - 'HFSPLUS': { 'PROG': 'mkfs.hfsplus', 'LABELPARAM': '-v' }, - 'UFS': { 'PROG': 'mkfs.ufs', 'PARAMS': '-O 2' }, - } - if fs not in data: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f"{disk} {par} {fs}") - return - - d = data[fs] - prog = d['PROG'] - params = d['PARAMS'] if 'PARAMS' in d else '' - labelparam = d['LABELPARAM'] if 'LABELPARAM' in d else '' - input = d['INPUT'] if 'INPUT' in d else '' - - if label == "CACHE": - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f"{ogGlobals.lang.MSG_RESERVEDVALUE}: CACHE") - return - if label: - params = f"{params} {labelparam or '-L'} {label}" - - ogLock (disk, par) - subprocess.run (['umount', PART]) - try: - if input: - errcode = subprocess.run ([prog] + params.split (' ') + [PART]).returncode - else: - errcode = subprocess.run ([prog] + params.split (' ') + [PART], input=input, text=True).returncode - except FileNotFoundError: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTEXEC, prog) - errcode = ogGlobals.OG_ERR_NOTEXEC - except: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f"{disk} {par}") - errcode = ogGlobals.OG_ERR_PARTITION - - ogUnlock (disk, par) - return errcode - - -#/** -# ogGetFsSize int_ndisk int_npartition [str_unit] -#@brief Muestra el tamanio del sistema de archivos indicado, permite definir la unidad de medida, por defecto GB -#@param int_ndisk nº de orden del disco -#@param int_npartition nº de orden de la partición -#@param str_unit unidad (opcional, por defecto: KB) -#@return float_size - Tamaño del sistema de archivos -#@note str_unit = { KB, MB, GB, TB } -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_NOTFOUND Disco o partición no corresponden con un dispositivo. -#*/ ## -def ogGetFsSize (disk, par, unit='KB'): - factor = 1 - if unit.upper() == "MB": - factor = 1024 - elif unit.upper() == "GB": - factor = 1024 * 1024 - elif unit.upper() == "TB": - factor = 1024 * 1024 * 1024 - elif unit.upper() != "KB": - SystemLib.ogRaiseError ( - [], - ogGlobals.OG_ERR_FORMAT, - f"{unit} != {{ KB, MB, GB, TB }}" - ) - return - - # Obtener el tamaño del sistema de archivo (si no está formateado; tamaño = 0). - mnt = FileSystemLib.ogMount (disk, par) - if mnt: - result = subprocess.run(["df", "-BK", mnt], capture_output=True, text=True) - val = result.stdout.split("\n")[1].split()[1] - val = val.replace ('K', '') - sz = int (val) / factor - else: - sz = 0 - - return int (sz) - - -#/** -# ogGetFsType int_ndisk int_nfilesys -#@brief Devuelve el mnemonico con el tipo de sistema de archivos. -#@param int_ndisk nº de orden del disco -#@param int_nfilesys nº de orden del sistema de archivos -#@return Mnemonico -#@note Mnemonico: { EXT2, EXT3, EXT4, BTRFS, REISERFS, XFS, JFS, FAT12, FAT16, FAT32, NTFS, LINUX-SWAP, LINUX-LVM, LINUX-RAID, HFS, HFSPLUS, CACHE } -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. -#*/ ## -def ogGetFsType(disk, part): - PART = DiskLib.ogDiskToDev(disk, part) - if not PART: return - - TYPE = None - if PART.startswith("/"): - out = subprocess.run(["blkid", "-o", "export", PART], capture_output=True, text=True).stdout.splitlines() - for line in out: - if line.startswith("TYPE="): - TYPE = line.split("=")[1].upper() - break - else: - try: - subprocess.run(["zfs", "mount", PART]) - except FileNotFoundError: - SystemLib.ogRaiseError ( - [], - ogGlobals.OG_ERR_NOTEXEC, - 'zfs' - ) - return - out = subprocess.run(["mount"], capture_output=True, text=True).stdout.splitlines() - for line in out: - if line.startswith(PART): - TYPE = line.split()[4].upper() - break - - if not TYPE: - SystemLib.ogRaiseError ( - [], - ogGlobals.OG_ERR_NOTFOUND, - f'{disk} {part}' - ) - return - - # Componer valores correctos. - if TYPE == "EXT4": - if f"{disk} {part}" == CacheLib.ogFindCache(): - if ogIsFormated(disk, part): - TYPE = "CACHE" - elif TYPE == "VFAT": - result = subprocess.run(["blkid", "-po", "export", PART], capture_output=True, text=True) - for line in result.stdout.split("\n"): - if line.startswith("VERSION="): - TYPE = line.split("=")[1].upper() - break - elif TYPE == "SWAP": - TYPE = "LINUX-SWAP" - elif TYPE.startswith("LVM"): - TYPE = "LINUX-LVM" - elif "RAID" in TYPE: - TYPE = "LINUX-RAID" - elif TYPE == "ZFS_MEMBER": - TYPE = "ZVOL" - elif "_MEMBER" in TYPE: - TYPE = TYPE.replace("_MEMBER", "") - - return TYPE - - -#/** -# ogGetMountPoint int_ndisk int_nfilesys -#@brief Devuelve el punto de montaje de un sistema de archivos. -#@param int_ndisk nº de orden del disco -#@param int_nfilesys nº de orden del sistema de archivos -#@return Punto de montaje -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. -#@note Requisitos: \c mount* \c awk -#*/ ## - -def ogGetMountPoint(disk, par): - PART = DiskLib.ogDiskToDev(disk, par) - if not PART: return - - return subprocess.run(["findmnt", "-n", "-o", "TARGET", PART], capture_output=True, text=True).stdout.strip() - - - -#/** -# ogIsFormated int_ndisk int_nfilesys -#@brief Comprueba si un sistema de archivos está formateado. -#@param int_ndisk nº de orden del disco o volumen. -#@param int_nfilesys nº de orden del sistema de archivos -#@return Código de salida: True - formateado, False - sin formato o error. -#*/ ## -def ogIsFormated(disk, part): - PART = DiskLib.ogDiskToDev (disk, part) - if not PART: - return - - # Revisar tipo de sistema de archivos. - if PART.startswith("/"): - out = subprocess.run(["blkid", "-s", "TYPE", PART], capture_output=True, text=True).stdout.strip() - if 'swap' in out: return False - if '_member' in out: return False - return bool(out) - else: - out = subprocess.run(["zfs", "list", "-Hp", "-o", "canmount", PART], capture_output=True, text=True).stdout.strip() - return out == "on" - - - -#/** -# ogIsLocked int_ndisk int_npartition -#@see ogIsPartitionLocked -#*/ - -def ogIsLocked(disk, par): - return ogIsPartitionLocked(disk, par) - - -#/** -# ogIsPartitionLocked int_ndisk int_npartition -#@brief Comprueba si una partición o su disco están bloqueados por una operación de uso exclusivo. -#@param int_ndisk nº de orden del disco -#@param int_npartition nº de orden de la partición -#@return Código de salida: 0 - bloqueado, 1 - sin bloquear o error. -#@note Los ficheros de bloqueo se localizan en \c /var/lock/dev, siendo \c dev el dispositivo de la partición o de su disco, sustituyendo el carácter "/" por "-". -#*/ ## -def ogIsPartitionLocked(disk, par): - DISK = DiskLib.ogDiskToDev(disk) - PART = DiskLib.ogDiskToDev(disk, par) - if not PART: return - - LOCKDISK = f"/var/lock/lock{DISK.replace('/', '-')}" - LOCKPART = f"/var/lock/lock{PART.replace('/', '-')}" - rc = os.path.isfile(LOCKDISK) or os.path.isfile(LOCKPART) - return rc - -#/** -# ogIsMounted int_ndisk int_nfilesys -#@brief Comprueba si un sistema de archivos está montado. -#@param int_ndisk nº de orden del disco -#@param int_nfilesys nº de orden del sistema de archivos -#@return Código de salida: 0 - montado, 1 - sin montar o error. -#*/ ## -def ogIsMounted (disk, par): - return bool (ogGetMountPoint (disk, par)) - - -#/** -# ogIsReadonly int_ndisk int_nfilesys -#@brief Comprueba si un sistema de archivos está montado solo de lectura. -#@param int_ndisk nº de orden del disco -#@param int_nfilesys nº de orden del sistema de archivos -#@return Código de salida: 0 - montado solo de lectura, 1 - con escritura o no montado. -#@version 1.1.0 - Primera versión para OpenGnsys. -#@author Ramon Gomez, ETSII Universidad de Sevilla -#@date 2016-01-20 -#*/ ## - -def ogIsReadonly(disk, par): - PART = DiskLib.ogDiskToDev(disk, par) - if not PART: return - - result = subprocess.run(["findmnt", "-n", "-o", "OPTIONS", PART], capture_output=True, text=True) - options = result.stdout.strip().split(",") - return "ro" in options - - -#/** -# ogIsWritable int_ndisk int_nfilesys -#@brief Comprueba si un sistema de archivos está montado de lectura y escritura. -#@param int_ndisk nº de orden del disco -#@param int_nfilesys nº de orden del sistema de archivos -#@return Código de salida: 0 - lectura y escritura, 1 - solo lectura o no montado. -#*/ ## -def ogIsWritable (disk, par): - PART = DiskLib.ogDiskToDev (disk, par) - if not PART: return - - result = subprocess.run(["findmnt", "-n", "-o", "OPTIONS", PART], capture_output=True, text=True) - options = result.stdout.strip().split(",") - return "rw" in options - - -#/** -# ogLock int_ndisk int_npartition -#@see ogLockPartition -#*/ -def ogLock(disk, par): - return ogLockPartition(disk, par) - -#/** -# ogLockPartition int_ndisk int_npartition -#@brief Genera un fichero de bloqueo para una partición en uso exlusivo. -#@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 corresponden con un dispositivo. -#@note El fichero de bloqueo se localiza en \c /var/lock/part, siendo \c part el dispositivo de la partición, sustituyendo el carácter "/" por "-". -#*/ ## -def ogLockPartition (disk, par): - PART = DiskLib.ogDiskToDev (disk, par) - if not PART: return - - LOCKFILE = f"/var/lock/lock{PART.replace('/', '-')}" - try: - open (LOCKFILE, 'w').close() - except: - return False - return True - - -#/** -# ogMount int_ndisk int_nfilesys -#@see ogMountFs ogMountCache ogMountCdrom -#*/ ## -def ogMount(*args): - if 1 == len (args): - if 'cache' == args[0].lower(): - return DiskLib.ogMountCache() - elif 'cdrom' == args[0].lower(): - return ogMountCdrom() - elif 2 == len (args): - return ogMountFs(args[0], args[1]) - - -#/** -# ogMountFirstFs int_ndisk -#@brief Monta el primer sistema de archivos disponible en el disco. -#@param int_ndisk nº de orden del disco -#@return Punto de montaje del primer sistema de archivos detectado -#*/ ## -def ogMountFirstFs (disk): - NPARTS = DiskLib.ogGetPartitionsNumber (disk) - for PART in range (1, NPARTS + 1): - MNTDIR = ogMount (disk, PART) - if MNTDIR: - return MNTDIR - SystemLib.ogRaiseError ('session', ogGlobals.OG_ERR_NOTFOUND, f'{disk}') - return ogGlobals.OG_ERR_NOTFOUND - -#/** -# ogMountFs int_ndisk int_nfilesys -#@brief Monta un sistema de archivos. -#@param int_ndisk nº de orden del disco -#@param int_nfilesys nº de orden del sistema de archivos -#@return Punto de montaje -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. -#@exception OG_ERR_PARTITION Tipo de particion desconocido o no se puede montar. -#*/ ## -def ogMountFs (disk, par): - dev = DiskLib.ogDiskToDev (disk, par) - if not dev: return - - mntdir = ogGetMountPoint (disk, par) - if mntdir: return mntdir - - if ogIsLocked (disk, par): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_LOCKED, f'{ogGlobals.lang.MSG_PARTITION}, {disk} {par}') - return - - # El camino de un dispositivo normal comienza por el carácter "/". - if dev.startswith ('/'): - # Crear punto de montaje o enlace simbólico para caché local. - mntdir = dev.replace ('/dev', '/mnt') - if f"{disk} {par}" == CacheLib.ogFindCache(): - os.makedirs(ogGlobals.OGCAC, exist_ok=True) - try: - os.symlink(ogGlobals.OGCAC, mntdir) - except FileExistsError: - pass - else: - os.makedirs(mntdir, exist_ok=True) - - # Montar sistema de archivos. - try: - rc = subprocess.run(['mount', dev, mntdir], check=True).returncode - except subprocess.CalledProcessError: - try: - rc = subprocess.run(['mount', dev, mntdir, '-o', 'force,remove_hiberfile'], check=True).returncode - except subprocess.CalledProcessError: - SystemLib.ogRaiseError ( - [], - ogGlobals.OG_ERR_PARTITION, - f"{disk}, {par}" - ) - return - - if 0 == rc: - pass - elif 14 == rc: - try: - subprocess.run (['ntfsfix', '-d', par], check=True) - except subprocess.CalledProcessError: - SystemLib.ogRaiseError ( - [], - ogGlobals.OG_ERR_PARTITION, - f"{disk, par}" - ) - #return - else: - try: - subprocess.run (['mount', par, mntdir, '-o', 'ro'], check=True) - except subprocess.CalledProcessError: - SystemLib.ogRaiseError ( - [], - ogGlobals.OG_ERR_PARTITION, - f"{disk, par}" - ) - #return - - # Aviso de montaje de solo lectura. - if ogIsReadonly(disk, par): - SystemLib.ogEcho("warning", f'ogMountFs: {ogGlobals.lang.MSG_MOUNTREADONLY}: "{disk}, {par}"') - else: - # Montar sistema de archivos ZFS (un ZPOOL no comienza por "/"). - subprocess.run(['zfs', 'mount', dev]) - - return mntdir - - - -#/** -# ogMountCdrom -#@brief Monta dispositivo óptico por defecto -#@return Punto de montaje -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_PARTITION Tipo de particion desconocido o no se puede montar. -#@version -#@author -#@date -#*/ ## -def ogMountCdrom(): - DEV = '/dev/cdrom' # Por defecto - outlines = subprocess.run (['mount'], capture_output=True, text=True).stdout.split ('\n') - mntdir = '' - for l in outlines: - items = l.split (' ') - if DEV == items[0]: - mntdir = items[2] - break - - if not mntdir: - mntdir = DEV.replace ('/dev', '/mnt') - os.makedirs (mntdir, exist_ok=True) - try: - subprocess.run (['mount', '-t', 'iso9660', DEV, mntdir], check=True) - except subprocess.CalledProcessError: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, 'cdrom') - return None - - return mntdir - - -#/** -# ogReduceFs int_ndisk int_nfilesys -#@brief Reduce el tamaño del sistema de archivos, sin tener en cuenta el espacio libre. -#@param int_ndisk nº de orden del disco -#@param int_nfilesys nº de orden del sistema de archivos -#@return int_tamañoKB - tamaño en KB -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. -#@exception OG_ERR_PARTITION Partición desconocida o no accesible. -#@warning En Windows, se borran los ficheros de hiberanción y de paginación. -#@warning El sistema de archivos se amplía al mínimo + 10%. -#@note Requisitos: *resize* -#*/ ## -def ogReduceFs (disk, par): - PART = DiskLib.ogDiskToDev (disk, par) - if not PART: return - - # Redimensionar según el tipo de partición. - type = ogGetFsType (disk, par) - if type in ['EXT2', 'EXT3', 'EXT4']: - ogUnmount (disk, par) - rc = subprocess.run (['resize2fs', '-fpM', PART], capture_output=True, text=True).returncode - if rc: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f"{disk},{par}") - return None - elif 'BTRFS' == type: - mntdir = ogMount (disk, par) - # Calcular tamaño ocupado + 10%, redondeado + 1 (incluyendo letra de unidad). - btrfs_lines = subprocess.run (['btrfs', 'filesystem', 'show', mntdir], capture_output=True, text=True).stdout.splitlines() - for l in btrfs_lines: - if 'devid' not in l: continue - ## 'devid 2 size 8.89GiB used 1.00GiB path /dev/sda4' - devid_str, devid, size_str, size, used_str, used, path_str, path = l.split() - if PART != os.path.realpath (path): continue - (sz, unit) = re.search ('^([^A-Z]+)([A-Z])', used).groups() - sz = float (sz) * 1.1 + 1 - size = f'{str(sz)}{unit}' - subprocess.run (['btrfs', 'filesystem', 'resize', size, mntdir], capture_output=True, text=True) - break - elif type in ['REISERFS', 'REISER4']: - mntdir = ogMount (disk, par) - df_lines = subprocess.run (['df', '-k', mntdir], capture_output=True, text=True).stdout.splitlines() - for l in df_lines: - if 'Filesystem' in l: continue - fs, blocks, used, avail, use_pct, mntpt = l.split() - size = str (int (used) * 1.1) - ogUnmount (disk, par) - subprocess.run (['resize_reiserfs', f'-s{size}K', PART], input='y\n', capture_output=True, text=True) - break - elif type == 'NTFS': - ogUnmount (disk, par) - nr_lines = subprocess.run (['ntfsresize', '-fi', PART], capture_output=True, text=True).stdout.splitlines() - maxsize = None - size = None - for l in nr_lines: - if 'device size' in l: - maxsize = float (l.split()[3]) - if 'resize at' in l: - size = l.split()[4] - size = int ((int (size) * 1.1 / 1024 + 1) * 1024) - - if not maxsize and not size: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f'{disk},{par}') - return None - - import time - - extrasize = 0 - retval = 1 - while retval != 0 and size+extrasize < maxsize: - nr = subprocess.run (['ntfsresize', '-fns', str(size), PART], capture_output=True, text=True) - for l in nr.stdout.splitlines(): - if 'Needed relocations' not in l: continue - extrasize = int ((int (l.split()[3])*1.1/1024+1)*1024) - break - retval = nr.returncode - size += extrasize - if size < maxsize: - rc = subprocess.run (['ntfsresize', '-fs', str(size), PART], input='y\n', capture_output=True, text=True).returncode - if rc: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f"{disk},{par}") - return None - elif type in ['FAT32', 'FAT16', 'F2FS', 'JFS', 'NILFS2', 'XFS', 'EXFAT', 'HFS', 'HFSPLUS', 'UFS']: - pass - else: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f"{disk},{par}") - return None - - return ogGetFsSize (disk, par) - - -#/** -# ogUnlock int_ndisk int_npartition -#@see ogUnlockPartition -#*/ ## -def ogUnlock (disk, par): - return ogUnlockPartition (disk, par) - -#/** -# ogUnlockPartition int_ndisk int_npartition -#@brief Elimina el fichero de bloqueo para una particion. -#@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 corresponden con un dispositivo. -#@note El fichero de bloqueo se localiza en \c /var/lock/part, siendo \c part el dispositivo de la partición, sustituyendo el carácter "/" por "-". -#*/ ## -def ogUnlockPartition (disk, par): - PART = DiskLib.ogDiskToDev (disk, par) - if not PART: return - - LOCKFILE = f"/var/lock/lock{PART.replace('/', '-')}" - if os.path.exists (LOCKFILE): - os.remove (LOCKFILE) - - -#/** -# ogUnmount int_ndisk int_npartition -#@see ogUnmountFs -#*/ ## -def ogUnmount (disk, par): - return ogUnmountFs (disk, par) - -#/** -# ogUnmountFs int_ndisk int_nfilesys -#@brief Desmonta un sistema de archivos. -#@param int_ndisk nº de orden del disco -#@param int_nfilesys nº de orden del sistema de archivos -#@return Nada -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. -#@warning La partición no está previamente montada o no se puede desmontar. -#*/ ## - -def ogUnmountFs(disk, par): - PART = DiskLib.ogDiskToDev (disk, par) - if not PART: return - MNTDIR = ogGetMountPoint (disk, par) - - # Si está montada, desmontarla. - if MNTDIR: - # Error si la particion está bloqueada. - if ogIsLocked (disk, par): - SystemLib.ogRaiseError ( - [], - ogGlobals.OG_ERR_LOCKED, - f"{ogGlobals.lang.MSG_PARTITION}, {disk} {par}" - ) - return - - # Desmontar y borrar punto de montaje. - try: - subprocess.run(["umount", PART], check=True) - except subprocess.CalledProcessError: - SystemLib.ogEcho("warning", f'ogUnmountFs: {ogGlobals.lang.MSG_DONTUNMOUNT}: "{disk}, {par}"') - try: - os.rmdir(MNTDIR) - except: - try: - os.remove(MNTDIR) - except: - pass - return True - else: - SystemLib.ogEcho ([], "warning", f'{ogGlobals.lang.MSG_DONTMOUNT}: "{disk},{par}"') - return True - - -#/** -# ogUnmountAll int_ndisk -#@brief Desmonta todos los sistema de archivos de un disco, excepto el caché local. -#@param int_ndisk nº de orden del disco -#@return Nada -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. -#@warning No se desmonta la partición marcada como caché local. -#*/ ## -def ogUnmountAll (disk): - DISK = DiskLib.ogDiskToDev (disk) - n = DiskLib.ogGetPartitionsNumber (disk) - if not n: return None - for PART in range (1, n+1): - if 'CACHE' != ogGetFsType (disk, PART): - ogUnmount (disk, PART) - - -#/** -# ogUnsetDirtyBit int_ndisk int_npart -#@brief Inhabilita el Dirty Bit del sistema de ficheros NTFS para evitar un CHKDSK en el primer arranque -#@param int_ndisk nº de orden del disco -#@param int_npart nº de orden de partición -#@return Nada -#@exception OG_ERR_FORMAT Formato incorrecto. -#*/ ## -def ogUnsetDirtyBit (disk, par): - PART = DiskLib.ogDiskToDev (disk, par) - if not PART: return None - - TYPE = ogGetFsType (disk, par) - if 'NTFS' == TYPE: - ogUnmount (disk, par) - subprocess.run (['ntfsfix', '--clear-dirty', PART]) - - -#/** -# ogGetFreeSize int_disco int_partition str_SizeOutput -#@brief muestra informacion del tamaño total, datos y libre. -#@param int_ndisk nº de orden del disco -#@param int_npart nº de orden de partición -#@param str_unitSize unidad mostrada -#@return int_size:int_data:int_free -#@TODO Componer corretcamente esta función. -#@exception OG_ERR_FORMAT Formato incorrecto. -#*/ ## - -def ogGetFreeSize(disk, part, unit='KB'): - PART = DiskLib.ogDiskToDev (disk, part) - if not PART: return - - unit2factor = { - 'kb': 1.024 / 1, - 'mb': 1.024 / 1000, - 'gb': 1.024 / 1000000, - } - if unit.lower() not in unit2factor: - kk - factor = unit2factor[unit.lower()] - - particion = FileSystemLib.ogMount (disk, part) - if not particion: - kk - df = subprocess.run (['df'], capture_output=True, text=True).stdout - df_part = list (filter (lambda l: particion in l, df.splitlines())) - if not len (df_part): - kk - _, size, used, free, pct, mntpt = df_part[0].split() - return float (free) * factor diff --git a/client/lib/engine/bin/Image.lib b/client/lib/engine/bin/Image.lib new file mode 100755 index 0000000..cf9eb83 --- /dev/null +++ b/client/lib/engine/bin/Image.lib @@ -0,0 +1,1209 @@ +#!/bin/bash +#/** +#@file Image.lib +#@brief Librería o clase Image +#@class Image +#@brief Funciones para creación, restauración y clonación de imágenes de sistemas. +#@version 1.1.0 +#@warning License: GNU GPLv3+ +#*/ + + +#/** +# ogCreateImageSyntax path_device path_filename [str_tool] [str_compressionlevel] +#@brief Genera una cadena de texto con la instrucción para crear un fichero imagen +#@param path_device dispositivo Linux del sistema de archivos +#@param path_fileneme path absoluto del fichero imagen +#@param [opcional] str_tool herrmaienta de clonacion [partimage, partclone, ntfsclone] +#@param [opcional] str_compressionlevel nivel de compresion. [0 -none-, 1-lzop-, 2-gzip] +#@return str_command - cadena con el comando que se debe ejecutar. +#@warning Salida nula si se producen errores. +#@TODO introducir las herramientas fsarchiver, dd +#@version 1.0 - Primeras pruebas +#@author Antonio J. Doblas Viso. Universidad de Málaga +#@date 2010/02/08 +#@version 1.0.5 - Incrustar códico de antigua función ogPartcloneSyntax +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2012/09/14 +#*/ ## +function ogCreateImageSyntax() +{ +local FS TOOL LEVEL DEV IMGFILE BUFFER PARAM1 PARAM2 PARAM3 + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME path_device path_imagefile [str_tool] [str_compressionlevel]" \ + "$FUNCNAME /dev/sda1 /opt/opengnsys/images/prueba.img partclone lzop" \ + "$FUNCNAME /dev/sda1 /opt/opengnsys/images/prueba.img" + return +fi +# Error si no se reciben entre 2 y 4 parámetros. +[ $# -ge 2 -a $# -le 4 ] || ogRaiseError $OG_ERR_FORMAT "$*" || return $? + +# Asignación de parámetros. +DEV="$1" +IMGFILE="$2" +case "$#" in + 2) # Sintaxis por defecto OG DEV IMGFILE + TOOL="partclone" + LEVEL="gzip" + ;; + 4) # Sintaxis condicionada. + TOOL="${3,,}" + LEVEL="${4,,}" + ;; +esac + +case "$TOOL" in + ntfsclone) + PARAM1="ntfsclone --force --save-image -O - $DEV" + ;; + partimage|default) + PARAM1="partimage -M -f3 -o -d -B gui=no -c -z0 --volume=0 save $DEV stdout" + ;; + partclone) + FS="$(ogGetFsType $(ogDevToDisk $DEV 2>/dev/null) 2>/dev/null)" + case "$FS" in + EXT[234]) PARAM1="partclone.extfs" ;; + BTRFS) PARAM1="partclone.btrfs" ;; + REISERFS) PARAM1="partclone.reiserfs" ;; + REISER4) PARAM1="partclone.reiser4" ;; + JFS) PARAM1="partclone.jfs" ;; + XFS) PARAM1="partclone.xfs" ;; + F2FS) PARAM1="partclone.f2fs" ;; + NILFS2) PARAM1="partclone.nilfs2" ;; + NTFS) PARAM1="partclone.ntfs" ;; + EXFAT) PARAM1="partclone.exfat" ;; + FAT16|FAT32) PARAM1="partclone.fat" ;; + HFS|HFSPLUS) PARAM1="partclone.hfsp" ;; + UFS) PARAM1="partclone.ufs" ;; + VMFS) PARAM1="partclone.vmfs" ;; + *) PARAM1="partclone.imager" ;; + esac + # Por compatibilidad, si no existe el ejecutable usar por defecto "parclone.dd". + which $PARAM1 &>/dev/null || PARAM1="partclone.dd" + PARAM1="$PARAM1 -d0 -F -c -s $DEV" + # Algunas versiones de partclone.dd no tienen opción "-c". + [ -z "$(eval ${PARAM1%% *} --help 2>&1 | grep -- -c)" ] && PARAM1="${PARAM1/ -c / }" + ;; +esac +# Comprobar que existe mbuffer. +which mbuffer &>/dev/null && PARAM2="| mbuffer -q -m 40M " || PARAM2=" " + +# Nivel de compresion. +case "$LEVEL" in + 0|none) PARAM3=" > " ;; + 1|lzop) PARAM3=" | lzop > " ;; + 2|gzip) PARAM3=" | gzip -c > " ;; + 3|bzip) PARAM3=" | bzip -c > " ;; +esac + +# Sintaxis final. +[ -n "$PARAM1" ] && echo "$PARAM1 $PARAM2 $PARAM3 $IMGFILE" +} + + +#/** +# ogRestoreImageSyntax path_filename path_device [str_tools] [str_compressionlevel] +#@brief Genera una cadena de texto con la instrucción para crear un fichero imagen +#@param path_device dispositivo Linux del sistema de archivos +#@param path_fileneme path absoluto del fichero imagen +#@param [opcional] str_tools herrmaienta de clonacion [partimage, partclone, ntfsclone] +#@param [opcional] str_compressionlevel nivel de compresion. [0 -none-, 1-lzop-, 2-gzip] +#@return cadena con el comando que se debe ejecutar. +#@exception OG_ERR_FORMAT formato incorrecto. +#@warning En pruebas iniciales +#@TODO introducir las herramientas fsarchiver, dd +#@TODO introducir el nivel de compresion gzip +#@version 1.0 - Primeras pruebas +#@author Antonio J. Doblas Viso. Universidad de Málaga +#@date 2010/02/08 +#*/ ## +function ogRestoreImageSyntax () +{ +local TOOL COMPRESSOR LEVEL PART IMGFILE FILEHEAD INFOIMG + + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME filename partition [tool] [levelcompresor]" \ + "$FUNCNAME /opt/opengnsys/images/prueba.img /dev/sda1 [partclone] [lzop]" + return +fi + +# Error si no se reciben entre 2 y 4 parámetros. +[ $# -ge 2 -a $# -le 4 ] || ogRaiseError $OG_ERR_FORMAT "$*" || return $? + +# controlamos que el parametro 1 (imagen) es tipo file. +[ -f $1 ] || ogRaiseError $OG_ERR_NOTFOUND "$1" || return $? + +# Si 2 parametros (file-origen-, device-destino-) = ogGetImageFull($1) +if [ "$#" -eq 2 ]; then + IMGFILE=$1 + PART=$2 + INFOIMG=$(ogGetImageInfo $IMGFILE) || ogRaiseError $OG_ERR_NOTFOUND "No Image $1" || return $? + TOOL=`echo $INFOIMG | cut -f1 -d:` + COMPRESSOR=`echo $INFOIMG | cut -f2 -d:` + ogRestoreImageSyntax $IMGFILE $PART $TOOL $COMPRESSOR +fi + + +# Si cuatro parametros genera sintaxis +if [ "$#" -eq 4 ]; then + IMGFILE=$1 + PART=$2 + # comprobamos parametro herramienta compresion. + TOOL=$(echo $3 | tr [A-Z] [a-z]) + #ogCheckProgram $TOOL + #comprobar parámetro compresor. + LEVEL=$(echo $4 | tr [A-Z] [a-z]) + #ogCheckProgram $LEVEL + + case "$LEVEL" in + "0"|"none") + COMPRESSOR=" " + ;; + "1"|"lzop" | "LZOP") + COMPRESSOR=" lzop -dc " + ;; + "2"|"gzip" | "GZIP") + COMPRESSOR=" gzip -dc " + ;; + "3"|"bzip" | "BZIP" ) + COMPRESSOR=" bzip -dc " + ;; + *) + ogRaiseError $OG_ERR_NOTFOUND "Compressor no valid $TOOL" || return $? + ;; + esac + #comprobar mbuffer + which mbuffer > /dev/null && MBUFFER="| mbuffer -q -m 40M " || MBUFFER=" " + + case "${TOOL,,}" in + ntfsclone) + TOOL="| ntfsclone --restore-image --overwrite $PART -" + ;; + partimage) + TOOL="| partimage -f3 -B gui=no restore $PART stdin" + ;; + partclone*) + # -C para que no compruebe tamaños + TOOL="| partclone.restore -d0 -C -I -o $PART" + ;; + dd) + TOOL="| pv | dd conv=sync,noerror bs=1M of=$PART" + ;; + *) + ogRaiseError $OG_ERR_NOTFOUND "Tools imaging no valid $TOOL" || return $? + ;; + esac + + echo "$COMPRESSOR $IMGFILE $MBUFFER $TOOL" +fi + +} + + + + +#/** +# ogCreateDiskImage int_ndisk str_repo path_image [str_tools] [str_compressionlevel] +#@brief Crea una imagen (copia de seguridad) de un disco completo. +#@param int_ndisk nº de orden del disco +#@param str_repo repositorio de imágenes (remoto o caché local) +#@param path_image camino de la imagen (sin extensión) +#@return (nada, por determinar) +#@note repo = { REPO, CACHE } +#@note Esta primera versión crea imágenes con dd comprimidas con gzip. +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. +#@exception OG_ERR_LOCKED particion bloqueada por otra operación. +#@exception OG_ERR_IMAGE error al crear la imagen del sistema. +#@warning En pruebas iniciales +#@todo Gestión de bloqueos de disco +#@todo Comprobar si debe desmontarse la caché local +#@todo Comprobar que no se crea la imagen en el propio disco +#@version 1.1.0 - Primera versión para OpenGnsys con herramientas prefijadas. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@Date 2016/04/08 +#*/ ## +function ogCreateDiskImage () +{ +# Variables locales +local DISK PROGRAM IMGDIR IMGFILE IMGTYPE ERRCODE + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk str_repo path_image" \ + "$FUNCNAME 1 REPO /disk1" + return +fi +# Error si no se reciben entre 3 y 5 parámetros. +[ $# -ge 3 -a $# -le 5 ] || ogRaiseError $OG_ERR_FORMAT "$*" || return $? + +# Comprobar que no está bloqueada ni la partición, ni la imagen. +DISK="$(ogDiskToDev $1)" || return $? +if ogIsDiskLocked $1; then + ogRaiseError $OG_ERR_LOCKED "$MSG_LOCKED $1" + return $? +fi +IMGTYPE="dsk" # Extensión genérica de imágenes de disco. +IMGDIR=$(ogGetParentPath "$2" "$3") +[ -n "$IMGDIR" ] || ogRaiseError $OG_ERR_NOTFOUND "$2 $(dirname $3)" || return $? +IMGFILE="$IMGDIR/$(basename "$3").$IMGTYPE" +if ogIsImageLocked "$IMGFILE"; then + ogRaiseError $OG_ERR_LOCKED "$MSG_IMAGE $3, $4" + return $? +fi + +# No guardar imagen en el propio disco (disco no incluido en el camino del repositorio). +if [[ $(ogGetPath "$2" /) =~ ^$DISK ]]; then + ogRaiseError $OG_ERR_IMAGE "$2 = $DISK" + return $? +fi + +# Generar la instruccion a ejecutar antes de aplicar los bloqueos. +PROGRAM=$(ogCreateImageSyntax $DISK $IMGFILE) +# Desmontar todos los sistemas de archivos del disco, bloquear disco e imagen. +ogUnmountAll $1 2>/dev/null +ogLockDisk $1 || return $? +ogLockImage "$2" "$3.$IMGTYPE" || return $? + +# Crear Imagen. +trap "ogUnlockDisk $1; ogUnlockImage "$3" "$4.$IMGTYPE"; rm -f $IMGFILE" 1 2 3 6 9 +eval $PROGRAM + +# Controlar salida de error, crear fichero de información y desbloquear partición. +ERRCODE=$? +if [ $ERRCODE == 0 ]; then + echo "$(ogGetImageInfo $IMGFILE):$(ogGetHostname)" > $IMGFILE.info +else + ogRaiseError $OG_ERR_IMAGE "$1 $2 $IMGFILE" + rm -f "$IMGFILE" +fi +# Desbloquear disco e imagen. +ogUnlockDisk $1 +ogUnlockImage "$2" "$3.$IMGTYPE" +return $ERRCODE +} + + +#/** +# ogCreateImage int_ndisk int_npartition str_repo path_image [str_tools] [str_compressionlevel] +#@brief Crea una imagen a partir de una partición. +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@param str_repo repositorio de imágenes (remoto o caché local) +#@param path_image camino de la imagen (sin extensión) +#@param [opcional] str_tools herrmaienta de clonacion [partimage, partclone, ntfsclone] +#@param [opcional] str_compressionlevel nivel de compresion. [0 -none-, 1-lzop-, 2-gzip] +#@return (nada, por determinar) +#@note repo = { REPO, CACHE } +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. +#@exception OG_ERR_PARTITION partición no accesible o no soportada. +#@exception OG_ERR_LOCKED particion bloqueada por otra operación. +#@exception OG_ERR_IMAGE error al crear la imagen del sistema. +#@todo Comprobaciones, control de errores, definir parámetros, etc. +#@version 0.1 - Integracion para Opengnsys - HIDRA:CrearImagen{EXT3, NTFS}.sh; EAC: CreateImageFromPartition () en Deploy.lib +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@Date 2008/05/13 +#@author Antonio J. Doblas Viso. Universidad de Malaga +#@date 2008/10/27 +#@version 0.9 - Versión en pruebas para OpenGnSys +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2009/10/07 +#@version 1.0 - Llama a función ogCreateImageSyntax para generar la llamada al comando. +#@author Antonio J. Doblas Viso. Universidad de Málaga +#@date 2010/02/08 +#*/ ## +function ogCreateImage () +{ +# Variables locales +local PART PROGRAM IMGDIR IMGFILE IMGTYPE ERRCODE + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_npart str_repo path_image" \ + "$FUNCNAME 1 1 REPO /aula1/win7" + return +fi +# Error si no se reciben entre 4 y 6 parámetros. +[ $# -ge 4 -a $# -le 6 ] || ogRaiseError $OG_ERR_FORMAT "$*" || return $? + +# Comprobar que no está bloqueada ni la partición, ni la imagen. +PART="$(ogDiskToDev $1 $2)" || return $? +if ogIsLocked $1 $2; then + ogRaiseError $OG_ERR_LOCKED "$MSG_LOCKED $1, $2" + return $? +fi + +IMGTYPE="img" # Extensión genérica de imágenes. +IMGDIR=$(ogGetParentPath "$3" "$4") +[ -n "$IMGDIR" ] || ogRaiseError $OG_ERR_NOTFOUND "$3 $(dirname $4)" || return $? + +IMGFILE="$IMGDIR/$(basename "$4").$IMGTYPE" +if ogIsImageLocked "$IMGFILE"; then + ogRaiseError $OG_ERR_LOCKED "$MSG_IMAGE $3, $4" + return $? +fi +# Generar la instruccion a ejecutar antes de aplicar los bloqueos. +PROGRAM=$(ogCreateImageSyntax $PART $IMGFILE $5 $6) +# Desmontar partición, bloquear partición e imagen. +ogUnmount $1 $2 2>/dev/null +ogLock $1 $2 || return $? +ogLockImage "$3" "$4.$IMGTYPE" || return $? + +# Crear Imagen. +trap "ogUnlock $1 $2; ogUnlockImage "$3" "$4.$IMGTYPE"; rm -f $IMGFILE" 1 2 3 6 9 +eval $PROGRAM + +# Controlar salida de error, crear fichero de información y desbloquear partición. +ERRCODE=$? +if [ $ERRCODE == 0 ]; then + echo "$(ogGetImageInfo $IMGFILE):$(ogGetHostname)" > $IMGFILE.info +else + ogRaiseError $OG_ERR_IMAGE "$1 $2 $IMGFILE" + rm -f "$IMGFILE" +fi +# Desbloquear partición e imagen. +ogUnlock $1 $2 +ogUnlockImage "$3" "$4.$IMGTYPE" +return $ERRCODE +} + + +#/** +# ogCreateMbrImage int_ndisk str_repo path_image +#@brief Crea una imagen a partir del sector de arranque de un disco. +#@param int_ndisk nº de orden del disco +#@param str_repo repositorio de imágenes (remoto o caché local) +#@param path_image camino de la imagen (sin extensión) +#@return (nada, por determinar) +#@note repo = { REPO, CACHE } +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. +#@exception OG_ERR_IMAGE error al crear la imagen del sistema. +#@version 0.9 - Versión en pruebas para OpenGNSys +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2010/01/12 +#@version 1.0 - Adaptación a OpenGnSys 1.0 +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2011/03/10 +#*/ ## +function ogCreateMbrImage () +{ +# Variables locales +local DISK IMGDIR IMGFILE +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk str_repo path_image" \ + "$FUNCNAME 1 REPO /aula1/mbr" + return +fi +# Error si no se reciben 3 parámetros. +[ $# == 3 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +DISK=$(ogDiskToDev "$1") || return $? +IMGDIR=$(ogGetParentPath "$2" "$3") +[ -n "$IMGDIR" ] || ogRaiseError $OG_ERR_NOTFOUND "$2 $(dirname $3)" || return $? +IMGFILE="$IMGDIR/$(basename "$3").mbr" + +# Crear imagen del MBR. +dd if="$DISK" of="$IMGFILE" bs=512 count=1 || ogRaiseError $OG_ERR_IMAGE "$1 $IMGFILE" || return $? +} + + +#/** +# ogCreateBootLoaderImage int_ndisk str_repo path_image +#@brief Crea una imagen del boot loader a partir del sector de arranque de un disco. +#@param int_ndisk nº de orden del disco +#@param str_repo repositorio de imágenes (remoto o caché local) +#@param path_image camino de la imagen (sin extensión) +#@return (nada, por determinar) +#@note repo = { REPO, CACHE } +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. +#@exception OG_ERR_IMAGE error al crear la imagen del sistema. +#@version 1.0 - Adaptacion de ogCreateMbrImage para guardar solo el Boot Loader +#@author Juan Carlos Xifre, SICUZ Universidad de Zaragoza +#@date 2011/03/21 +#*/ ## +function ogCreateBootLoaderImage () +{ +# Variables locales +local DISK IMGDIR IMGFILE +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk str_repo path_image" \ + "$FUNCNAME 1 REPO /aula1/mbr" + return +fi +# Error si no se reciben 3 parámetros. +[ $# == 3 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +DISK=$(ogDiskToDev "$1") || return $? +IMGDIR=$(ogGetParentPath "$2" "$3") +[ -n "$IMGDIR" ] || ogRaiseError $OG_ERR_NOTFOUND "$2 $(dirname $3)" || return $? +IMGFILE="$IMGDIR/$(basename "$3").mbr" + +# Crear imagen del Boot Loader dentro del MBR. +dd if="$DISK" of="$IMGFILE" bs=446 count=1 || ogRaiseError $OG_ERR_IMAGE "$1 $IMGFILE" || return $? +} + +#/** +# ogGetSizeParameters int_num_disk int_num_part str_repo [monolit|sync|diff] +#@brief Devuelve el tamaño de los datos de un sistema de ficheros, el espacio necesario para la imagen y si cabe en el repositorio elegido. +#@param int_disk numero de disco +#@param int_part numero de particion +#@param str_repo repositorio de imágenes { REPO, CACHE } +#@param str_imageName Nombre de la imagen +#@param str_imageType Tipo de imagen: monolit (por defecto), sync o diff. (parametro opcional) +#@return SIZEDATA SIZEREQUIRED SIZEFREE ISENOUGHSPACE +#@note si str_imageType= diff necesario /tmp/ogimg.info, que es creado por ogCreateInfoImage. +#@note para el tamaño de la imagen no sigue enlaces simbólicos. +#@exception OG_ERR_FORMAT formato incorrecto. +#@author Irina Gomez, ETSII Universidad de Sevilla +#@date 2014/10/24 +#@version 1.1.0 - En la salida se incluye el espacio disponible en el repositorio (ticket #771) +#@author Irina Gomez - ETSII Universidad de Sevilla +#@date 2017-03-28 +#@version 1.1.0 - Si la imagen ya existe en el REPO se suma su tamaño al espacio libre +#@author Irina Gomez - ETSII Universidad de Sevilla +#@date 2017-11-08 +#*/ ## +function ogGetSizeParameters () +{ +local REPO MNTDIR SIZEDATA KERNELVERSION SIZEREQUIRED FACTORGZIP FACTORLZOP FACTORSYNC SIZEFREE +local IMGTYPE IMGDIR IMGFILE IMGEXT IMGSIZE + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME num_disk num_part str_repo path_imgname [monolit|sync|diff]" \ + "if $FUNCNAME 1 2 REPO Windows10 sync ; then ...; fi" \ + "if $FUNCNAME 1 6 Ubuntu16 CACHE ; then ...; fi" + return +fi +# Error si no se reciben 1 o 2 parámetros. +[ $# -lt 4 ] && return $(ogRaiseError session $OG_ERR_FORMAT "$MSG_FORMAT: $PROG ndisco nparticion REPO|CACHE imgname [monolit|sync|diff]" ; echo $?) + +# Recogemos parametros +REPO=${3^^} +IMGTYPE="_${5^^}_" + +MNTDIR=$(ogMount $1 $2) +if [ "$MNTDIR" == "" ]; then + ogRaiseError $OG_ERR_PARTITION "$1 $2" + return $? +fi + +# Datos contenidos en la particion o en la lista de archivos de contiene la diferencial. +if [ "$IMGTYPE" == "_DIFF_" ]; then + [ -r /tmp/ogimg.info ] || return $(ogRaiseError session $OG_ERR_NOTFOUND "/tmp/ogimg.info"; echo $?) + cd $MNTDIR + SIZEDATA=$(grep -v "\/$" /tmp/ogimg.info | tr '\n' '\0'| du -x -c --files0-from=- 2>/dev/null|tail -n1 |cut -f1) + cd / +else + SIZEDATA=$(df -k | grep $MNTDIR\$ | awk '{print $3}') +fi + +#Aplicar factor de compresion +if [ "$IMGTYPE" == "_SYNC_" -o "$IMGTYPE" == "_DIFF_" ]; then + + # Sistema de fichero de la imagen según kernel, menor que 3.7 EXT4. comparamos revision + KERNELVERSION=$(uname -r| awk '{printf("%d",$1);sub(/[0-9]*\./,"",$1);printf(".%02d",$1)}') + [ $KERNELVERSION \< 3.07 ] && IMGFS="EXT4" || IMGFS=${IMGFS:-"BTRFS"} + FACTORSYNC=${FACTORSYNC:-"130"} + # Si IMGFS="BTRFS" la compresion es mayor. + [ $IMGFS == "BTRFS" ] && let FACTORSYNC=$FACTORSYNC-20 + + let SIZEREQUIRED=$SIZEDATA*$FACTORSYNC/100 + # El tamaño mínimo del sistema de ficheros btrfs es 250M, ponemos 300 + [ $SIZEREQUIRED -lt 300000 ] && SIZEREQUIRED=300000 + +else + FACTORGZIP=55/100 + FACTORLZOP=65/100 + let SIZEREQUIRED=$SIZEDATA*$FACTORLZOP +fi + +#Comprobar espacio libre en el contenedor. +[ "$REPO" == "CACHE" ] && SIZEFREE=$(ogGetFreeSize `ogFindCache`) +[ "$REPO" == "REPO" ] && SIZEFREE=$(df -k | grep $OGIMG | awk '{print $4}') + +# Comprobamos si existe una imagen con el mismo nombre en $REPO +# En sincronizadas restamos tamaño de la imagen y en monoloticas de la .ant +case "${IMGTYPE}" in + _DIFF_) IMGEXT="img.diff" + ;; + _SYNC_) IMGEXT="img" + ;; + *) IMGEXT="img.ant" + ;; +esac + +IMGDIR=$(ogGetParentPath "$REPO" "/$4") +IMGFILE=$(ogGetPath "$IMGDIR/$(basename "/$4").$IMGEXT") +if [ -z "$IMGFILE" ]; then + IMGSIZE=0 +else + IMGSIZE=$(ls -s "$IMGFILE" | cut -f1 -d" ") +fi + +let SIZEFREE=$SIZEFREE+$IMGSIZE + +[ "$SIZEREQUIRED" -lt "$SIZEFREE" ] && ISENOUGHSPACE=TRUE || ISENOUGHSPACE=FALSE + +echo $SIZEDATA $SIZEREQUIRED $SIZEFREE $ISENOUGHSPACE + +} + +#/** +# ogIsImageLocked [str_repo] path_image +#@brief Comprueba si una imagen está bloqueada para uso exclusivo. +#@param str_repo repositorio de imágenes (opcional) +#@param path_image camino de la imagen (sin extensión) +#@return Código de salida: 0 - bloqueado, 1 - sin bloquear o error. +#@note repo = { REPO, CACHE } +#@exception OG_ERR_FORMAT formato incorrecto. +#@version 1.0 - Adaptación a OpenGnSys 1.0 +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2011/03/10 +#@version 1.0.1 - Devolver falso en caso de error. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2011-05-18 +#*/ ## +function ogIsImageLocked () +{ +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME [str_repo] path_image" \ + "if $FUNCNAME /opt/opengnsys/images/aula1/win7.img; then ...; fi" \ + "if $FUNCNAME REPO /aula1/win7.img; then ...; fi" + return +fi +# Error si no se reciben 1 o 2 parámetros. +[ $# -lt 1 -o $# -gt 2 ] && return 1 + +# Comprobar si existe el fichero de bloqueo. +test -n "$(ogGetPath $@.lock)" +} + + +#/** +# ogLockImage [str_repo] path_image +#@brief Bloquea una imagen para uso exclusivo. +#@param str_repo repositorio de imágenes (opcional) +#@param path_image camino de la imagen (sin extensión) +#@return Nada. +#@note Se genera un fichero con extensión .lock +#@note repo = { REPO, CACHE } +#@exception OG_ERR_FORMAT formato incorrecto. +#@version 1.0 - Adaptación a OpenGnSys 1.0 +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2011/03/10 +#*/ ## +function ogLockImage () +{ +# Variables locales +local IMGDIR + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME [str_repo] path_image" \ + "$FUNCNAME /opt/opengnsys/images/aula1/win7.img" \ + "$FUNCNAME REPO /aula1/win7.img" + return +fi +# Error si no se reciben 1 o 2 parámetros. +[ $# == 1 -o $# == 2 ] || ogRaiseError $OG_ERR_FORMAT || return $? +# Comprobar que existe directorio de imagen +IMGDIR=$(ogGetParentPath $@) || return $? +# Crear fichero de bloqueo. +touch $IMGDIR/$(basename "${!#}").lock 2>/dev/null || ogRaiseError $OG_ERR_NOTWRITE "$*" || return $? +} + + +#/** +# ogRestoreDiskImage str_repo path_image int_npartition +#@brief Restaura (recupera) una imagen de un disco completo. +#@param str_repo repositorio de imágenes o caché local +#@param path_image camino de la imagen +#@param int_ndisk nº de orden del disco +#@return (por determinar) +#@warning Primera versión en pruebas +#@todo Gestionar bloqueos de disco +#@todo Comprobar que no se intenta restaurar de la caché sobre el mismo disco +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND fichero de imagen o partición no detectados. +#@exception OG_ERR_LOCKED partición bloqueada por otra operación. +#@exception OG_ERR_IMAGE error al restaurar la imagen del sistema. +#@exception OG_ERR_IMGSIZEPARTITION Tamaño de la particion es menor al tamaño de la imagen. +#@version 1.1.0 - Primera versión para OpenGnsys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@Date 2016/04/08 +#*/ ## +function ogRestoreDiskImage () +{ +# Variables locales +local DISK DISKSIZE IMGFILE IMGTYPE IMGSIZE PROGRAM ERRCODE + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME str_repo path_image int_ndisk" \ + "$FUNCNAME REPO /aula1/win7 1" + return +fi +# Error si no se reciben 4 parámetros. +[ $# == 3 ] || ogRaiseError $OG_ERR_FORMAT || return $? +# Procesar parámetros. +DISK="$(ogDiskToDev $3)" || return $(ogRaiseError $OG_ERR_NOTFOUND " $3 $4"; echo $?) +IMGTYPE="dsk" +IMGFILE=$(ogGetPath "$1" "$2.$IMGTYPE") +[ -r "$IMGFILE" ] || return $(ogRaiseError $OG_ERR_NOTFOUND " $3 $4"; echo $?) + +# comprobamos consistencia de la imagen +ogGetImageInfo $IMGFILE >/dev/null || return $(ogRaiseError $OG_ERR_IMAGE " $1 $2"; echo $?) + +#/* (Comienzo comentario Doxygen) +# Error si la imagen no cabe en la particion. +#IMGSIZE=$(ogGetImageSize "$1" "$2") || return $(ogRaiseError $OG_ERR_IMAGE " $1 $2"; echo $?) +#DISKSIZE=$(ogGetDiskSize $3) +#if [ $IMGSIZE -gt $DISKSIZE ]; then +# ogRaiseError $OG_ERR_IMGSIZEPARTITION "$DISKSIZE < $IMGSIZE" +# return $? +#fi +#*/ (Fin comentario Doxygen) + +# Comprobar el bloqueo de la imagen y de la partición. +if ogIsImageLocked "$IMGFILE"; then + ogRaiseError $OG_ERR_LOCKED "$MSG_IMAGE $1, $2.$IMGTYPE" + return $? +fi +if ogIsDiskLocked $3; then + ogRaiseError $OG_ERR_LOCKED "$MSG_DISK $3" + return $? +fi +# Solicitamos la generación de la instruccion a ejecutar +PROGRAM=$(ogRestoreImageSyntax $IMGFILE $DISK) + +# Bloquear el disco +ogLockDisk $3 || return $? +trap "ogUnlockDisk $3" 1 2 3 6 9 + +# Ejecutar restauración según el tipo de imagen. +eval $PROGRAM + +ERRCODE=$? +if [ $ERRCODE != 0 ]; then + ogRaiseError $OG_ERR_IMAGE "$IMGFILE, $3, $4" +fi +ogUnlockDisk $3 $4 +return $ERRCODE +} + + +#/** +# ogRestoreImage str_repo path_image int_ndisk int_npartition +#@brief Restaura una imagen de sistema de archivos en una partición. +#@param str_repo repositorio de imágenes o caché local +#@param path_image camino de la imagen +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@return (por determinar) +#@exception OG_ERR_FORMAT 1 formato incorrecto. +#@exception OG_ERR_NOTFOUND 2 fichero de imagen o partición no detectados. +#@exception OG_ERR_PARTITION 3 # Error en partición de disco. +#@exception OG_ERR_LOCKED 4 partición bloqueada por otra operación. +#@exception OG_ERR_IMAGE 5 error al restaurar la imagen del sistema. +#@exception OG_ERR_IMGSIZEPARTITION 30 Tamaño de la particion es menor al tamaño de la imagen. +#@todo Comprobar incongruencias partición-imagen, control de errores, definir parámetros, caché/repositorio, etc. +#@version 0.1 - Integracion para Opengnsys - HIDRA:RestaurarImagen{EXT3, NTFS}.sh; EAC: RestorePartitionFromImage() en Deploy.lib +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@Date 2008/05/13 +#@author Antonio J. Doblas Viso. Universidad de Malaga +#@date 2008/10/27 +#@version 0.9 - Primera version muy en pruebas para OpenGnSys +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2009/09/10 +#@version 1.0 - generacion sintaxis de restauracion +#@author Antonio J. Doblas Viso, Universidad de Malaga +#@date 2011/02/01 +#@version 1.0.1 - Control errores, tamaño particion, fichero-imagen +#@author Antonio J. Doblas Viso, Universidad de Malaga +#@date 2011/05/11 +#*/ ## +function ogRestoreImage () +{ +# Variables locales +local PART PARTSIZE IMGFILE IMGTYPE IMGSIZE FSTYPE PROGRAM ERRCODE + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME str_repo path_image int_ndisk int_npart" \ + "$FUNCNAME REPO /aula1/win7 1 1" + return +fi +# Error si no se reciben 4 parámetros. +[ $# == 4 ] || ogRaiseError $OG_ERR_FORMAT || return $? +# Procesar parámetros. +PART="$(ogDiskToDev $3 $4)" || return $(ogRaiseError $OG_ERR_NOTFOUND " $3 $4"; echo $?) +#IMGTYPE=$(ogGetImageType "$1" "$2") +IMGTYPE=img +IMGFILE=$(ogGetPath "$1" "$2.$IMGTYPE") +[ -r "$IMGFILE" ] || return $(ogRaiseError $OG_ERR_NOTFOUND " $3 $4"; echo $?) +# comprobamos consistencia de la imagen +ogGetImageInfo $IMGFILE >/dev/null || return $(ogRaiseError $OG_ERR_IMAGE " $1 $2"; echo $?) + +# Error si la imagen no cabe en la particion. +IMGSIZE=$(ogGetImageSize "$1" "$2") || return $(ogRaiseError $OG_ERR_IMAGE " $1 $2"; echo $?) +#TODO: +#Si la particion no esta formateado o tiene problemas formateamos +ogMount $3 $4 || ogFormat $3 $4 +PARTSIZE=$(ogGetPartitionSize $3 $4) +if [ $IMGSIZE -gt $PARTSIZE ]; then + ogRaiseError $OG_ERR_IMGSIZEPARTITION " $PARTSIZE < $IMGSIZE" + return $? +fi +# Comprobar el bloqueo de la imagen y de la partición. +if ogIsImageLocked "$IMGFILE"; then + ogRaiseError $OG_ERR_LOCKED "$MSG_IMAGE $1, $2.$IMGTYPE" + return $? +fi +if ogIsLocked $3 $4; then + ogRaiseError $OG_ERR_LOCKED "$MSG_PARTITION $3, $4" + return $? +fi + +# Solicitamos la generación de la instruccion a ejecutar +# Atención: no se comprueba el tipo de sistema de archivos. +# Atención: no se comprueba incongruencia entre partición e imagen. +PROGRAM=`ogRestoreImageSyntax $IMGFILE $PART` + +# Desmontar y bloquear partición. +ogUnmount $3 $4 2>/dev/null || return $(ogRaiseError $OG_ERR_PARTITION " $3 $4"; echo $?) +ogLock $3 $4 || return $? +trap "ogUnlock $3 $4" 1 2 3 6 9 + +# Ejecutar restauración según el tipo de imagen. +eval $PROGRAM + +ERRCODE=$? +if [ $ERRCODE != 0 ]; then + ogRaiseError $OG_ERR_IMAGE "$IMGFILE, $3, $4" +fi +ogUnlock $3 $4 +return $ERRCODE +} + + +#/** +# ogRestoreMbrImage str_repo path_image int_ndisk +#@brief Restaura la imagen del sector de arranque de un disco. +#@param str_repo repositorio de imágenes o caché local +#@param path_image camino de la imagen +#@param int_ndisk nº de orden del disco +#@return (por determinar) +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND fichero de imagen o partición no detectados. +#@exception OG_ERR_IMAGE error al restaurar la imagen del sistema. +#@version 0.9 - Primera versión en pruebas. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2010/01/12 +#@version 1.0 - Adaptación a OpenGnSys 1.0 +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2011/03/10 +#*/ ## +function ogRestoreMbrImage () +{ +# Variables locales +local DISK IMGFILE +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME str_repo path_image int_ndisk" \ + "$FUNCNAME REPO /aula1/mbr 1" + return +fi +# Error si no se reciben 3 parámetros. +[ $# == 3 ] || ogRaiseError $OG_ERR_FORMAT || return $? +# Procesar parámetros. +DISK=$(ogDiskToDev "$3") || return $? +IMGFILE=$(ogGetPath "$1" "$2.mbr") +[ -r "$IMGFILE" ] || ogRaiseError $OG_ERR_NOTFOUND "$IMGFILE" || return $? + +# Restaurar imagen del MBR. +dd if="$IMGFILE" of="$DISK" bs=512 count=1 || ogRaiseError $OG_ERR_IMAGE "$1 $IMGFILE" || return $? +} + + +#/** +# ogRestoreBootLoaderImage str_repo path_image int_ndisk +#@brief Restaura la imagen del boot loader del sector de arranque de un disco. +#@param str_repo repositorio de imágenes o caché local +#@param path_image camino de la imagen +#@param int_ndisk nº de orden del disco +#@return (por determinar) +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND fichero de imagen o partición no detectados. +#@exception OG_ERR_IMAGE error al restaurar la imagen del sistema. +#@version 1.0 - Adaptacion de ogRestoreMbrImage para restaurar solo el Boot Loader +#@author Juan Carlos Xifre, SICUZ Universidad de Zaragoza +#@date 2011/03/21 +#*/ ## +function ogRestoreBootLoaderImage () +{ +# Variables locales +local DISK IMGFILE +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME str_repo path_image int_ndisk" \ + "$FUNCNAME REPO /aula1/mbr 1" + return +fi +# Error si no se reciben 3 parámetros. +[ $# == 3 ] || ogRaiseError $OG_ERR_FORMAT || return $? +# Procesar parámetros. +DISK=$(ogDiskToDev "$3") || return $? +IMGFILE=$(ogGetPath "$1" "$2.mbr") +[ -r "$IMGFILE" ] || ogRaiseError $OG_ERR_NOTFOUND "$IMGFILE" || return $? + +# Restaurar imagen del MBR. +dd if="$IMGFILE" of="$DISK" bs=446 count=1 || ogRaiseError $OG_ERR_IMAGE "$1 $IMGFILE" || return $? +} + +#/** +# ogUnlockImage [str_repo] path_image +#@brief Desbloquea una imagen con uso exclusivo. +#@param str_repo repositorio de imágenes (opcional) +#@param path_image camino de la imagen (sin extensión) +#@return Nada. +#@note repo = { REPO, CACHE } +#@note Se elimina el fichero de bloqueo con extensión .lock +#@exception OG_ERR_FORMAT formato incorrecto. +#@version 1.0 - Adaptación a OpenGnSys 1.0 +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2011/03/10 +#*/ ## +function ogUnlockImage () +{ +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME [str_repo] path_image" \ + "$FUNCNAME /opt/opengnsys/images/aula1/win7.img" \ + "$FUNCNAME REPO /aula1/win7.img" + return +fi +# Error si no se reciben 1 o 2 parámetros. +[ $# == 1 -o $# == 2 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +# Borrar fichero de bloqueo para la imagen. +rm -f $(ogGetPath $@.lock) +} + + +#/** +# ogGetImageInfo filename +#@brief muestra información sobre la imagen monolitica. +#@param 1 filename path absoluto del fichero imagen +#@return cadena compuesta por clonacion:compresor:sistemaarchivos:tamañoKB +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND fichero no encontrado. +#@exception OG_ERR_IMAGE "Image format is not valid $IMGFILE" +#@warning En pruebas iniciales +#@TODO Definir sintaxis de salida (herramienta y compresor en minuscula) +#@TODO Arreglar loop para ntfsclone +#@TODO insertar parametros entrada tipo OG +#@version 1.0 - Primeras pruebas +#@author Antonio J. Doblas Viso. Universidad de Málaga +#@date 2010/02/08 +#*/ ## + +function ogGetImageInfo () +{ +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME path_filename" \ + "$FUNCNAME /opt/opengnsys/images/prueba.img ==> PARTCLONE:LZOP:NTFS:5642158" + return +fi + +# Error si no se recibe 1 parámetro. +[ $# == 1 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +#comprobando que el parametro uno es un file. +[ -f $1 ] || ogRaiseError $OG_ERR_NOTFOUND "$1" || return $? + +local TOOLS COMPRESSOR IMGFILE FILEHEAD FS FSPLUS SIZE SIZEFACTOR PARTIMAGEINFO PARTCLONEINFO NTFSCLONEINFO IMGDETECT +IMGDETECT="FALSE" + +IMGFILE=$1 +FILEHEAD=/tmp/`basename $IMGFILE`.infohead +COMPRESSOR=`file $IMGFILE | awk '{print $2}'` +ogCheckStringInGroup "$COMPRESSOR" "gzip lzop" || ogRaiseError $OG_ERR_IMAGE "Image format is not valid $IMGFILE" || return $? +$($COMPRESSOR -dc $IMGFILE 2>/dev/null | head -n 40 > $FILEHEAD) || ogRaiseError $OG_ERR_IMAGE "Image format is not valid $IMGFILE" || return $? + +## buscando Primera opción. +if [ "$IMGDETECT" == "FALSE" ] +then + PARTCLONEINFO=$(LC_ALL=C partclone.info $FILEHEAD 2>&1) + if `echo $PARTCLONEINFO | grep size > /dev/null` + then + TOOLS=PARTCLONE + FS=$(echo $PARTCLONEINFO | awk '{gsub(/\: /,"\n"); print toupper($8);}') + if [[ "$FS" == "HFS" || "$FS" == "HFSPLUS" || "$FS" == "FAT32" ]]; then + FSPLUS=$(echo $PARTCLONEINFO | awk '{gsub(/\: /,"\n"); print toupper($9);}') + echo $PARTCLONEINFO | grep GB > /dev/null && SIZEFACTOR=1000000 || SIZEFACTOR=1024 + if [ "$FSPLUS" == "PLUS" ]; then + FS=$FS$FSPLUS + SIZE=$(echo $PARTCLONEINFO | awk -v FACTOR=$SIZEFACTOR '{printf "%d\n", $17*FACTOR;}') + else + SIZE=$(echo $PARTCLONEINFO | awk -v FACTOR=$SIZEFACTOR '{printf "%d\n", $16*FACTOR;}') + fi + else + echo $PARTCLONEINFO | grep GB > /dev/null && SIZEFACTOR=1000000 || SIZEFACTOR=1024 + SIZE=$(echo $PARTCLONEINFO | awk -v FACTOR=$SIZEFACTOR '{gsub(/\: /,"\n"); printf "%d\n", $11*FACTOR;}') + fi + IMGDETECT="TRUE" + fi +fi +#buscando segunda opcion. +if [ "$IMGDETECT" == "FALSE" -a ! -f /dev/loop2 ] +then + cat $FILEHEAD | grep -w ntfsclone-image > /dev/null && NTFSCLONEINFO=$(cat $FILEHEAD | ntfsclone --restore --overwrite /dev/loop2 - 2>&1) + if `echo $NTFSCLONEINFO | grep ntfsclone > /dev/null` + then + TOOLS=NTFSCLONE + SIZE=$(echo $NTFSCLONEINFO | awk '{gsub(/\(|\)|\./,""); printf "%d\n",$17/1000;}') + FS=NTFS + IMGDETECT="TRUE" + fi +fi +## buscando Tercer opción. +if [ "$IMGDETECT" == "FALSE" ] +then + PARTIMAGEINFO=$(partimage -B gui=no imginfo "$FILEHEAD" 2>&1) + if `echo $PARTIMAGEINFO | grep Partition > /dev/null` + then + TOOLS=PARTIMAGE + FS=$(echo $PARTIMAGEINFO | awk '{gsub(/ /,"\n"); print $17;}' | awk '{sub(/\.\.+/," "); print toupper($2)}') + SIZE=$( echo $PARTIMAGEINFO | awk '{gsub(/ /,"\n"); print $36;}' | awk '{sub(/\.\.+/," "); printf "%d\n",$2*1024*1024;}') + IMGDETECT="TRUE" + fi + if file $FILEHEAD 2> /dev/null | grep -q "boot sector"; then + TOOLS="partclone.dd" + FS= + SIZE= + IMGDETECT="TRUE" + fi +fi +#comprobamos valores #Chequeamos los valores devueltos. +if [ -z "$TOOLS" -o -z "$COMPRESSOR" -o "$IMGDETECT" == "FALSE" ] +then + ogRaiseError $OG_ERR_IMAGE "Image format is not valid $IMGFILE" || return $? +else + COMPRESSOR=$(echo $COMPRESSOR | tr [a-z] [A-Z]) + echo $TOOLS:$COMPRESSOR:$FS:$SIZE +fi +} + +#/** +# ogGetImageProgram str_REPO str_imagen +#@brief muestra información sobre la imagen monolitica. +#@see ogGetImageInfo +#@param 1 REPO o CACHE contenedor de la imagen +#@param 2 filename nombre de la imagen sin extension +#@return nombre del programa usado para generar la imagen +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND fichero no encontrado. +#@note ogGetImageProgram REPO imagenA -> partclone +#@version 1.0 - Primeras pruebas +#@author Antonio J. Doblas Viso. Universidad de Málaga +#@date 2010/02/08 +#*/ ## + +function ogGetImageProgram () +{ +local IMGFILE +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME str_repo path_image" \ + "$FUNCNAME REPO prueba ==> PARTCLONE" + return +fi +# Error si no se reciben 2 parámetros. +[ $# == 2 ] || ogRaiseError $OG_ERR_FORMAT || return $? +IMGFILE=$(ogGetPath "$1" "$2.img") +[ -r "$IMGFILE" ] || ogRaiseError $OG_ERR_NOTFOUND "$IMGFILE" || return $? +ogGetImageInfo $IMGFILE | awk -F: '{print $1}' +} + +#/** +# ogGetImageCompressor str_REPO str_imagen +#@brief muestra información sobre la imagen monolitica. +#@see ogGetImageInfo +#@param 1 REPO o CACHE contenedor de la imagen +#@param 2 filename nombre de la imagen sin extension +#@return tipo de compresión usada al generar la imagen +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND fichero no encontrado. +#@note ogGetImageCompressor REPO imagenA -> lzop +#@version 1.0 - Primeras pruebas +#@author Antonio J. Doblas Viso. Universidad de Málaga +#@date 2010/02/08 +#*/ ## +function ogGetImageCompressor () +{ +local IMGFILE +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME str_repo path_image" \ + "$FUNCNAME REPO prueba ==> LZOP" + return +fi +# Error si no se reciben 2 parámetros. +[ $# == 2 ] || ogRaiseError $OG_ERR_FORMAT || return $? +IMGFILE=$(ogGetPath "$1" "$2.img") +[ -r "$IMGFILE" ] || ogRaiseError $OG_ERR_NOTFOUND "$IMGFILE" || return $? +ogGetImageInfo $IMGFILE | awk -F: '{print $2}' +} + + +#/** +# ogGetImageType str_REPO str_imagen +#@brief muestra información sobre el sistema de archivos de imagen monolitica. +#@see ogGetImageInfo +#@param 1 REPO o CACHE contenedor de la imagen +#@param 2 filename nombre de la imagen sin extension +#@return tipo de compresión usada al generar la imagen +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND fichero no encontrado. +#@note ogGetImageType REPO imagenA -> NTFS +#@version 1.0 - Primeras pruebas +#@author Antonio J. Doblas Viso. Universidad de Málaga +#@date 2010/02/08 +#*/ ## +function ogGetImageType () +{ +local IMGFILE +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME str_repo path_image" \ + "$FUNCNAME REPO prueba ==> NTFS" + return +fi +# Error si no se reciben 2 parámetros. +[ $# == 2 ] || ogRaiseError $OG_ERR_FORMAT || return $? +IMGFILE=$(ogGetPath "$1" "$2.img") +[ -r "$IMGFILE" ] || ogRaiseError $OG_ERR_NOTFOUND "$IMGFILE" || return $? +ogGetImageInfo $IMGFILE | awk -F: '{print $3}' +} + + +#/** +# ogGetImageSize str_REPO str_imagen +#@brief muestra información sobre el tamaño (KB) del sistema de archivos de imagen monolitica. +#@see ogGetImageInfo +#@param 1 REPO o CACHE contenedor de la imagen +#@param 2 filename nombre de la imagen sin extension +#@return tipo de compresión usada al generar la imagen +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND fichero no encontrado. +#@note ogGetImagesize REPO imagenA -> 56432234 > Kb +#@version 1.0 - Primeras pruebas +#@author Antonio J. Doblas Viso. Universidad de Málaga +#@date 2010/02/08 +#*/ ## +function ogGetImageSize () +{ +# Variables locales +local IMGFILE + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME str repo path_image" \ + "$FUNCNAME REPO prueba ==> 5642158" + return +fi +# Error si no se reciben 2 parámetros. +[ $# == 2 ] || ogRaiseError $OG_ERR_FORMAT || return $? +# Error si el fichero de imagen no es accesible. +IMGFILE=$(ogGetPath "$1" "$2.img") +[ -r "$IMGFILE" ] || ogRaiseError $OG_ERR_NOTFOUND "$IMGFILE" || return $? + +# Devuelve el tamaño de la imagen en KB. +ogGetImageInfo $IMGFILE | awk -F: '{print $4}' +} + + +#/** +# ogCreateGptImage int_ndisk str_repo path_image +#@brief Crea una imagen de la tabla de particiones GPT de un disco. +#@param int_ndisk nº de orden del disco +#@param str_repo repositorio de imágenes (remoto o caché local) +#@param path_image camino de la imagen (sin extensión) +#@return (nada, por determinar) +#@note repo = { REPO, CACHE } +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. +#@exception OG_ERR_IMAGE error al crear la imagen del sistema. +#@version 1.1 - Adaptación a OpenGnSys 1.1 +#@author Juan Carlos Garcia. Universidad de Zaragoza +#@date 2017/03/29 +#*/ ## +function ogCreateGptImage () +{ +# Variables locales +local DISK IMGDIR IMGFILE +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk path_dir str_image" \ + "$FUNCNAME 1 REPO /aula1/gpt" + return +fi +# Error si no se reciben 3 parámetros. +[ $# == 3 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +DISK=$(ogDiskToDev "$1") || return $? +IMGDIR=$(ogGetParentPath "$2" "$3") +[ -n "$IMGDIR" ] || ogRaiseError $OG_ERR_NOTFOUND "$2 $(dirname $3)" || return $? +IMGFILE="$IMGDIR/$(basename "$3").gpt" + +# Crear imagen de la tabla GPT. +sgdisk -b="$IMGFILE" "$DISK" || ogRaiseError $OG_ERR_IMAGE "$1 $IMGFILE" || return $? +} + +#/** +# ogRestoreGptImage str_repo path_image int_ndisk +#@brief Restaura la imagen de la tabla de particiones GPT de un disco. +#@param str_repo repositorio de imágenes o caché local +#@param path_image camino de la imagen +#@param int_ndisk nº de orden del disco +#@return (por determinar) +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND fichero de imagen o partición no detectados. +#@exception OG_ERR_IMAGE error al restaurar la imagen del sistema. +#@version 1.1 - Adaptación a OpenGnSys 1.1 +#@author Juan Carlos Garcia, Universidad de Zaragoza +#@date 2017/03/29 +#*/ ## +function ogRestoreGptImage () +{ +# Variables locales +local DISK IMGFILE +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME path_dir str_image int_ndisk" \ + "$FUNCNAME REPO /aula1/gpt 1" + return +fi +# Error si no se reciben 3 parámetros. +[ $# == 3 ] || ogRaiseError $OG_ERR_FORMAT || return $? +# Procesar parámetros. +DISK=$(ogDiskToDev "$3") || return $? +IMGFILE=$(ogGetPath "$1" "$2.gpt") +[ -r "$IMGFILE" ] || ogRaiseError $OG_ERR_NOTFOUND "$IMGFILE" || return $? + +# Restaurar tabla GPT del disco. +sgdisk -l="$IMGFILE" "$DISK" || ogRaiseError $OG_ERR_IMAGE "$1 $IMGFILE" || return $? +} + diff --git a/client/lib/engine/bin/ImageLib.py b/client/lib/engine/bin/ImageLib.py deleted file mode 100644 index 0d3b5d1..0000000 --- a/client/lib/engine/bin/ImageLib.py +++ /dev/null @@ -1,836 +0,0 @@ -#!/usr/bin/python3 - -import shutil -import subprocess -import os -import os.path -import re -from pathlib import Path - -import DiskLib -import FileSystemLib -import SystemLib -import ogGlobals -import FileLib -import CacheLib -import NetLib - -## ProtocolLib.ogUcastSyntax() calls ogCreateImageSyntax() -## in ogCreateImageSyntax(), param2 may contain a pipe or may be empty -## if param2 is empty, then ogUcastSyntax(): -## - does a .split() -## - accesses the third element of the resulting array (ie. does "parts[2]") -## - promptly gets an IndexError exception -## -## param2 in ogCreateImageSyntax() only contains a pipe if 'mbuffer' is installed -## therefore, a hard dependency on mbuffer is created -## -## raise an Exception at import time if mbuffer is not present -if not shutil.which ('mbuffer'): - raise FileNotFoundError ('"mbuffer" utility must be present') - -#/** -#@file ImageLib.py -#@brief Librería o clase Image -#@class Image -#@brief Funciones para creación, restauración y clonación de imágenes de sistemas. -#@warning License: GNU GPLv3+ -#*/ - - -#/** -# ogCreateImageSyntax path_device path_filename [str_tool] [str_compressionlevel] -#@brief Genera una cadena de texto con la instrucción para crear un fichero imagen -#@param path_device dispositivo Linux del sistema de archivos -#@param path_fileneme path absoluto del fichero imagen -#@param [opcional] str_tool herrmaienta de clonacion [partimage, partclone, ntfsclone] -#@param [opcional] str_compressionlevel nivel de compresion. [0 -none-, 1-lzop-, 2-gzip] -#@return str_command - cadena con el comando que se debe ejecutar. -#@warning Salida nula si se producen errores. -#@TODO introducir las herramientas fsarchiver, dd -#*/ ## -#ogCreateImageSyntax /dev/sda1 /opt/opengnsys/images/prueba.img partclone lzop -#ogCreateImageSyntax /dev/sda1 /opt/opengnsys/images/prueba.img -def ogCreateImageSyntax (dev, imgfile, tool='partclone', level='gzip'): - - if 'ntfsclone' == tool: - param1 = f'ntfsclone --force --save-image -O - {dev}' - elif 'partimage' == tool or 'default' == tool: - param1 = f'partimage -M -f3 -o -d -B gui=no -c -z0 --volume=0 save {dev} stdout' - elif 'partclone' == tool: - disk, part = DiskLib.ogDevToDisk (dev).split() - fs = FileSystemLib.ogGetFsType (disk, part) - param1 = { - 'EXT2': 'partclone.extfs', - 'EXT3': 'partclone.extfs', - 'EXT4': 'partclone.extfs', - 'BTRFS': 'partclone.btrfs', - 'REISERFS': 'partclone.reiserfs', - 'REISER4': 'partclone.reiser4', - 'JFS': 'partclone.jfs', - 'XFS': 'partclone.xfs', - 'F2FS': 'partclone.f2fs', - 'NILFS2': 'partclone.nilfs2', - 'NTFS': 'partclone.ntfs', - 'EXFAT': 'partclone.exfat', - 'FAT16': 'partclone.fat', - 'FAT32': 'partclone.fat', - 'HFS': 'partclone.hfsp', - 'HFSPLUS': 'partclone.hfsp', - 'UFS': 'partclone.ufs', - 'VMFS': 'partclone.vmfs', - }.get (fs, 'partclone.imager') - dash_c = '-c' - if not shutil.which (param1): - param1 = 'partclone.dd' - # Algunas versiones de partclone.dd no tienen opción "-c". - out = subprocess.run (['partclone.dd', '--help'], capture_output=True, text=True).stdout - if ' -c' not in out: dash_c = '' - param1=f'{param1} -d0 -F {dash_c} -s {dev}' - else: - raise Exception (f'unknown tool "{tool}"') - - param2 = '| mbuffer -q -m 40M ' if shutil.which ('mbuffer') else ' ' - - param3 = { - 0: ' > ', - 'none': ' > ', - 1: ' | lzop > ', - 'lzop': ' | lzop > ', - 2: ' | gzip -c > ', - 'gzip': ' | gzip -c > ', - 3: ' | bzip -c > ', - 'bzip': ' | bzip -c > ', - }.get (level, ' > ') - - #print (f'param1 ({param1}) param2 ({param2}) param3 ({param3}) imgfile ({imgfile})') - if param1: return f'{param1} {param2} {param3} {imgfile}' - - -#/** -# ogRestoreImageSyntax path_filename path_device [str_tools] [str_compressionlevel] -#@brief Genera una cadena de texto con la instrucción para crear un fichero imagen -#@param path_device dispositivo Linux del sistema de archivos -#@param path_fileneme path absoluto del fichero imagen -#@param [opcional] str_tools herrmaienta de clonacion [partimage, partclone, ntfsclone] -#@param [opcional] str_compressionlevel nivel de compresion. [0 -none-, 1-lzop-, 2-gzip] -#@return cadena con el comando que se debe ejecutar. -#@exception OG_ERR_FORMAT formato incorrecto. -#@warning En pruebas iniciales -#@TODO introducir las herramientas fsarchiver, dd -#@TODO introducir el nivel de compresion gzip -#*/ ## -#ogRestoreImageSyntax /opt/opengnsys/images/prueba.img /dev/sda1 [partclone] [lzop] -def ogRestoreImageSyntax (imgfile, part, tool=None, level=None): - if not os.path.exists (imgfile): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, imgfile) - ## original bash code is broken: 'return' is never called - #return - - if tool is None or level is None: - infoimg = ogGetImageInfo (imgfile) - if not infoimg: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'no image {imgfile}') - ## original bash code is broken: 'return' is never called - #return - try: - tool, level = infoimg.split (':')[0:2] - except: - tool, level = '', '' - return ogRestoreImageSyntax (imgfile, part, tool, level) - - tool = tool.lower() - level = level.lower() - compressor = { - 0: ' ', - 'none': ' ', - 1: ' lzop -dc ', - 'lzop': ' lzop -dc ', - 2: ' gzip -dc ', - 'gzip': ' gzip -dc ', - 3: ' bzip -dc ', - 'bzip': ' bzip -dc ', - }.get (level, '') - #print (f'tool ({tool}) level ({level}) compressor ({compressor})') - if compressor == '': - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'Compressor no valid {level}') - ## original bash code is broken: 'return' is never called - #return - - mbuffer = '| mbuffer -q -m 40M ' if shutil.which ('mbuffer') else ' ' - #print (f'mbuffer ({mbuffer})') - if 'ntfsclone' == tool: - tool = f'| ntfsclone --restore-image --overwrite {part} -' - elif 'partimage' == tool: - tool = f'| partimage -f3 -B gui=no restore {part} stdin' - elif 'partclone' in tool: - # -C para que no compruebe tamaños - tool = f'| partclone.restore -d0 -C -I -o {part}' - elif 'dd' == tool: - tool = f'| pv | dd conv=sync,noerror bs=1M of={part}' - else: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'Tools imaging no valid {tool}') - ## original bash code is broken: 'return' is never called - #return - #print (f'tool ({tool})') - - return f'{compressor} {imgfile} {mbuffer} {tool}'.strip() - - - - -#/** -# ogCreateDiskImage int_ndisk str_repo path_image [str_tools] [str_compressionlevel] -#@brief Crea una imagen (copia de seguridad) de un disco completo. -#@param int_ndisk nº de orden del disco -#@param str_repo repositorio de imágenes (remoto o caché local) -#@param path_image camino de la imagen (sin extensión) -#@return (nada, por determinar) -#@note repo = { REPO, CACHE } -#@note Esta primera versión crea imágenes con dd comprimidas con gzip. -#@exception OG_ERR_FORMAT formato incorrecto. -#@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. -#@exception OG_ERR_LOCKED particion bloqueada por otra operación. -#@exception OG_ERR_IMAGE error al crear la imagen del sistema. -#@warning En pruebas iniciales -#@todo Gestión de bloqueos de disco -#@todo Comprobar si debe desmontarse la caché local -#@todo Comprobar que no se crea la imagen en el propio disco -#*/ ## - - -#/** -# ogCreateImage int_ndisk int_npartition str_repo path_image [str_tools] [str_compressionlevel] -#@brief Crea una imagen a partir de una partición. -#@param int_ndisk nº de orden del disco -#@param int_npartition nº de orden de la partición -#@param str_repo repositorio de imágenes (remoto o caché local) -#@param path_image camino de la imagen (sin extensión) -#@param [opcional] str_tools herrmaienta de clonacion [partimage, partclone, ntfsclone] -#@param [opcional] str_compressionlevel nivel de compresion. [0 -none-, 1-lzop-, 2-gzip] -#@return (nada, por determinar) -#@note repo = { REPO, CACHE } -#@exception OG_ERR_FORMAT formato incorrecto. -#@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. -#@exception OG_ERR_PARTITION partición no accesible o no soportada. -#@exception OG_ERR_LOCKED particion bloqueada por otra operación. -#@exception OG_ERR_IMAGE error al crear la imagen del sistema. -#@todo Comprobaciones, control de errores, definir parámetros, etc. -#*/ ## -def ogCreateImage (disk, par, container, imgfile, tool='partclone', level='gzip'): - PART = DiskLib.ogDiskToDev (disk, par) - if not PART: return None - - if FileSystemLib.ogIsLocked (disk, par): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_LOCKED, f'{ogGlobals.lang.MSG_ERR_LOCKED} {disk}, {par}') - return None - - imgtype = 'img' # Extensión genérica de imágenes. - imgdir = FileLib.ogGetParentPath (src=container, file=imgfile) - if not imgdir: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'{container} {imgfile}') - return None - - bn = os.path.basename (imgfile) - IMGFILE = f'{imgdir}/{bn}.{imgtype}' - if ogIsImageLocked (IMGFILE): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_LOCKED, f'{ogGlobals.lang.MSG_IMAGE} {container}, {imgfile}') - return None - -# Generar la instruccion a ejecutar antes de aplicar los bloqueos. - program = ogCreateImageSyntax (PART, IMGFILE, tool=tool, level=level) -# Desmontar partición, bloquear partición e imagen. - FileSystemLib.ogUnmount (disk, par) - if not FileSystemLib.ogLock (disk, par): - return None - if not ogLockImage (container, f'{imgfile}.{imgtype}'): - return None - -# Crear Imagen. - #trap - p = subprocess.run (program, shell=True, check=True) - errcode = p.returncode - if 0 == errcode: - i = ogGetImageInfo (IMGFILE) - h = NetLib.ogGetHostname() - with open (f'{IMGFILE}.info', 'w') as fd: - fd.write (f'{i}:{h}\n') - else: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_IMAGE, f'{disk} {par} {IMGFILE}') - if os.path.exists (IMGFILE): - os.unlink (IMGFILE) - - FileSystemLib.ogUnlock (disk, par) - ogUnlockImage (container, f'{imgfile}.{imgtype}') - return not errcode ## reverse to indicate success - - -#/** -# ogCreateMbrImage int_ndisk str_repo path_image -#@brief Crea una imagen a partir del sector de arranque de un disco. -#@param int_ndisk nº de orden del disco -#@param str_repo repositorio de imágenes (remoto o caché local) -#@param path_image camino de la imagen (sin extensión) -#@return (nada, por determinar) -#@note repo = { REPO, CACHE } -#@exception OG_ERR_FORMAT formato incorrecto. -#@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. -#@exception OG_ERR_IMAGE error al crear la imagen del sistema. -#*/ ## - - -#/** -# ogCreateBootLoaderImage int_ndisk str_repo path_image -#@brief Crea una imagen del boot loader a partir del sector de arranque de un disco. -#@param int_ndisk nº de orden del disco -#@param str_repo repositorio de imágenes (remoto o caché local) -#@param path_image camino de la imagen (sin extensión) -#@return (nada, por determinar) -#@note repo = { REPO, CACHE } -#@exception OG_ERR_FORMAT formato incorrecto. -#@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. -#@exception OG_ERR_IMAGE error al crear la imagen del sistema. -#*/ ## - -#/** -# ogGetSizeParameters int_num_disk int_num_part str_repo [monolit|sync|diff] -#@brief Devuelve el tamaño de los datos de un sistema de ficheros, el espacio necesario para la imagen y si cabe en el repositorio elegido. -#@param int_disk numero de disco -#@param int_part numero de particion -#@param str_repo repositorio de imágenes { REPO, CACHE } -#@param str_imageName Nombre de la imagen -#@param str_imageType Tipo de imagen: monolit (por defecto), sync o diff. (parametro opcional) -#@return SIZEDATA SIZEREQUIRED SIZEFREE ISENOUGHSPACE -#@note si str_imageType= diff necesario /tmp/ogimg.info, que es creado por ogCreateInfoImage. -#@note para el tamaño de la imagen no sigue enlaces simbólicos. -#@exception OG_ERR_FORMAT formato incorrecto. -#*/ ## -#SIZEDATA, SIZEREQUIRED, SIZEFREE, ISENOUGHSPACE = ogGetSizeParameters (1, 1, 'REPO', 'myimg') -def ogGetSizeParameters (disk, par, repo, imgname, imgtype=None): - repo = repo.upper() - ## imgtype se soporta como parametro pero se ignora - - mntdir = FileSystemLib.ogMount (disk, par) - if not mntdir: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f'{disk} {par}') - return None - - #if [ "$IMGTYPE" == "_DIFF_" ]; then cosas - #else: - sizedata = None - df_out = subprocess.run (['df', '-k'], capture_output=True, text=True).stdout - for l in df_out.splitlines(): - if (re.search (f'{mntdir}$', l)): - sizedata = int (l.split()[2]) - break - if sizedata is None: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_GENERIC, 'sizedata is None') - return None - - #if [ "$IMGTYPE" == "_SYNC_" -o "$IMGTYPE" == "_DIFF_" ]; then cosas - #else: - factorgzip=55/100 - factorlzop=65/100 - sizerequired = sizedata * factorlzop - - #Comprobar espacio libre en el contenedor. - sizefree = None - if 'CACHE' == repo: - CACHEPART = CacheLib.ogFindCache() - if not CACHEPART: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTCACHE, '') - return None - cache_disk, cache_par = CACHEPART.split() - sizefree = FileSystemLib.ogGetFreeSize (cache_disk, cache_par) - if 'REPO' == repo: - df_out = subprocess.run (['df', '-k'], capture_output=True, text=True).stdout - for l in df_out.splitlines(): - if (re.search (f'{ogGlobals.OGIMG}', l)): - sizefree = int (l.split()[3]) - break - if sizefree is None: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_GENERIC, 'sizefree is None') - return None - -# Comprobamos si existe una imagen con el mismo nombre en $REPO -# En sincronizadas restamos tamaño de la imagen y en monoloticas de la .ant - #case "${IMGTYPE}" in blah blah - #*) - imgext = 'img.ant' - - imgdir = FileLib.ogGetParentPath (src=repo, file=f'/{imgname}') - bn = os.path.basename (f'/{imgname}') - imgfile = FileLib.ogGetPath (file=f'{imgdir}/{bn}.{imgext}') - - if not imgfile: - imgsize = 0 - else: - ls_out = subprocess.run (['ls', '-s', imgfile], capture_output=True, text=True).stdout - imgsize = int (ls_out.split()[0]) - - sizefree = sizefree + imgsize - - if sizerequired < sizefree: - isenoughspace = True - else: - isenoughspace = False - - return sizedata, sizerequired, sizefree, isenoughspace - -#/** -# ogIsImageLocked [str_repo] path_image -#@brief Comprueba si una imagen está bloqueada para uso exclusivo. -#@param str_repo repositorio de imágenes (opcional) -#@param path_image camino de la imagen (sin extensión) -#@return Código de salida: 0 - bloqueado, 1 - sin bloquear o error. -#@note repo = { REPO, CACHE } -#@exception OG_ERR_FORMAT formato incorrecto. -#*/ ## -#ogIsImageLocked ('/opt/opengnsys/images/aula1/win7.img') -#ogIsImageLocked ('REPO', '/aula1/win7.img') -def ogIsImageLocked (container=None, imgfile=None): - if container and imgfile: - p = FileLib.ogGetPath (src=container, file=f'{imgfile}.lock') - elif imgfile: - p = FileLib.ogGetPath (file=f'{imgfile}.lock') - else: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'{container} {imgfile}') - return - return os.path.exists (p) - - -#/** -# ogLockImage [str_repo] path_image -#@brief Bloquea una imagen para uso exclusivo. -#@param str_repo repositorio de imágenes (opcional) -#@param path_image camino de la imagen (sin extensión) -#@return Nada. -#@note Se genera un fichero con extensión .lock -#@note repo = { REPO, CACHE } -#@exception OG_ERR_FORMAT formato incorrecto. -#*/ ## -def ogLockImage (container=None, imgfile=None): - if not imgfile: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, '') - return None - - if container: - imgdir = FileLib.ogGetParentPath (src=container, file=imgfile) - else: - imgdir = FileLib.ogGetParentPath (file=imgfile) - - try: - bn = os.path.basename (imgfile) - open (f'{imgdir}/{bn}.lock', 'w').close() - return True - except: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTWRITE, f'{container} {imgfile}') - return None - - -#/** -# ogRestoreDiskImage str_repo path_image int_npartition -#@brief Restaura (recupera) una imagen de un disco completo. -#@param str_repo repositorio de imágenes o caché local -#@param path_image camino de la imagen -#@param int_ndisk nº de orden del disco -#@return (por determinar) -#@warning Primera versión en pruebas -#@todo Gestionar bloqueos de disco -#@todo Comprobar que no se intenta restaurar de la caché sobre el mismo disco -#@exception OG_ERR_FORMAT formato incorrecto. -#@exception OG_ERR_NOTFOUND fichero de imagen o partición no detectados. -#@exception OG_ERR_LOCKED partición bloqueada por otra operación. -#@exception OG_ERR_IMAGE error al restaurar la imagen del sistema. -#@exception OG_ERR_IMGSIZEPARTITION Tamaño de la particion es menor al tamaño de la imagen. -#*/ ## - - -#/** -# ogRestoreImage str_repo path_image int_ndisk int_npartition -#@brief Restaura una imagen de sistema de archivos en una partición. -#@param str_repo repositorio de imágenes o caché local -#@param path_image camino de la imagen -#@param int_ndisk nº de orden del disco -#@param int_npartition nº de orden de la partición -#@return (por determinar) -#@exception OG_ERR_FORMAT 1 formato incorrecto. -#@exception OG_ERR_NOTFOUND 2 fichero de imagen o partición no detectados. -#@exception OG_ERR_PARTITION 3 # Error en partición de disco. -#@exception OG_ERR_LOCKED 4 partición bloqueada por otra operación. -#@exception OG_ERR_IMAGE 5 error al restaurar la imagen del sistema. -#@exception OG_ERR_IMGSIZEPARTITION 30 Tamaño de la particion es menor al tamaño de la imagen. -#@todo Comprobar incongruencias partición-imagen, control de errores, definir parámetros, caché/repositorio, etc. -#*/ ## -#ogRestoreImage ('REPO', '/aula1/win7', '1', '1') -def ogRestoreImage (repo, imgpath, disk, par): - PART = DiskLib.ogDiskToDev (disk, par) - if not PART: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f' {disk} {par}') - return None - - imgtype = 'img' - imgfile = FileLib.ogGetPath (repo, f'{imgpath}.{imgtype}') - if not os.path.exists (imgfile): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f' {disk} {par}') - return None - - if not ogGetImageInfo (imgfile): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_IMAGE, f' {repo} {imgpath}') - return None - - # Error si la imagen no cabe en la particion. - imgsize = ogGetImageSize (repo, imgpath) - if not imgsize: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_IMAGE, f' {repo} {imgpath}') - return None - if not FileSystemLib.ogMount (disk, par): - FileSystemLib.ogFormat (disk, par) - partsize = DiskLib.ogGetPartitionSize (disk, par) - if float (imgsize) > float (partsize): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_IMGSIZEPARTITION, f' {partsize} < {imgsize}') - return None - - if ogIsImageLocked (container=None, imgfile=imgfile): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_LOCKED, f'{ogGlobals.lang.MSG_IMAGE} {repo}, {imgpath}.{imgtype}') - return None - - if FileSystemLib.ogIsLocked (disk, par): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_LOCKED, f'{ogGlobals.lang.MSG_PARTITION} {disk}, {par}') - return None - - program = ogRestoreImageSyntax (imgfile, PART) - - if not FileSystemLib.ogUnmount (disk, par): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f' {disk} {par}') - return None - - if not FileSystemLib.ogLock (disk, par): - print (f'not FileSystemLib.ogLock()') - return None - - rc = None - try: - p = subprocess.run (program, shell=True, capture_output=True, text=True) - rc = p.returncode - if not rc: - SystemLib.ogRaiseError ([], ogGlobalsOG_ERR_IMAGE, f'{imgfile}, {disk}, {par}') - except: - pass - finally: - FileSystemLib.ogUnlock (disk, par) - - return rc - - - -#/** -# ogRestoreMbrImage str_repo path_image int_ndisk -#@brief Restaura la imagen del sector de arranque de un disco. -#@param str_repo repositorio de imágenes o caché local -#@param path_image camino de la imagen -#@param int_ndisk nº de orden del disco -#@return (por determinar) -#@exception OG_ERR_FORMAT formato incorrecto. -#@exception OG_ERR_NOTFOUND fichero de imagen o partición no detectados. -#@exception OG_ERR_IMAGE error al restaurar la imagen del sistema. -#*/ ## - - -#/** -# ogRestoreBootLoaderImage str_repo path_image int_ndisk -#@brief Restaura la imagen del boot loader del sector de arranque de un disco. -#@param str_repo repositorio de imágenes o caché local -#@param path_image camino de la imagen -#@param int_ndisk nº de orden del disco -#@return (por determinar) -#@exception OG_ERR_FORMAT formato incorrecto. -#@exception OG_ERR_NOTFOUND fichero de imagen o partición no detectados. -#@exception OG_ERR_IMAGE error al restaurar la imagen del sistema. -#*/ ## - -#/** -# ogUnlockImage [str_repo] path_image -#@brief Desbloquea una imagen con uso exclusivo. -#@param str_repo repositorio de imágenes (opcional) -#@param path_image camino de la imagen (sin extensión) -#@return Nada. -#@note repo = { REPO, CACHE } -#@note Se elimina el fichero de bloqueo con extensión .lock -#@exception OG_ERR_FORMAT formato incorrecto. -#*/ ## -#ogUnlockImage REPO /cucu.img -def ogUnlockImage (container=None, imgfile=None): - f = f'{imgfile}.lock' - if container: - p = FileLib.ogGetPath (src=container, file=f) - else: - p = FileLib.ogGetPath (file=f) - - if os.path.exists (p): - os.unlink (p) - - -#/** -# ogGetImageInfo filename -#@brief muestra información sobre la imagen monolitica. -#@param 1 filename path absoluto del fichero imagen -#@return cadena compuesta por clonacion:compresor:sistemaarchivos:tamañoKB -#@exception OG_ERR_FORMAT formato incorrecto. -#@exception OG_ERR_NOTFOUND fichero no encontrado. -#@exception OG_ERR_IMAGE "Image format is not valid $IMGFILE" -#@warning En pruebas iniciales -#@TODO Definir sintaxis de salida (herramienta y compresor en minuscula) -#@TODO Arreglar loop para ntfsclone -#@TODO insertar parametros entrada tipo OG -#*/ ## -#ogGetImageInfo /opt/opengnsys/images/prueba.img ==> PARTCLONE:LZOP:NTFS:5642158" -def ogGetImageInfo (imgfile): - if not os.path.exists (imgfile): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, imgfile) - return - - imgdetect = False - filehead = f'/tmp/{os.path.basename (imgfile)}.infohead' - compressor = subprocess.run (['file', imgfile], capture_output=True, text=True).stdout.split()[1] - if compressor not in ['gzip', 'lzop']: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_IMAGE, f'Image format is not valid {imgfile}') - return - - ## original bash idiom is: $($COMPRESSOR -dc $IMGFILE 2>/dev/null | head -n 40 > $FILEHEAD) || ogRaiseError - ## the purpose of which I can't fully comprehend - #print (f'shelling out "{compressor} -dc {imgfile} |head -n 40 > {filehead}"') - if subprocess.run (f'{compressor} -dc {imgfile} |head -n 40 > {filehead}', shell=True).returncode: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_IMAGE, f'Image format is not valid {imgfile}') - return - - tools = fs = size = None - - if False == imgdetect: - lc_all = os.getenv ('LC_ALL') - os.environ['LC_ALL'] = 'C' - partclone_info = subprocess.run (['partclone.info', filehead], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True).stdout - #partclone_info = subprocess.run (['cat', '/tmp/foo-partclone'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True).stdout - ## sacado de un email de alberto garcía uma.es - #Partclone v0.3.13 http://partclone.org - #Unknown mode - #File system: NTFS - #Device size: 29.2 GB = 7138019 Blocks - #Space in use: 26.6 GB = 6485355 Blocks - #Free Space: 2.7 GB = 652664 Blocks - #Block size: 4096 Byte - # - #image format: 0002 - #created on a: 64 bits platform - #with partclone: v0.3.13 - #bitmap mode: BIT - #checksum algo: CRC32 - #checksum size: 4 - #blocks/checksum: 256 - if lc_all is not None: - os.environ["LC_ALL"] = lc_all - else: - del os.environ["LC_ALL"] - - if 'size' in partclone_info: - tools = 'PARTCLONE' - m = re.search (r'File system *: *(\S+)', partclone_info) - fs = m.group(1) if m else '' - - sizefactor = 1000000 if 'GB' in partclone_info else 1024 - m = re.search (r'Device size *: *(\S+)', partclone_info) - size = float (m.group(1)) if m else 0 - size = int (size * sizefactor) - - ## why is this? - #if fs in ['HFS', 'HFSPLUS', 'FAT32']: - # #FSPLUS=$(echo $PARTCLONEINFO | awk '{gsub(/\: /,"\n"); print toupper($9);}') - # fsplus = 'PLUS' - # if fsplus: # fs += fsplus ## 'HFS' -> 'HFSPLUS' - - imgdetect = True - - if False == imgdetect and not os.path.exists ('/dev/loop2'): - filehead_contents = Path (filehead).read_bytes() - if b'ntfsclone-image' in filehead_contents: - #print (f'shelling out "cat {filenead} | ntfsclone --restore --overwrite /dev/loop2 - 2>&1"') - ntfscloneinfo = subprocess.run (f'cat {filenead} | ntfsclone --restore --overwrite /dev/loop2 - 2>&1', shell=True, capture_output=True, text=True).stdout - #ntfscloneinfo = subprocess.run (['cat', '/tmp/foo-ntfsclone'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True).stdout - ## sacado de claude 3 haiku - #ntfsclone v2023.4.0 (libntfs-3g) - #NTFS volume version: 3.1 - #Cluster size: 4096 bytes - #Image volume size: 104857600 bytes (105 MB) - #Space in use: 52428800 bytes (52 MB) - #Reading and restoring NTFS... - #100.00 percent completed - #Syncing ... - #Successfully cloned image to device '/dev/loop2'. - else: - ntfscloneinfo = '' - - if 'ntfsclone' in ntfscloneinfo: - tools = 'NTFSCLONE' - m = re.search (r'Image volume size *: *(\S+)', ntfscloneinfo) - size = float (m.group(1))/1000 if m else 0 - fs = 'NTFS' - imgdetect = True - - if False == imgdetect: - partimageinfo = subprocess.run (['partimage', '-B', 'gui=no', 'imginfo', filehead], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True).stdout - #partimageinfo = subprocess.run (['cat', '/tmp/foo-partimage'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True).stdout - ## sacado de un email de alberto garcía uma.es - #Volume number:.........0 - #Volume size:...........1,27 MiB - #Compression level: ....0 -> ninguno - #Identificator:.........12442509728668372730=ACACACACCB9ECEFA - #Filesystem:............ntfs - #Description:...........Sin descripcion - #Original device:......./dev/nvme0n1p2 - #Original filepath:.... stdout - #Flags:.................0: Bandera sin activar - #Creation date:.........Mon Nov 11 21:00:22 2024 - #Partition size:........476,84 GiB - #Hostname:..............ING-LTR-083 - #Compatible Version:....0.6.1 - #Encryption algorithm:..0 -> ninguno - #MBR saved count:.......0 - partimageinfo = re.sub (r':\s*\.+', ' : ', partimageinfo) - if 'Partition' in partimageinfo: - tools = 'PARTIMAGE' - m = re.search (r'Filesystem *: *(\S+)', partimageinfo) - fs = m.group(1).upper() if m else '' - - m = re.search (r'Partition size *: *(\S+)', partimageinfo) - size = m.group(1) if m else '' - size = re.sub (r' [MGT]i?B$', '', size) - size = float (size.replace (',', '.')) - size = int (size*1024*1024) - - imgdetect = True - if 'boot sector' in subprocess.run (['file', filehead], capture_output=True, text=True).stdout: - tools = 'partclone.dd' - fs = '' - size = 0 - imgdetect = True - - if not tools or not compressor or False == imgdetect: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_IMAGE, f'Image format is not valid {imgfile}') - return - - compressor = compressor.upper() - return ':'.join ([tools, compressor, fs, str (size)]) - -#/** -# ogGetImageProgram str_REPO str_imagen -#@brief muestra información sobre la imagen monolitica. -#@see ogGetImageInfo -#@param 1 REPO o CACHE contenedor de la imagen -#@param 2 filename nombre de la imagen sin extension -#@return nombre del programa usado para generar la imagen -#@exception OG_ERR_FORMAT formato incorrecto. -#@exception OG_ERR_NOTFOUND fichero no encontrado. -#@note ogGetImageProgram REPO imagenA -> partclone -#*/ ## - -#ogGetImageProgram ('REPO', 'prueba') ==> 'PARTCLONE' -def ogGetImageProgram (container, filename): - imgfile = FileLib.ogGetPath (container, f'{filename}.img') - if not os.path.exists (imgfile): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, imgfile) - return None - i = ogGetImageInfo (imgfile) - return i.split (':')[0] - -#/** -# ogGetImageCompressor str_REPO str_imagen -#@brief muestra información sobre la imagen monolitica. -#@see ogGetImageInfo -#@param 1 REPO o CACHE contenedor de la imagen -#@param 2 filename nombre de la imagen sin extension -#@return tipo de compresión usada al generar la imagen -#@exception OG_ERR_FORMAT formato incorrecto. -#@exception OG_ERR_NOTFOUND fichero no encontrado. -#@note ogGetImageCompressor REPO imagenA -> lzop -#*/ ## - -#ogGetImageCompressor ('REPO', 'prueba') ==> 'LZOP' -def ogGetImageCompressor (container, filename): - imgfile = FileLib.ogGetPath (container, f'{filename}.img') - if not os.path.exists (imgfile): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, imgfile) - return None - i = ogGetImageInfo (imgfile) - return i.split (':')[1] - - -#/** -# ogGetImageType str_REPO str_imagen -#@brief muestra información sobre el sistema de archivos de imagen monolitica. -#@see ogGetImageInfo -#@param 1 REPO o CACHE contenedor de la imagen -#@param 2 filename nombre de la imagen sin extension -#@return tipo de compresión usada al generar la imagen -#@exception OG_ERR_FORMAT formato incorrecto. -#@exception OG_ERR_NOTFOUND fichero no encontrado. -#@note ogGetImageType REPO imagenA -> NTFS -#*/ ## -#ogGetImageType ('REPO', 'imgprueba') ==> 'NTFS' -#ogGetImageType ('CACHE', 'testimg') ==> 'EXTFS' -def ogGetImageType (repo, imgname): - imgfile = FileLib.ogGetPath (src=repo, file=f'{imgname}.img') - if not os.path.exists (imgfile): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, imgfile) - return None - - i = ogGetImageInfo (imgfile) - return i.split (':')[2] - - - -#/** -# ogGetImageSize str_REPO str_imagen -#@brief muestra información sobre el tamaño (KB) del sistema de archivos de imagen monolitica. -#@see ogGetImageInfo -#@param 1 REPO o CACHE contenedor de la imagen -#@param 2 filename nombre de la imagen sin extension -#@return tipo de compresión usada al generar la imagen -#@exception OG_ERR_FORMAT formato incorrecto. -#@exception OG_ERR_NOTFOUND fichero no encontrado. -#@note ogGetImagesize REPO imagenA -> 56432234 > Kb -#*/ ## -#ogGetImageSize ('REPO', 'prueba') ==> '5642158' -def ogGetImageSize (repo, imgname): - imgfile = FileLib.ogGetPath (src=repo, file=f'{imgname}.img') - if not os.path.exists (imgfile): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, imgfile) - return None - - i = ogGetImageInfo (imgfile) - return i.split (':')[3] - - -#/** -# ogCreateGptImage int_ndisk str_repo path_image -#@brief Crea una imagen de la tabla de particiones GPT de un disco. -#@param int_ndisk nº de orden del disco -#@param str_repo repositorio de imágenes (remoto o caché local) -#@param path_image camino de la imagen (sin extensión) -#@return (nada, por determinar) -#@note repo = { REPO, CACHE } -#@exception OG_ERR_FORMAT formato incorrecto. -#@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. -#@exception OG_ERR_IMAGE error al crear la imagen del sistema. -#*/ ## - -#/** -# ogRestoreGptImage str_repo path_image int_ndisk -#@brief Restaura la imagen de la tabla de particiones GPT de un disco. -#@param str_repo repositorio de imágenes o caché local -#@param path_image camino de la imagen -#@param int_ndisk nº de orden del disco -#@return (por determinar) -#@exception OG_ERR_FORMAT formato incorrecto. -#@exception OG_ERR_NOTFOUND fichero de imagen o partición no detectados. -#@exception OG_ERR_IMAGE error al restaurar la imagen del sistema. -#*/ ## diff --git a/client/lib/engine/bin/Inventory.lib b/client/lib/engine/bin/Inventory.lib new file mode 100755 index 0000000..a905f1b --- /dev/null +++ b/client/lib/engine/bin/Inventory.lib @@ -0,0 +1,528 @@ +#!/bin/bash +#/** +#@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+ +#*/ + + +#/** +# ogGetArch +#@brief Devuelve el tipo de arquitectura del cliente. +#@return str_arch - Arquitectura (i386 para 32 bits, x86_64 para 64 bits). +#@version 0.9.2 - Primera versión para OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2010-07-17 +#*/ +function ogGetArch () +{ +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME" "$FUNCNAME => x86_64" + return +fi + +[ -d /lib64 ] && echo "x86_64" || echo "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 +#*/ ## +function ogGetOsType () +{ +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_npartition" \ + "$FUNCNAME 1 2 => Linux" + return +fi +ogGetOsVersion "$@" | cut -sf1 -d: +} + + +#/** +# 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 +#@version 1.1.0 - Primera versión para OpenGnsys +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2015-09-09 +#*/ ## +function ogGetOsUuid () +{ +# Variables locales. +local MNTDIR +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_nfilesys" \ + "$FUNCNAME 1 2 => 540e47c6-8e78-4178-aa46-042e4803fb16" + return +fi +# Error si no se reciben 2 parametros. +[ $# = 2 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +# Montar la particion, si no lo estaba previamente. +MNTDIR=$(ogMount $1 $2) || return $? + +# Obtener UUID según el tipo de sistema operativo. +case "$(ogGetOsType $1 $2)" in + Linux) + # Leer el UUID del sistema de ficheros raíz o el fichero de identificador. + findmnt -no UUID $MNTDIR 2>/dev/null || cat $MNTDIR/etc/machine-id 2>/dev/null + ;; + Windows) + # Leer identificador en clave de registro. + ogGetRegistryValue $MNTDIR SOFTWARE '\Microsoft\Cryptography\MachineGuid' 2>/dev/null + ;; +esac +} + + +#/** +# ogGetSerialNumber +#@brief Obtiene el nº de serie del cliente. +#@version 1.1.0 - Primeras versión con OpenGnsys +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2015-06-08 +#*/ ## +function ogGetSerialNumber () +{ +# Variables locales. +local SERIALNO +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME" "$FUNCNAME => 123456" + return +fi + +# Obtener nº de serie (ignorar los no especificados). +SERIALNO=$(dmidecode -s system-serial-number | egrep -vi "(^[ 0]+$|not specified|to be filled|invalid entry|default string)") +# Quitar espacios y truncar cadena si >25 caracteres. +SERIALNO="${SERIALNO// /}" +[ ${#SERIALNO} -gt 25 ] && SERIALNO="${SERIALNO:0:22}..." +[ -n "$SERIALNO" ] && echo "$SERIALNO" +return 0 +} + + +#/** +# ogIsEfiActive +#@brief Comprueba si el sistema tiene activo el arranque EFI. +#*/ ## +function ogIsEfiActive () +{ +test -d /sys/firmware/efi +} + + +#/** +# 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 +#@version 0.1 - Primeras pruebas con OpenGnSys +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2009-07-28 +#@version 1.1.0 - Incluir nuevos componentes al inventario. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2014-04-23 +#*/ ## +function ogListHardwareInfo () +{ +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME" + return +fi + +# Recopilación de dispositivos procesando la salida de \c lshw +ogEcho info "$MSG_HARDWAREINVENTORY}" +echo "cha=$(dmidecode -s chassis-type)" | grep -v "Other" +[ -e /sys/firmware/efi ] && echo "boo=UEFI" || echo "boo=BIOS" +lshw | awk 'BEGIN {type="mod";} + /product:/ {sub(/ *product: */,""); prod=$0;} + /vendor:/ {sub(/ *vendor: */,""); vend=$0;} + /version:/ {sub(/ *version: */,"v.");vers=$0;} + /size:/ {size=$2;} + /clock:/ {clock=$2;} + /slot:/ {sub(/ *slot: */,""); slot=$0;} + /\*-/ {if (type=="mem"){ + if (size!=""){ + numbank++; + print type"="vend,prod,size,clock" ("slot")";} + }else{ + if (type=="totalmem"){ + if (size!=""){ + totalmemory="mem="size;} + }else{ + if (type!="" && prod!=""){ + if (prod=="v."vers) + vers=""; + print type"="vend,prod,size,vers;} } + } + type=prod=vend=vers=size=clock=slot="";} + $1~/-core/ {type="boa";} + $1~/-firmware/ {type="bio";} + $1~/-cpu/ {type="cpu";} + $1~/-bank/ {type="mem";} + $1~/-memory/ {type="totalmem";} + $1~/-ide/ {type="ide";} + $1~/-storage/ {type="sto";} + $1~/-disk/ {type="dis";} + $1~/-cdrom/ {type="cdr";} + $1~/-display/ {type="vga";} + $1~/-network/ {type="net";} + $1~/-multimedia/ {type="mul";} + $1~/-usb/ {type="usb";} + $1~/-firewire/ {type="fir";} + $1~/-serial/ {type="bus";} + END {if (type!="" && prod!="") + print type"="vend,prod,size,vers; + if (length(numbank)==0 && length(totalmemory)>=4) + print totalmemory; } + ' +# */ (comentario para Doxygen) +} + + +#/** +# 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 +#@version 0.1 - Primeras pruebas con OpenGnSys +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2009-09-23 +#@version 1.0.5 - Aproximación para inventario de software de Mac OS. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2013-10-08 +#@version 1.0.6 - Proceso depende del tipo de SO y soporte para FreeBSD. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2014-11-13 +#@version 1.1.0 - Se muestra el sistema operativo en la primera línea de la salida +#@author Irina Gomez, ETSII Universidad de Sevilla +#@date 2016-04-26 +#*/ ## +function ogListSoftware () +{ +# Variables locales. +local APPS HIVE k KEYS KEYS32 MNTDIR PKGDIR PROG VERS TMPFILE TYPE + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME 1 1" + return +fi +# Error si no se reciben 2 parametros. +[ $# = 2 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +# Obtener tipo de sistema de archivos y montarlo. +MNTDIR=$(ogMount $1 $2) || return $? +TYPE=$(ogGetOsType $1 $2) || return $? + +# Ficheros temporales. +APPS=$(mktemp /tmp/apps.XXXXX) +TMPFILE=$(mktemp /tmp/tmp.XXXXX) +trap "rm -f $APPS $TMPFILE" 1 2 3 9 15 + +case "$TYPE" in + Linux) # Software de GNU/Linux. + # Procesar paquetes dpkg. + PKGDIR="${MNTDIR}/var/lib/dpkg" + if [ -r $PKGDIR ]; then + # Proceso de fichero en sistemas de 64 bits. + awk '/Package:/ {if (pack!="") print pack,vers; + sub(/-dev$/,"",$2); + pack=$2} + /Version:/ {sub(/^.*:/,"",$2); sub(/-.*$/,"",$2); + vers=$2} + /Status:/ {if ($2!="install") pack=vers=""} + END {if (pack!="") print pack,vers} + ' $PKGDIR/status > $APPS + fi + # Procesar paquetes RPM. + PKGDIR="${MNTDIR}/var/lib/rpm" + if [ -r $PKGDIR ]; then + # Listar si está instalado el paquete "rpm" en el cliente. + if which rpm &>/dev/null; then + rm -f ${PKGDIR}/__db.* + rpm --dbpath $PKGDIR -qa --qf "%{NAME} %{VERSION}\n" 2>/dev/null | \ + awk '$1!~/-devel$/ {sub(/-.*$/,"",$2); print $0}' > $APPS + rm -f ${PKGDIR}/__db.* + else + # Obtener el nombre de cada paquete en la BD de RPM. + python <<<" +import re; +import bsddb; +db=bsddb.hashopen('$PKGDIR/Name','r'); +for k in db.keys(): + print re.sub('-devel$','',k);" > $APPS + fi + fi + # Procesar paquetes pacman. + PKGDIR="${MNTDIR}/var/lib/pacman/local" + if [ -r $PKGDIR ]; then + ls $PKGDIR | awk -F- '/-/ {print gensub(/-/, " ", NF-2);}' > $APPS + fi + # Procesar aplicaciones Snappy. + PKGDIR="${MNTDIR}/snap" + find $PKGDIR/*/current/meta -name snap.yaml -exec \ + awk '/name:/ {pack=$2} + /version:/ {vers=$2} + END {if (pack!="") print pack,"(snap)",vers}' {} 2>/dev/null \; >> $APPS + # Procesar aplicaciones Flatpak. + PKGDIR="${MNTDIR}/var/lib/flatpak" + ls -1 $PKGDIR/app/*/current/active/deploy 2> /dev/null | python -c " +import sys +for f in sys.stdin: + p = open(f.strip()).read().split('\0') + try: + if(p[0] != 'flathub'): + raise ValueError + print('{} (flatpak) {}'.format(p[p.index('appdata-name') + 4], p[p.index('appdata-version') + 1])) + except ValueError: + pass +" >> $APPS + ;; + Windows) # Software de Windows. + # Comprobar tipo de proceso del registro de Windows. + if which hivexregedit &>/dev/null; then + # Nuevo proceso más rápido basado en "hivexregedit". + HIVE=$(ogGetHivePath $MNTDIR software 2>/dev/null) + if [ -n "$HIVE" ]; then + # Claves de registro para programas instalados. + hivexregedit --unsafe-printable-strings --export "$HIVE" '\Microsoft\Windows\CurrentVersion\Uninstall' > $TMPFILE 2>/dev/null + hivexregedit --unsafe-printable-strings --export "$HIVE" '\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall' >> $TMPFILE 2>/dev/null + # Mostrar los valores "DisplayName" y "DisplayVersion" para cada clave. + awk -F\" '$1~/^\[/ {n=""} + $2~/DisplayName/ {n=$4} + $2~/DisplayVersion/ {print n,$4} + ' $TMPFILE > $APPS + fi + else + # Compatibilidad con clientes ogLive antiguos. + # Claves de registro para programas instalados: formato "{clave}". + KEYS=$(ogListRegistryKeys $MNTDIR software '\Microsoft\Windows\CurrentVersion\Uninstall') + KEYS32=$(ogListRegistryKeys $MNTDIR software '\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall') + # Mostrar los valores "DisplayName" y "DisplayVersion" para cada clave. + for k in $KEYS; do + PROG=$(ogGetRegistryValue $MNTDIR software "\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\$k\\DisplayName") + if [ -n "$PROG" ]; then + VERS=$(ogGetRegistryValue $MNTDIR software "\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\$k\\DisplayVersion") + echo "$PROG $VERS" + fi + done > $APPS + for k in $KEYS32; do + PROG=$(ogGetRegistryValue $MNTDIR software "\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\$k\\DisplayName") + if [ -n "$PROG" ]; then + VERS=$(ogGetRegistryValue $MNTDIR software "\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\$k\\DisplayVersion") + echo "$PROG $VERS" + fi + done >> $APPS + fi + ;; + MacOS) # Software de Mac OS. + # Listar directorios de aplicaciones e intentar obtener la versión del fichero .plist (tanto original como descomprimido). + find "${MNTDIR}/Applications" -type d -name "*.app" -prune -print | \ + while read k; do + FILE="$k/Contents/version.plist" + [ -s "$FILE" ] || FILE="$k/Contents/version.plist.uncompress" + [ -s "$FILE" ] && VERSION=$(awk -F"[<>]" '/ShortVersionString/ {getline;v=$3} + END {print v}' "$FILE") + echo "$(basename "$k" .app) $VERSION" + done > $APPS + ;; + BSD) # Software de FreeBSD. + sqlite3 $MNTDIR/var/db/pkg/local.sqlite <<<"SELECT name FROM pkg_search;" 2>/dev/null | \ + sed 's/\(.*\)-\(.*\)/\1 \2/g' > $APPS + ;; + *) ogRaiseError $OG_ERR_NOTOS "$1, $2 ${TYPE+($TYPE)}" + return $? ;; +esac + +# Mostrar sistema Operativo y aplicaciones. +ogGetOsVersion $1 $2 | awk -F: '{print $2}' +sort $APPS | uniq | iconv -ct utf-8 +rm -f $APPS $TMPFILE +} + +#/** +# 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. +#@version 0.9 - Primera versión para OpenGnSys +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2009-09-15 +#@version 1.0.4 - Incluir tipos BSD, MacOS y Solaris. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2012-06-29 +#@version 1.0.5 - Incluir tipos GrubLoader, Hurd y WinLoader, leer por defecto fichero /etc/os-release. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2013-10-07 +#@version 1.0.6 - Detectar GrubLoader al final y sistemas basados en EFI. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2014-08-27 +#*/ ## +function ogGetOsVersion () +{ +# Variables locales. +local MNTDIR TYPE DISTRIB VERSION IS64BIT FILE +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_nfilesys" \ + "$FUNCNAME 1 2 => Linux:Ubuntu precise (12.04 LTS) 64 bits" + return +fi +# Error si no se reciben 2 parametros. +[ $# = 2 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +# Montar la particion, si no lo estaba previamente. +MNTDIR=$(ogMount $1 $2) || return $? + +# Buscar tipo de sistema operativo. +# Para GNU/Linux: leer descripción. +TYPE="Linux" +FILE="$MNTDIR/etc/os-release" +[ -r $FILE ] && VERSION="$(awk -F= '$1~/PRETTY_NAME/ {gsub(/\"/,"",$2); print $2}' $FILE)" +# Si no se puede obtener, buscar en ficheros del sistema. +if [ -z "$VERSION" ]; then + FILE="$MNTDIR/etc/lsb-release" + [ -r $FILE ] && VERSION="$(awk -F= '$1~/DESCRIPTION/ {gsub(/\"/,"",$2); print $2}' $FILE)" + for DISTRIB in redhat SuSE mandrake gentoo; do + FILE="$MNTDIR/etc/${DISTRIB}-release" + [ -r $FILE ] && VERSION="$(head -1 $FILE)" + done + FILE="$MNTDIR/etc/arch-release" + [ -r $FILE ] && VERSION="Arch Linux" + FILE="$MNTDIR/etc/slackware-version" + [ -r $FILE ] && VERSION="Slackware $(cat $FILE)" +fi +# Si no se encuentra, intentar ejecutar "lsb_release". +[ -z "$VERSION" ] && VERSION=$(chroot $MNTDIR lsb_release -d 2>/dev/null | awk -F":\t" '{print $2}') +# Comprobar Linux de 64 bits. +[ -n "$VERSION" ] && [ -e $MNTDIR/lib64 ] && IS64BIT="$MSG_64BIT" +# Para Android, leer fichero de propiedades. +if [ -z "$VERSION" ]; then + TYPE="Android" + FILE="$MNTDIR/android*/system/build.prop" + [ -r $FILE ] && VERSION="Android $(awk -F= '$1~/(product.brand|build.version.release)/ {print $2}' $FILE | tr '\n' ' ')" + [ -e $MNTDIR/lib64 ] && IS64BIT="$MSG_64BIT" +fi +# Para GNU/Hurd, comprobar fichero de inicio (basado en os-prober). +if [ -z "$VERSION" ]; then + TYPE="Hurd" + FILE="$MNTDIR/hurd/init" + [ -r $FILE ] && VERSION="GNU/Hurd" +fi +# Para Windows: leer la version del registro. +if [ -z "$VERSION" ]; then + TYPE="Windows" + FILE="$(ogGetHivePath $MNTDIR SOFTWARE)" + if [ -n "$FILE" ]; then + # Nuevo método más rápido para acceder al registro de Windows.. + VERSION=$(echo $(hivexsh << EOT 2>/dev/null +load $FILE +cd \Microsoft\Windows NT\CurrentVersion +lsval ProductName +lsval ReleaseId +EOT + )) + [ -n "$(reglookup -H -p "Microsoft/Windows/CurrentVersion/ProgramW6432Dir" "$FILE" 2>/dev/null)" ] && IS64BIT="$MSG_64BIT" + if [ -z "$VERSION" ]; then + # Compatibilidad con métrodo antiguo y más lento de acceder al registro. + VERSION=$(ogGetRegistryValue $MNTDIR software '\Microsoft\Windows NT\CurrentVersion\ProductName' 2>/dev/null) + [ -n "$(ogGetRegistryValue $MNTDIR software '\Microsoft\Windows\CurrentVersion\ProgramW6432Dir' 2>/dev/null)" ] && IS64BIT="$MSG_64BIT" + fi + fi +fi +# Para cargador Windows: buscar versión en fichero BCD (basado en os-prober). +if [ -z "$VERSION" ]; then + TYPE="WinLoader" + FILE="$(ogGetPath $MNTDIR/boot/bcd)" + [ -z "$FILE" ] && FILE="$(ogGetPath $MNTDIR/EFI/Microsoft/boot/bcd)" + if [ -n "$FILE" ]; then + for DISTRIB in "Windows Recovery" "Windows Boot"; do + if grep -aqs "$(echo "$DISTRIB" | sed 's/./&./g')" $FILE; then + VERSION="$DISTRIB loader" + fi + done + fi +fi +# Para macOS: detectar kernel y completar con fichero plist de información del sistema. +if [ -z "$VERSION" ]; then + TYPE="MacOS" + # Kernel de Mac OS (no debe ser fichero de texto). + FILE="$MNTDIR/mach_kernel" + if [ -z "$(file -b $FILE | grep 'text')" ]; then + # Obtener tipo de kernel. + [ -n "$(file -b $FILE | grep 'Mach-O')" ] && VERSION="macOS" + [ -n "$(file -b $FILE | grep 'Mach-O 64-bit')" ] && IS64BIT="$MSG_64BIT" + # Datos de configuración de versión de Mac OS. + FILE="$MNTDIR/System/Library/CoreServices/SystemVersion.plist" + [ -r $FILE ] && VERSION=$(awk -F"[<>]" ' + /ProductName/ {getline;s=$3} + /ProductVersion/ {getline;v=$3} + END {print s,v}' $FILE) + # Datos de recuperación de macOS. + FILE="$MNTDIR/com.apple.recovery.boot" + [ -r $FILE -a -n "$VERSION" ] && VERSION="$VERSION recovery" + fi +fi +# Para FreeBSD: obtener datos del Kernel. +### TODO Revisar solución. +if [ -z "$VERSION" ]; then + TYPE="BSD" + FILE="$MNTDIR/boot/kernel/kernel" + if [ -r $FILE ]; then + VERSION="$(strings $FILE|awk '/@.*RELEASE/ {sub(/@\(#\)/,""); print $1,$2}')" + [ -n "$(file -b $FILE | grep 'x86-64')" ] && IS64BIT="$MSG_64BIT" + fi +fi +# Para Solaris: leer el fichero de versión. +### TODO Revisar solución. +if [ -z "$VERSION" ]; then + TYPE="Solaris" + FILE="$MNTDIR/etc/release" + [ -r $FILE ] && VERSION="$(head -1 $FILE)" +fi +# Para cargador GRUB, comprobar fichero de configuración. +if [ -z "$VERSION" ]; then + TYPE="GrubLoader" + for FILE in $MNTDIR/{,boot/}grub/menu.lst; do + [ -r $FILE ] && VERSION="GRUB Loader" + done +#/* (comentario Doxygen) + for FILE in $MNTDIR/{,boot/}{grub{,2},EFI/*}/grub.cfg; do + [ -r $FILE ] && VERSION="GRUB2 Loader" + done +fi +#*/ (Comentario Doxygen) +# Mostrar resultado y salir sin errores. +[ -n "$VERSION" ] && echo "$TYPE:$VERSION $IS64BIT" +return 0 +} diff --git a/client/lib/engine/bin/InventoryLib.py b/client/lib/engine/bin/InventoryLib.py deleted file mode 100755 index 2269af3..0000000 --- a/client/lib/engine/bin/InventoryLib.py +++ /dev/null @@ -1,531 +0,0 @@ -#/** -#@file InventoryLib.py -#@brief Librería o clase Inventory -#@class Inventory -#@brief Funciones para recogida de datos de inventario de hardware y software de los clientes. -#@warning License: GNU GPLv3+ -#*/ - -import platform -import sys -import os -import subprocess -import re -import json -import shutil -import glob -import plistlib -#import bsddb - -import ogGlobals -import SystemLib -import FileSystemLib -import RegistryLib -import FileLib - - -#/** -# 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 os.path.isdir ('/lib64'): - return 'x86_64' - else: - return '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) - if os_version: - return os_version.split(":", 1)[0] - else: - return None - except Exception as e: - 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 (disk, par): - mntdir = FileSystemLib.ogMount (disk, par) - if not mntdir: return None - -# Obtener UUID según el tipo de sistema operativo. - os_type = ogGetOsType (disk, par) - if 'Linux' == os_type: - # Leer el UUID del sistema de ficheros raíz o el fichero de identificador. - uuid = subprocess.run (['findmnt', '-no', 'UUID', mntdir], capture_output=True, text=True).stdout.strip() - if not uuid: - uuid = open (os.path.join (mntdir, 'etc', 'machine-id')).read().strip() - return uuid - elif 'Windows' == os_type: - # Leer identificador en clave de registro. - uuid = RegistryLib.ogGetRegistryValue (mntdir, 'SOFTWARE', r'\Microsoft\Cryptography\MachineGuid') - return uuid - - -#/** -# ogGetSerialNumber -#@brief Obtiene el nº de serie del cliente. -#*/ ## -def ogGetSerialNumber(): - SERIALNO = subprocess.check_output(["dmidecode", "-s", "system-serial-number"]).decode().strip() - SERIALNO = re.sub(r"(not specified|to be filled|invalid entry|default string)", "", SERIALNO, flags=re.IGNORECASE) - SERIALNO = SERIALNO.replace(" ", "") - SERIALNO = SERIALNO[:25] if len(SERIALNO) > 25 else SERIALNO - if SERIALNO: return SERIALNO - return None - - -#/** -# ogIsEfiActive -#@brief Comprueba si el sistema tiene activo el arranque EFI. -#*/ ## -def ogIsEfiActive(): - return os.path.isdir("/sys/firmware/efi") - - -#/** -# 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(): - ret = '' - - SystemLib.ogEcho ([], 'info', ogGlobals.lang.MSG_HARDWAREINVENTORY) - # Ejecutar dmidecode y obtener tipo de chasis - dmi_out = subprocess.run (['dmidecode', '-s', 'chassis-type'], capture_output=True, text=True).stdout - dmi_out = '\n'.join ([ x for x in dmi_out.splitlines() if 'Other' not in x ]) - ret += f'cha={dmi_out}\n' - - if os.path.exists ('/sys/firmware/efi'): - ret += f'boo=UEFI\n' - else: - ret += f'boo=BIOS\n' - - awk_script = r''' - BEGIN {type="mod";} - /product:/ {sub(/ *product: */,""); prod=$0;} - /vendor:/ {sub(/ *vendor: */,""); vend=$0;} - /version:/ {sub(/ *version: */,"v.");vers=$0;} - /size:/ {size=$2;} - /clock:/ {clock=$2;} - /slot:/ {sub(/ *slot: */,""); slot=$0;} - /\*-/ {if (type=="mem"){ - if (size!=""){ - numbank++; - print type"="vend,prod,size,clock" ("slot")";} - }else{ - if (type=="totalmem"){ - if (size!=""){ - totalmemory="mem="size;} - }else{ - if (type!="" && prod!=""){ - if (prod=="v."vers) - vers=""; - print type"="vend,prod,size,vers;} } - } - type=prod=vend=vers=size=clock=slot="";} - $1~/-core/ {type="boa";} - $1~/-firmware/ {type="bio";} - $1~/-cpu/ {type="cpu";} - $1~/-bank/ {type="mem";} - $1~/-memory/ {type="totalmem";} - $1~/-ide/ {type="ide";} - $1~/-storage/ {type="sto";} - $1~/-disk/ {type="dis";} - $1~/-cdrom/ {type="cdr";} - $1~/-display/ {type="vga";} - $1~/-network/ {type="net";} - $1~/-multimedia/ {type="mul";} - $1~/-usb/ {type="usb";} - $1~/-firewire/ {type="fir";} - $1~/-serial/ {type="bus";} - END {if (type!="" && prod!="") - print type"="vend,prod,size,vers; - if (length(numbank)==0 && length(totalmemory)>=4) - print totalmemory; } - ''' - lshw_out = subprocess.run (['lshw'], capture_output=True, text=True).stdout - awk_out = subprocess.run (['awk', awk_script], input=lshw_out, capture_output=True, text=True).stdout - - ret += awk_out - - return ret - - -#/** -# 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, par): - mntdir = FileSystemLib.ogMount (disk, par) - if not mntdir: return None - ostype = ogGetOsType (disk, par) - if not ostype: return None - - apps = [] - - if 'Linux' == ostype: - # Procesar paquetes dpkg. - pkgdir = f'{mntdir}/var/lib/dpkg' - if os.path.exists (pkgdir): - status_file = os.path.join(pkgdir, "status") - awk_script = ''' - /Package:/ {if (pack!="") print pack,vers; - sub(/-dev$/,"",$2); - pack=$2} - /Version:/ {sub(/^.*:/,"",$2); sub(/-.*$/,"",$2); - vers=$2} - /Status:/ {if ($2!="install") pack=vers=""} - END {if (pack!="") print pack,vers} - ''' - awk_out = subprocess.run (['awk', awk_script, status_file], capture_output=True, text=True).stdout - apps = awk_out.splitlines() - - # Procesar paquetes RPM. - pkgdir = f'{mntdir}/var/lib/rpm' - if os.path.exists (pkgdir): - if shutil.which ('rpm'): - for f in glob.glob (f'{pkgdir}/__db.*'): - os.unlink (f) - rpm_out = subprocess.run (['rpm', '--dbpath', pkgdir, '-qa', '--qf', '%{NAME} %{VERSION}\n'], capture_output=True, text=True).stdout - for l in rpm_out.splitlines(): - words = l.split() - if (not re.search ('-devel$', words[0])): - words[1] = re.sub ('-.*', '', words[1]) - apps.append (' '.join (words)) - for f in glob.glob (f'{pkgdir}/__db.*'): - os.unlink (f) - else: - pass - #db = bsddb.hashopen (f'{pkgdir}/Name', 'r'); - #for k in db.keys(): - # apps.append (re.sub ('-devel$', '', k)) - - # Procesar paquetes pacman. - pkgdir = f'{mntdir}/var/lib/pacman/local' - if os.path.exists (pkgdir): - for f in glob.glob (f'{pkgdir}/*'): - if '-' not in f: continue - idx = f[0:f.rfind ('-')].rfind ('-') ## index of 2nd-to-last dash - apps.append (f[0:idx] + ' ' + f[idx+1:]) - # Procesar aplicaciones Snappy. - pkgdir = f'{mntdir}/snap' - out = '' - awk_script = ''' - /name:/ {pack=$2} - /version:/ {vers=$2} - END {if (pack!="") print pack,"(snap)",vers} - ''' - files = subprocess.run (['find', f'{pkgdir}/*/current/meta', '-name', 'snap.yaml'], capture_output=True, text=True).stdout.splitlines() - for f in files: - awk_out = subprocess.run (['awk', awk_script, f], capture_output=True, text=True).stdout - out += awk_out - apps += out.splitlines() - # Procesar aplicaciones Flatpak. - pkgdir = f'{mntdir}/var/lib/flatpak' - files = glob.glob (f'{pkgdir}/app/*/current/active/deploy/*') - for f in files: - p = open (f.strip()).read().split ('\0') - try: - if (p[0] != 'flathub'): raise ValueError - apps.append ('{} (flatpak) {}'.format (p[p.index('appdata-name') + 4], p[p.index('appdata-version') + 1])) - except ValueError: - pass - - elif 'Windows' == ostype: - if shutil.which ('hivexregedit'): - hive = RegistryLib.ogGetHivePath (mntdir, 'software') - if hive: - cmd1_out = subprocess.run (['hivexregedit', '--unsafe-printable-strings', '--export', hive, r'\Microsoft\Windows\CurrentVersion\Uninstall'], capture_output=True, text=True).stdout - cmd1_out += subprocess.run (['hivexregedit', '--unsafe-printable-strings', '--export', hive, r'\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall'], capture_output=True, text=True).stdout - out = name = '' - for l in cmd1_out.splitlines(): - words = l.split ('"') - if len(words) < 4: continue - if (re.match (r'\[', words[0])): name='' - if (re.search ('DisplayName', words[1])): name=words[3] - if (re.search ('DisplayVersion', words[1])): apps.append (f'{name} {words[3]}') - else: - keys = RegistryLib.ogListRegistryKeys (mntdir, 'software', r'\Microsoft\Windows\CurrentVersion\Uninstall') - keys32 = RegistryLib.ogListRegistryKeys (mntdir, 'software', r'\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall') - for k in keys: - prog = RegistryLib.ogGetRegistryValue (mntdir, 'software', rf'\Microsoft\Windows\CurrentVersion\Uninstall\{k}\DisplayName') - if prog: - vers = RegistryLib.ogGetRegistryValue (mntdir, 'software', rf'\Microsoft\Windows\CurrentVersion\Uninstall\{k}\DisplayVersion') - apps.append (f'{prog} {vers}') - for k in keys32: - prog = RegistryLib.gGetRegistryValue (mntdir, 'software', rf'\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{k}\DisplayName') - if prog: - vers = RegistryLib.ogGetRegistryValue (mntdir, 'software', rf'\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{k}\DisplayVersion') - apps.append (f'{prog} {vers}') - - elif 'MacOS' == ostype: - files = subprocess.run (['find', f'{mntdir}/Applications', '-type', 'd', '-name', '*.app', '-prune', '-print'], capture_output=True, text=True).stdout.splitlines() - for k in files: - FILE = f'{k}/Contents/version.plist' - if not os.stat (FILE).st_size: - FILE = f'{k}/Contents/version.plist.uncompress' - if os.stat (FILE).st_size: - VERSION = subprocess.run (['awk', '-F[<>]', '/ShortVersionString/ {getline;v=$3} END {print v}', FILE], capture_output=True, text=True).stdout.strip() - bn = os.path.basename (k) - bn = re.sub ('.app$', '', bn) - apps.append (f'{bn} {VERSION}') - - elif 'BSD' == ostype: - sqlite_out = subprocess.run (['sqlite3', f'{mntdir}/var/db/pkg/local.sqlite'], input='SELECT name FROM pkg_search;\n', capture_output=True, text=True).stdout - for l in sqlite_out.splitlines(): - apps.append (' '.join (re.search ('(.*)-(.*)', l).groups())) - - else: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTOS, f'{disk}, {par} ({ostype})') - return None - - os_version = ogGetOsVersion (disk, par).split (':')[1] - return [os_version] + 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): - 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("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(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 - version = version.replace ('\n', ' ') -# 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 not file: - file = FileLib.ogGetPath (file=f'{mntdir}/EFI/Microsoft/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_regex, 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/Net.lib b/client/lib/engine/bin/Net.lib new file mode 100755 index 0000000..d8f272b --- /dev/null +++ b/client/lib/engine/bin/Net.lib @@ -0,0 +1,345 @@ +#!/bin/bash +#/** +#@file Net.lib +#@brief Librería o clase Net +#@class Net +#@brief Funciones básicas de red. +#@version 1.0.6 +#@warning License: GNU GPLv3+ +#*/ + + +#/** +# ogChangeRepo IPREPO [ OgUnit ] +#@brief Cambia el repositorio para el recurso remoto images. +#@param 1 Ip Repositorio +#@param 2 Abreviatura Unidad Organizativa +#@return Cambio recurso remoto en OGIMG. +#@version 1.1 - Primera versión para OpenGnSys. +#@author Irina Gomez, ETSII Universidad de Sevilla +#@date 2015-06-16 +#*/ +function ogChangeRepo () +{ +local SRCIMG NEWREPO REPO OGUNIT + +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME IPREPO [ OgUnit ]" \ + "$FUNCNAME 10.1.120.3" \ + "$FUNCNAME 10.1.120.3 cdc" + return +fi + + +if [ $# -lt 1 ]; then + ogRaiseError $OG_ERR_FORMAT "$MSG_FORMAT: $FUNCNAME IPREPO [ OgUnit ]" + return $? +fi + + +# Opciones de montaje: lectura o escritura +mount |grep "ogimages.*rw," &>/dev/null && RW=",rw" || RW=",ro" + +# Si REPO tomamos el repositorio y la unidad organizativa actual +REPO=$(ogGetRepoIp) +OGUNIT="$(df | awk -F " " '/ogimages/ {sub("//.*/ogimages","",$1); sub("/","",$1); print $1}')" + +# Parametros de entrada. Si $1 = "REPO" dejo el repositorio actual +[ "${1^^}" == "REPO" ] && NEWREPO="$REPO" || NEWREPO="${1}" + +# Si $1 y $2 son el repositorio y la OU actual me salgo +[ "$NEWREPO" == "$REPO" ] && [ "$2" == "$OGUNIT" ] && return 0 + +source /scripts/functions +source /scripts/ogfunctions +umount $OGIMG +[ "$2" == "" ] && SRCIMG="ogimages" || SRCIMG="ogimages/$2" +eval $(grep "OPTIONS=" /scripts/ogfunctions) + +ogEcho session log "$MSG_HELP_ogChangeRepo $NEWREPO ${2%/}" +ogConnect $NEWREPO $ogprotocol $SRCIMG $OGIMG $RW + +# Si da error volvemos a montar el inicial +if [ $? -ne 0 ]; then + ogConnect $REPO $ogprotocol $SRCIMG $OGIMG $RW + ogRaiseError session $OG_ERR_REPO "$NEWREPO" + return $? +fi + +} + + +#/** +# ogGetGroupDir [ str_repo ] +#@brief Devuelve el camino del directorio para el grupo del cliente. +#@param str_repo repositorio de imágenes (opcional) +#@return path_dir - Camino al directorio del grupo. +#@note repo = { REPO, CACHE } REPO por defecto +#@exception OG_ERR_FORMAT formato incorrecto. +#@version 1.0.2 - Primera versión para OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2011-10-03 +#*/ +function ogGetGroupDir () +{ +local REPO DIR GROUP +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME str_repo" \ + "$FUNCNAME REPO ==> /opt/opengnsys/images/groups/Grupo1" + return +fi +# Error si se recibe más de 1 parámetro. +case $# in + 0) REPO="REPO" ;; + 1) REPO="$1" ;; + *) ogRaiseError $OG_ERR_FORMAT "$*" + return $? ;; +esac + +GROUP="$(ogGetGroupName)" +if [ -n "$GROUP" ]; then + DIR=$(ogGetPath "$REPO" "/groups/$GROUP" 2>/dev/null) + [ -d "$DIR" ] && echo "$DIR" +fi +# Para que no haya error al fallar la condición anterior +return 0 +} + + +#/** +# ogGetGroupName +#@brief Devuelve el nombre del grupo al que pertenece el cliente. +#@return str_group - Nombre de grupo. +#@version 1.0.2 - Primera versión para OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2011-10-03 +#*/ +function ogGetGroupName () +{ +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME" "$FUNCNAME => Grupo1" + return +fi +[ -n "$group" ] && echo "$group" +} + + +#/** +# ogGetHostname +#@brief Muestra el nombre del cliente. +#@return str_host - nombre de máquina +#@version 0.10 - Integración en OpenGnSys 0.10 +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2010-02-11 +#*/ ## +function ogGetHostname () +{ +local HOST +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME" "$FUNCNAME => pc1" + return +fi +# Tomar nombre de la variable HOSTNAME +HOST="$HOSTNAME" +# Si no, tomar del DHCP, opción host-name /* (comentario para Doxygen) +[ -z "$HOST" ] && HOST=$(awk -F\" '/option host-name/ {gsub(/;/,""); host=$2} + END {print host} + ' /var/lib/dhcp3/dhclient.leases) +# Si no, leer el parámetro del kernel hostname (comentario para Doxygen) */ +[ -z "$HOST" ] && HOST=$(awk 'BEGIN {RS=""; FS="="} + $1~/hostname/ {print $2}' /proc/cmdline) +[ "$HOSTNAME" != "$HOST" ] && export HOSTNAME="$HOST" +[ -n "$HOST" ] && echo $HOST +} + + +#/** +# ogGetIpAddress +#@brief Muestra la dirección IP del sistema +#@return str_ip - Dirección IP +#@version 0.10 - Integración en OpenGnSys 0.10 +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2010-02-11 +#@version 1.0 - Integración OpenGnSys 0.10 Opengnsys 0.10-testing +#@note Usa las variables utilizadas por el initrd "/etc/net-ethX.conf +#@author Antonio J. Doblas Viso. Universidad de Malaga. +#@date 2011-02-24 +#@version 1.0.2 - Soporte para varias tarjetas de red +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2011-06-17 +#*/ ## +function ogGetIpAddress () +{ +local IP +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME" "$FUNCNAME => 192.168.0.10" + return +fi +if [ -n "$IPV4ADDR" ]; then + IP="$IPV4ADDR" +else + # Obtener direcciones IP. + if [ -n "$DEVICE" ]; then + IP=$(ip -o address show up dev "$DEVICE" 2>/dev/null | awk '{if ($3~/inet$/) {printf ("%s ", $4)}}') + else + IP=$(ip -o address show up | awk '$2!~/lo/ {if ($3~/inet$/) {printf ("%s ", $4)}}') + fi +fi +# Mostrar solo la primera. +echo "${IP%%/*}" # (comentario para Doxygen) */ +} + + +#/** +# ogGetMacAddress +#@brief Muestra la dirección Ethernet del cliente. +#@return str_ether - Dirección Ethernet +#@version 0.10 - Integración en OpenGnSys 0.10 +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2010-02-11 +#@version 1.0.2 - Soporte para varias tarjetas de red +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2011-06-17 +#*/ ## +function ogGetMacAddress () +{ +local MAC +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME" "$FUNCNAME => 00:11:22:33:44:55" + return +fi +# Obtener direcciones Ethernet. +if [ -n "$DEVICE" ]; then + MAC=$(ip -o link show up dev "$DEVICE" 2>/dev/null | awk '{sub (/.*\\/, ""); if ($1~/ether/) printf ("%s ", toupper($2));}') +else + MAC=$(ip -o link show up | awk '$2!~/lo/ {sub (/.*\\/, ""); if ($1~/ether/) printf ("%s ", toupper($2));}') +fi +# Mostrar sólo la primera. +echo ${MAC%% *} +} + + +#/** +# ogGetNetInterface +#@brief Muestra la interfaz de red del sistema +#@return str_interface - interfaz de red +#@version 1.0 - Integración OpenGnSys 0.10 Opengnsys 0.10-testing +#@note Usa las variables utilizadas por el initrd "/etc/net-ethX.conf +#@author Antonio J. Doblas Viso. Universidad de Malaga. +#@date 2011-02-24 +#*/ ## +function ogGetNetInterface () +{ +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME" "$FUNCNAME => eth0" + return +fi +[ -n "$DEVICE" ] && echo "$DEVICE" +} + + +#/** +# ogGetRepoIp +#@brief Muestra la dirección IP del repositorio de datos. +#@return str_ip - Dirección IP +#@version 0.10 - Integración en OpenGnSys 0.10 +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2011-01-13 +#@version 1.0 - Integración OpenGnSys 0.10 Opengnsys 0.10-testing +#@note Comprobacion segun protocolo de conexion al Repo +#@author Antonio J. Doblas Viso. Universidad de Malaga. +#@date 2011-02-24 +#@version 1.0.6 - Obtener datos del punto de montaje, evitando fallo si $ogprotocol está vacía. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2014-08-27 +#*/ ## +function ogGetRepoIp () +{ +# Variables locales. +local SOURCE FSTYPE + +# Mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME" "$FUNCNAME => 192.168.0.2" + return +fi + +# Obtener direcciones IP, según el tipo de montaje. +eval $(findmnt -P -o SOURCE,FSTYPE $OGIMG) +case "$FSTYPE" in + nfs) echo "$SOURCE" | cut -f1 -d: ;; + cifs) echo "$SOURCE" | cut -f3 -d/ ;; +esac +} + + +#/** +# ogGetServerIp +#@brief Muestra la dirección IP del Servidor de OpenGnSys. +#@return str_ip - Dirección IP +#@version 0.10 - Integración en OpenGnSys 0.10 +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2011-01-13 +#@version 1.0 - Integración OpenGnSys 0.10 Opengnsys 0.10-testing +#@note Comprobacion segun protocolo de conexion al Repo +#@author Antonio J. Doblas Viso. Universidad de Malaga. +#@date 2011-02-24 +#@version 1.0.6 - Obtener datos del punto de montaje, evitando fallo si $ogprotocol está vacía. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2014-08-27 +#*/ ## +function ogGetServerIp () +{ +# Variables locales. +local SOURCE FSTYPE + +# Mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME" "$FUNCNAME => 192.168.0.2" + return +fi + +# Obtener direcciones IP, según el tipo de montaje. +eval $(findmnt -P -o SOURCE,FSTYPE $OPENGNSYS) +case "$FSTYPE" in + nfs) echo "$SOURCE" | cut -f1 -d: ;; + cifs) echo "$SOURCE" | cut -f3 -d/ ;; +esac +} + + +#/** +# ogMakeGroupDir [ str_repo ] +#@brief Crea el directorio para el grupo del cliente. +#@param str_repo repositorio de imágenes (opcional) +#@return (nada) +#@note repo = { REPO, CACHE } REPO por defecto +#@exception OG_ERR_FORMAT formato incorrecto. +#@version 1.0.5 - Primera versión para OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2013-09-26 +#*/ +function ogMakeGroupDir () +{ +local REPO DIR GROUP +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME str_repo" \ + "$FUNCNAME" "$FUNCNAME REPO" + return +fi +# Error si se recibe más de 1 parámetro. +case $# in + 0) REPO="REPO" ;; + 1) REPO="$1" ;; + *) ogRaiseError $OG_ERR_FORMAT "$*" + return $? ;; +esac +# Comprobar tipo de repositorio. +DIR=$(ogGetPath "$REPO" / 2>/dev/null) +[ -n "$DIR" ] || ogRaiseError $OG_ERR_FORMAT "$1" +GROUP="$(ogGetGroupName)" +if [ -n "$GROUP" ]; then + mkdir -p "$DIR/groups/$GROUP" 2>/dev/null +fi +} + diff --git a/client/lib/engine/bin/NetLib.py b/client/lib/engine/bin/NetLib.py deleted file mode 100755 index e36f863..0000000 --- a/client/lib/engine/bin/NetLib.py +++ /dev/null @@ -1,315 +0,0 @@ -#/** -#@file NetLib.py -#@brief Librería o clase Net -#@class Net -#@brief Funciones básicas de red. -#@warning License: GNU GPLv3+ -#*/ - -import subprocess -import sys -import os -import json -import re - -import ogGlobals -import SystemLib -import FileLib - -def _ogConnect_options(): - ## the original bash code does: eval $(grep "OPTIONS=" /scripts/ogfunctions) - ## this is highly insecure but we need to keep it for now - opt = subprocess.run (['grep', '-o', 'OPTIONS=.*', '/scripts/ogfunctions'], capture_output=True, text=True).stdout.strip() - exec (opt, globals()) - return OPTIONS - -## defined in /scripts/ogfunctions. We can't tackle that yet. -## this is a quick implementation just to unblock development -def _ogConnect (server, protocol, src, dst, options, readonly): - if 'smb' != protocol: return None ## only supported value right now - write_option = ',ro' if readonly else ',rw' - options += write_option - return not subprocess.run (['mount.cifs', f'//{server}/{src}', dst] + options.split()).returncode - - -#/** -# ogChangeRepo IPREPO [ OgUnit ] -#@brief Cambia el repositorio para el recurso remoto images. -#@param 1 Ip Repositorio -#@param 2 Abreviatura Unidad Organizativa -#@return Cambio recurso remoto en OGIMG. -#*/ -def ogChangeRepo(ip_repo, og_unit=None): - ogprotocol = os.environ['ogprotocol'] or 'smb' - - if og_unit: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_GENERIC, 'the og_unit parameter became unsupported') - return None - - try: - mount = subprocess.run (['mount'], capture_output=True, text=True).stdout - ro = bool (list (filter (lambda line: re.search (r'ogimages.*\bro,', line), mount.splitlines()))) - - current_repo = ogGetRepoIp() - new_repo = current_repo if ip_repo.upper() == "REPO" else ip_repo - if new_repo == current_repo: return True - - subprocess.run(["umount", ogGlobals.OGIMG], check=True) - - SystemLib.ogEcho (['session', 'log'], None, f'{ogGlobals.lang.MSG_HELP_ogChangeRepo} {new_repo}') - options = _ogConnect_options() - if not _ogConnect (new_repo, ogprotocol, 'ogimages', ogGlobals.OGIMG, options, ro): - _ogConnect (current_repo, ogprotocol, 'ogimages', ogGlobals.OGIMG, options, ro) - SystemLib.ogRaiseError( - "session", - ogGlobals.OG_ERR_REPO, - f"Error connecting to the new repository: {new_repo}", - ) - return False - - SystemLib.ogEcho( - ["session", "log"], - None, - f"Repository successfully changed to {new_repo}".strip(), - ) - - return True - - except Exception as e: - SystemLib.ogRaiseError( - "session", - ogGlobals.OG_ERR_GENERIC, - f"Error executing ogChangeRepo: {e}", - ) - return None - -#/** -# ogGetGroupDir [ str_repo ] -#@brief Devuelve el camino del directorio para el grupo del cliente. -#@param str_repo repositorio de imágenes (opcional) -#@return path_dir - Camino al directorio del grupo. -#@note repo = { REPO, CACHE } REPO por defecto -#@exception OG_ERR_FORMAT formato incorrecto. -#*/ -def ogGetGroupDir(repo=None): - try: - repo = repo or "REPO" - - group = ogGetGroupName() - if group: - dir_path = FileLib.ogGetPath(repo, f"/groups/{group}") - if dir_path and os.path.isdir(dir_path): - return dir_path - - return None - - except Exception as e: - SystemLib.ogRaiseError( - "session", - ogGlobals.OG_ERR_FORMAT, - f"Error in ogGetGroupDir: {e}" - ) - return None - -#/** -# ogGetGroupName -#@brief Devuelve el nombre del grupo al que pertenece el cliente. -#@return str_group - Nombre de grupo. -#*/ -def ogGetGroupName(): - try: - group = globals().get("group", None) - return group if group else None - except Exception as e: - print(f"Error in ogGetGroupName: {e}") - return None - -#/** -# ogGetHostname -#@brief Muestra el nombre del cliente. -#@return str_host - nombre de máquina -#*/ ## -def ogGetHostname(): -# Tomar nombre de la variable HOSTNAME - host = os.getenv("HOSTNAME", "").strip() - if host: return host - -# Si no, tomar del DHCP, opción host-name /* (comentario para Doxygen) - dhcp_file = "/var/lib/dhcp3/dhclient.leases" - if os.path.exists(dhcp_file): - with open(dhcp_file, "r") as f: - for line in f: - if 'option host-name' in line: - return line.split('"')[1].strip(";") - -# Si no, leer el parámetro del kernel hostname (comentario para Doxygen) */ - cmdline_file = "/proc/cmdline" - if os.path.exists(cmdline_file): - with open(cmdline_file, "r") as f: - for entry in f.read().split(): - if entry.startswith("hostname="): - return entry.split("=")[1].strip() - - -#/** -# ogGetIpAddress -#@brief Muestra la dirección IP del sistema -#@return str_ip - Dirección IP -#@note Usa las variables utilizadas por el initrd "/etc/net-ethX.conf -#*/ ## -def ogGetIpAddress(): - if "IPV4ADDR" in os.environ: - ip = os.environ["IPV4ADDR"] - if '/' in ip: ip = ip.split ('/')[0] - return ip - - extra_args = [] - if "DEVICE" in os.environ: - extra_args = [ "dev", os.environ["DEVICE"] ] - ipas = subprocess.run (['ip', '-json', 'address', 'show', 'up'] + extra_args, capture_output=True, text=True).stdout - - ipasj = json.loads (ipas) - addresses = [] - for e in ipasj: - if 'lo' == e['ifname']: continue - if 'addr_info' not in e: continue - addrs = e['addr_info'] - for a in addrs: - if 'inet' != a['family']: continue - addresses.append ({ 'local': a['local'], 'prefixlen': a['prefixlen'] }) - - if 1 != len (addresses): - raise Exception ('more than one local IP address found') - return addresses[0] - - -#/** -# ogGetMacAddress -#@brief Muestra la dirección Ethernet del cliente. -#@return str_ether - Dirección Ethernet -#*/ ## -def ogGetMacAddress(): - try: - if "DEVICE" in os.environ: - device = os.environ["DEVICE"] - result = subprocess.run( - ["ip", "-o", "link", "show", "up", "dev", device], - capture_output=True, - text=True, - check=True - ).stdout - else: - result = subprocess.run( - ["ip", "-o", "link", "show", "up"], - capture_output=True, - text=True, - check=True - ).stdout - - mac_addresses = [] - for line in result.splitlines(): - if "link/ether" in line: - parts = line.split() - for i, part in enumerate(parts): - if part == "link/ether": - mac_addresses.append(parts[i + 1].upper()) - - if mac_addresses: - print (f'nati: ogGetMacAddress: {mac_addresses[0]}') - return mac_addresses[0] - else: - print("No active mac address found") - return None - - except subprocess.CalledProcessError as e: - print(f"Error executing ip command: {e.stderr}") - return None - except Exception as e: - print(f"Unexpected error: {str(e)}") - return None - -#/** -# ogGetNetInterface -#@brief Muestra la interfaz de red del sistema -#@return str_interface - interfaz de red -#@note Usa las variables utilizadas por el initrd "/etc/net-ethX.conf -#*/ ## -def ogGetNetInterface(): - if len(sys.argv) >= 2 and sys.argv[1] == "help": - SystemLib.ogHelp("ogGetNetInterface", "ogGetNetInterface", "ogGetNetInterface => eth0") - return - - if "DEVICE" in os.environ: - print(os.environ["DEVICE"]) - - return 0 - -#/** -# ogGetRepoIp -#@brief Muestra la dirección IP del repositorio de datos. -#@return str_ip - Dirección IP -#*/ ## -def ogGetRepoIp(): - out = subprocess.run (["findmnt", "--json", "--output", "SOURCE,FSTYPE", ogGlobals.OGIMG], capture_output=True, text=True).stdout - try: - j = json.loads (out) - except json.decoder.JSONDecodeError: - return None - - if 'filesystems' not in j: return None - source = j['filesystems'][0]['source'] - fstype = j['filesystems'][0]['fstype'] - - if 'nfs' == fstype: return source.split(":")[0] - elif 'cifs' == fstype: return source.split("/")[2] - - return None - -#/** -# ogGetServerIp -#@brief Muestra la dirección IP del Servidor de OpenGnSys. -#@return str_ip - Dirección IP -#@note Comprobacion segun protocolo de conexion al Repo -#*/ ## -def ogGetServerIp(): - return os.environ['ogcore'] - -#/** -# ogGetServerPort -#@brief Muestra el puerto del Servidor de OpenGnSys. -#@return str_port - Puerto -#*/ ## -def ogGetServerPort(): - if 'ogcore_port' in os.environ: - return os.environ['ogcore_port'] - else: - return '8443' - - -#/** -# ogMakeGroupDir [ str_repo ] -#@brief Crea el directorio para el grupo del cliente. -#@param str_repo repositorio de imágenes (opcional) -#@return (nada) -#@note repo = { REPO, CACHE } REPO por defecto -#@exception OG_ERR_FORMAT formato incorrecto. -#*/ -def ogMakeGroupDir(): - REPO = "" - DIR = "" - GROUP = "" - - if len(sys.argv) < 2: - SystemLib.ogHelp("ogMakeGroupDir", "ogMakeGroupDir str_repo", "ogMakeGroupDir", "ogMakeGroupDir REPO") - return - - if len(sys.argv) == 1: - REPO = "REPO" - else: - REPO = sys.argv[1] - - DIR = FileLib.ogGetPath(REPO, "/groups/" + ogGetGroupName(), stderr=subprocess.DEVNULL) - if DIR: - subprocess.run(["mkdir", "-p", DIR], stderr=subprocess.DEVNULL) - - return 0 diff --git a/client/lib/engine/bin/PostConf.lib b/client/lib/engine/bin/PostConf.lib new file mode 100755 index 0000000..4fe47b5 --- /dev/null +++ b/client/lib/engine/bin/PostConf.lib @@ -0,0 +1,543 @@ +#!/bin/bash +#/** +#@file PostConf.lib +#@brief Librería o clase PostConf +#@class PostConf +#@brief Funciones para la postconfiguración de sistemas operativos. +#@version 1.1.0 +#@warning License: GNU GPLv3+ +#*/ + + +#/** +# ogCleanOs int_ndisk int_nfilesys +#@brief Elimina los archivos que no son necesarios en el sistema operativo. +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden del sistema de archivos +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@exception OG_ERR_PARTITION Partición desconocida o no accesible. +#@note Antes incluido en la funcion ogReduceFs +#@author Irina Gomez. Universidad de Sevilla. +#@return (nada) +#@date 2014-10-27 +#*/ ## +function ogCleanOs () +{ + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_nfilesys" \ + "$FUNCNAME 1 1" + return +fi + +# Error si no se reciben 2 parámetros. +[ $# == 2 ] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME int_ndisk int_nfilesys" || return $? + +case "$(ogGetOsType $1 $2)" in + Linux) + # Borramos los ficheros de dispositivos y los temporales. + ogCleanLinuxDevices $1 $2 + rm -rf $(ogMount $1 $2)/tmp/* #*/ Comentario Doxygen + ;; + Windows) + # Borrar ficheros de hibernación y paginación de Windows. + [ -n "$(ogGetPath $1 $2 pagefile.sys)" ] && ogDeleteFile $1 $2 pagefile.sys + [ -n "$(ogGetPath $1 $2 hiberfil.sys)" ] && ogDeleteFile $1 $2 hiberfil.sys + [ -n "$(ogGetPath $1 $2 swapfile.sys)" ] && ogDeleteFile $1 $2 swapfile.sys + ;; +esac + +} + + + +#/** +# ogInstallMiniSetup int_ndisk int_npartition str_filename [str_admuser str_admpassword bool_autologin [str_autouser str_autopassword] ] +#@brief Metafunción para instalar archivo que se ejecutará en el arranque de Windows. +#@see ogInstallFirstBoot ogInstallRunonce +#*/ ## +function ogInstallMiniSetup () +{ +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$MSG_SEE ogInstallFirstBoot ogInstallRunonce" + return +fi +case $# in + 3) # Ejecución en el primer arranque de la máquina. + ogInstallFirstBoot "$@" ;; + 6|8) # Ejecución en el "runonce". + ogInstallRunonce "$@" ;; + *) ogRaiseError $OG_ERR_FORMAT + return $? ;; +esac +} + + +#/** +# ogInstallFirstBoot int_ndisk int_npartition str_filename +#@brief Crea unas claves del registro y el archivo cmd que se ejecutara en el primer arranque estando la maquina en un estado bloqueado +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@param str_filename nombre del archivo .cmd a ejecutar en el arranque +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@note El archivo estará en system32 y será visible por el sistema. +#@version 1.0.2 - Nueva función +#@author Jonathan Alonso Martinez - Universidad Autonoma de Barcelona +#@date 2011-06-29 +#@version 1.0.4 - Heredada de antigua función ogInstallMiniSetup. +#@author Jonathan Alonso Martinez - Universidad Autonoma de Barcelona +#@date 2012-04-16 +#*/ ## +function ogInstallFirstBoot () +{ +local MNTDIR DIR CMDDIR CMDFILE +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_npartition str_filename" \ + "$FUNCNAME 1 1 filename.cmd" + return +fi +# Error si no se reciben 3 parámetros. +[ $# == 3 ] || return $(ogRaiseError $OG_ERR_FORMAT; echo $?) +# Comprobar que existe el directorio del fichero de comandos. +MNTDIR=$(ogMount "$1" "$2") || return $? +for i in winnt windows; do + DIR=$(ogGetPath $MNTDIR/$i/system32) + [ -n "$DIR" ] && CMDDIR=$DIR +done +[ -n "$CMDDIR" ] || ogRaiseError $OG_ERR_NOTFOUND "$MNTDIR/windows/system32" || return $? +CMDFILE="$CMDDIR/$3" + +# Creamos el archivo cmd y creamos un par de comandos para que una vez acabe la +# postconfiguracion resetee el mini setup, sino lo haria en cada arranque. +cat > "$CMDFILE" << EOF +REG ADD HKLM\System\Setup /v SystemSetupInProgress /t REG_DWORD /d 0 /f +REG ADD HKLM\System\Setup /v CmdLine /t REG_SZ /d "" /f +EOF + +# Crear los valores de registro necesarios para que se haga la ejecución del .cmd al aranque. +ogSetRegistryValue "$MNTDIR" SYSTEM "\Setup\SystemSetupInProgress" 1 +ogSetRegistryValue "$MNTDIR" SYSTEM "\Setup\SetupType" 4 +#ogDeleteRegistryValue "$MNTDIR" SYSTEM "\Setup\CmdLine" +ogAddRegistryValue "$MNTDIR" SYSTEM "\Setup\CmdLine" +ogSetRegistryValue "$MNTDIR" SYSTEM "\Setup\CmdLine" "cmd.exe /c $(basename $CMDFILE)" +} + + +#/** +# ogInstallRunonce int_ndisk int_npartition str_filename str_adm_user str_adm_password bool_autologin [str_auto_user str_auto_password] +#@brief Crea el archivo cmd que se ejecutara en el runonce de un usuario administrador +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@param str_filename nombre del archivo .cmd a ejecutar en el arranque (estara en system32 y sera visible por el sistema) +#@param str_adm_user usuario administrador para hacer autologin y ejecutar el runonce +#@param str_adm_password password del usuario administrador +#@param bool_autologin si despues de la postconfiguracion queremos que la maquina haga autologin (0 o 1) +#@param str_auto_user Usuario con el que queremos que haga autologin despues de la postconfiguracion +#@param str_auto_password Password del usuario que hara autologin +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@version 1.0.2 - Nueva función +#@author Jonathan Alonso Martinez - Universidad Autonoma de Barcelona +#@date 2011-06-29 +#@version 1.0.4 - Heredado de antigua función ogInstallMiniSetup +#@author Jonathan Alonso Martinez - Universidad Autonoma de Barcelona +#@date 2012-04-16 +#@version 1.1.0 - Resuelve problemas a partir de Windows 10 +#@author Carmelo Cabezuelo Aguilar - Universidad Politécnica de Valencia +#@date 2018-02-20 +#*/ ## +function ogInstallRunonce () +{ +local MOUNTPOINT DIR CMDDIR CMDFILE +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_npartition str_filename str_adm_user str_adm_password bool_autologin [str_auto_user str_auto_password]" \ + "$FUNCNAME 1 1 filename.cmd administrator passadmin 1 userauto passuserauto" \ + "$FUNCNAME 1 1 filename.cmd administrator passadmin 0" + return +fi +# Error si no se reciben 6 u 8 parámetros. +[ $# == 6 -o $# == 8 ] || return $(ogRaiseError $OG_ERR_FORMAT; echo $?) +# Punto de montaje. +MOUNTPOINT="$(ogGetPath "$1" "$2" /)" +# Comprobar que existe el directorio del fichero de comandos. +for i in winnt windows; do + DIR=$(ogGetPath $MOUNTPOINT/$i/system32) + [ -n "$DIR" ] && CMDDIR=$DIR +done +[ -n "$CMDDIR" ] || ogRaiseError $OG_ERR_NOTFOUND "$MOUNTPOINT/Windows/System32" || return $? +CMDFILE="$CMDDIR/$3" + +if [ $6 == 0 ]; then + # Si no queremos hacer autologin despues de la postconfiguracion lo indicamos en las claves de registro + cat > "$CMDFILE" << EOF +DEL C:\ogboot.* +REG ADD "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v AutoAdminLogon /t REG_SZ /d 0 /f +REG ADD "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultUserName /t REG_SZ /d "" /f +REG DELETE "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultPassword /f +EOF +else + # Si queremos hacer autologin despues de la postconfiguracion introducimos la informacion en las claves de registro + cat > "$CMDFILE" << EOF +DEL C:\ogboot.* +REG ADD "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v AutoAdminLogon /t REG_SZ /d 1 /f +REG ADD "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultUserName /t REG_SZ /d "$7" /f +REG ADD "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultPassword /t REG_SZ /d "$8" /f +EOF +fi +#Creamos las claves de registro necesarias para que meter el cmd en el runonce del usuario y este haga autologin +ogAddRegistryValue $MOUNTPOINT software '\Microsoft\Windows\CurrentVersion\RunOnce\PostConfiguracion' 2>/dev/null +ogSetRegistryValue $MOUNTPOINT software '\Microsoft\Windows\CurrentVersion\RunOnce\PostConfiguracion' "C:\windows\system32\\$3" 2>/dev/null +ogAddRegistryValue $MOUNTPOINT software '\Microsoft\Windows NT\CurrentVersion\Winlogon\AutoAdminLogon' 2>/dev/null +ogSetRegistryValue $MOUNTPOINT software '\Microsoft\Windows NT\CurrentVersion\Winlogon\AutoAdminLogon' 1 2>/dev/null +ogAddRegistryValue $MOUNTPOINT software '\Microsoft\Windows NT\CurrentVersion\Winlogon\DefaultUserName' 2>/dev/null +ogSetRegistryValue $MOUNTPOINT software '\Microsoft\Windows NT\CurrentVersion\Winlogon\DefaultUserName' "$4" 2>/dev/null +ogAddRegistryValue $MOUNTPOINT software '\Microsoft\Windows NT\CurrentVersion\Winlogon\DefaultDomainName' 2>/dev/null +ogSetRegistryValue $MOUNTPOINT software '\Microsoft\Windows NT\CurrentVersion\Winlogon\DefaultDomainName' ".\\" 2>/dev/null +ogAddRegistryValue $MOUNTPOINT software '\Microsoft\Windows NT\CurrentVersion\Winlogon\DefaultPassword' 2>/dev/null +ogSetRegistryValue $MOUNTPOINT software '\Microsoft\Windows NT\CurrentVersion\Winlogon\DefaultPassword' "$5" 2>/dev/null +ogDeleteRegistryValue $MOUNTPOINT software '\Microsoft\Windows NT\CurrentVersion\Winlogon\ForceAutoLockOnLogon' 2>/dev/null +ogDeleteRegistryValue $MOUNTPOINT software '\Microsoft\Windows NT\CurrentVersion\Winlogon\AutoLogonCount' 2>/dev/null +} + +#/** +# ogAddCmd int_ndisk int_npartition str_filename str_commands +#@brief Añade comandos al cmd creado por ogInstalMiniSetup +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@param str_filename nombre del fichero cmd (siempre se guardara en windows\system32\para que sea visible por el sistema +#@param str_commands comando o comandos que se añadiran al fichero +#@return +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. +#@version 1.0.2 - Nueva función +#@author Jonathan Alonso Martinez - Universidad Autonoma de Barcelona +#@date 2011-06-29 +#@version 1.0.4 - Cambios en los parametros de entrada de la funcion +#@author Jonathan Alonso Martinez - Universidad Autonoma de Barcelona +#@date 2012-04-16 +#*/ ## +function ogAddCmd () +{ +local MOUNTPOINT CMDFILE +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_npartition str_filename str_commands" \ + "$FUNCNAME 1 1 filename.cmd command" + return +fi +# Error si no se reciben 4 parámetros. +[ $# == 4 ] || return $(ogRaiseError $OG_ERR_FORMAT; echo $?) +# Punto de montaje +MOUNTPOINT="$(ogMount "$1" "$2")" || return $? +# Crear fichero de comandos, si no existe. +CMDFILE="$(ogGetPath "$MOUNTPOINT/windows/system32")/$3" +[ -n "$CMDFILE" ] || ogInstallMiniSetup "$1" "$2" "$3" +[ -n "$CMDFILE" ] || ogRaiseError $OG_ERR_NOTFOUND "$MOUNTPOINT/windows/system32/$3" || return $? + +# Concatenamos el comando en el fichero de comandos +cat >> "$CMDFILE" << EOF +$4 +EOF +} + + +#/** +# ogDomainScript int_ndisk int_npartition str_domain str_user str_password +#@brief Crea un script .vbs para unir al dominio una maquina windows y el comando adequado en el archivo cmd creado por ogInstallMiniSetup +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@param str_filename nombre del fichero cmd donde deberemos introducir el comando de ejecutar el script vbs +#@param str_domain dominio donde se quiere conectar +#@param str_user usuario con privilegios para unir al dominio +#@param str_password password del usuario con privilegios +#@return +#@exception OG_ERR_FORMAT Formato incorrecto. +#@version 1.0.2 - Nueva función +#@author Jonathan Alonso Martinez - Universidad Autonoma de Barcelona +#@date 2011-06-29 +#@version 1.0.4 - Cambios en los parametros de entrada de la funcion +#@author Jonathan Alonso Martinez - Universidad Autonoma de Barcelona +#@date 2012-04-16 +#*/ ## +function ogDomainScript () +{ +local CMDDIR +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" \ + "$FUNCNAME int_ndisk int_npartition str_filename str_domain str_user str_password" \ + "$FUNCNAME 1 1 filename.cmd domain user password_user" + return +fi +# Error si no se reciben 6 parámetros. +[ $# == 6 ] || return $(ogRaiseError $OG_ERR_FORMAT; echo $?) +# Punto de montaje +MOUNTPOINT="$(ogMount "$1" "$2")" || return $? +# Comprobar que existe el directorio de comandos. +CMDDIR=$(ogGetPath "$MOUNTPOINT/windows/system32") +[ -n "$CMDDIR" ] || ogRaiseError $OG_ERR_NOTFOUND "$1/windows/system32" || return $? + +# Añadimos en el cmd que se ejecutara al arranque, el comando de ejecutar el script que añade al dominio. +ogAddCmd $1 $2 "$3" "CSCRIPT joindomain.vbs" +# Eliminamos el script porque tiene el usuario de administrador de dominio en claro +ogAddCmd $1 $2 "$3" "DEL /Q C:\Windows\System32\joindomain.vbs" +# Metemos unas claves de registro para que el dominio salga seleccionado por defecto +ogAddCmd $1 $2 "$3" "REG ADD \"HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\" /v DefaultDomainName /t REG_SZ /d \"$4\" /f" + +# Creamos el archivo joindomain.vbs que nos introduce la maquina en el dominio +cat > "$CMDDIR/joindomain.vbs" << EOF +Const JOIN_DOMAIN = 1 +Const ACCT_CREATE = 2 +Const ACCT_DELETE = 4 +Const WIN9X_UPGRADE = 16 +Const DOMAIN_JOIN_IF_JOINED = 32 +Const JOIN_UNSECURE = 64 +Const MACHINE_PASSWORD_PASSED = 128 +Const DEFERRED_SPN_SET = 256 +Const INSTALL_INVOCATION = 262144 + +strDomain = "$4" +strUser = "$5" +strPassword = "$6" + +Set objNetwork = CreateObject("WScript.Network") +strComputer = objNetwork.ComputerName + +Set objComputer = GetObject("winmgmts:{impersonationLevel=Impersonate}!\\\" & _ + strComputer & "\root\cimv2:Win32_ComputerSystem.Name='" & strComputer & "'") + +ReturnValue = objComputer.JoinDomainOrWorkGroup(strDomain, strPassword, _ + strDomain & "\" & strUser, NULL, JOIN_DOMAIN + ACCT_CREATE) +EOF + +#*/ " (comentario Doxygen) + + +} + + +### PRUEBAS. + +#/** +# ogConfigureOgagent int_ndisk int_filesys +#@brief Modifica el fichero de configuración del nuevo agente OGAent para sistemas operativos. +#@param int_ndisk nº de orden del disco +#@param int_filesys nº de orden del sistema de archivos +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Fichero o dispositivo no encontrado. +#@exception OG_ERR_LOCKED Sistema de archivos bloqueado. +#@version 1.1.0 - Primera adaptación para OpenGnsys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2016-07-15 +#*/ ## +function ogConfigureOgagent () +{ +# Variables locales. +local MNTDIR AGENTDIR CFGFILE +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_filesys" \ + "$FUNCNAME 1 1" + return +fi + +# Error si no se reciben 2 parámetros. +[ $# == 2 ] || ogRaiseError $OG_ERR_FORMAT || return $? +# Obtener sistema de archvios. +MNTDIR=$(ogMount $1 $2) || return $? + +# Comprobar si existe el fichero de configuración de OGAgent. +for AGENTDIR in usr/share/OGAgent "Program Files/OGAgent" "Program Files (x86)/OGAgent" Applications/OGAgent.app; do + CFGFILE=$(ogGetPath "$MNTDIR/$AGENTDIR/cfg/ogagent.cfg") + [ -n "$CFGFILE" ] && break +done +[ -n "$CFGFILE" ] || ogRaiseError $OG_ERR_NOTFOUND "ogagent.cfg" || return $? +# Parchear dirección del servidor OpenGnsys en el fichero de configuración de OGAgent. +sed -i "0,/remote=/ s,remote=.*,remote=https://$(ogGetServerIp):8443/opengnsys/rest/," "$CFGFILE" +} + + +#/** +# ogInstallLaunchDaemon int_ndisk int_nfilesys str_filename +#@brief Instala archivo que se ejecutará en el arranque de macOS. +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden del sistema de archivos +#@param str_filename nombre del script +#return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Fichero o directorio no encontrado. +#@npte Crea ficheros de configuración /Library/LaunchDaemon/es.opengnsys.Script.plist. +#@version 1.0.6 - Primera versión para OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2014-10-06 +#*/ ## +function ogInstallLaunchDaemon () +{ +# Variables locales. +local LAUNCHDIR SCRIPTDIR +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_filesys str_scriptname" \ + "$FUNCNAME 1 2 postconf" + return +fi + +# Error si no se reciben 3 parámetros. +[ $# == 3 ] || ogRaiseError $OG_ERR_FORMAT || return $? +# Comprobar directorios. +LAUNCHDIR=$(ogGetPath $1 $2 /Library/LaunchDaemons) +[ -n "$LAUNCHDIR" ] || ogRaiseError $OG_ERR_NOTFOUND "$1 $2 /Library/LaunchDaemons" || return $? +SCRIPTDIR=$(ogGetPath $1 $2 /usr/share) +[ -n "$SCRIPTDIR" ] || ogRaiseError $OG_ERR_NOTFOUND "$1 $2 /usr/share" || return $? + +# Crear fichero de configuración del servicio de arranque. +cat << EOT $LAUNCHDIR/es.opengnsys.$3.plist + + + + Label + es.opengnsys.$3 + ProgramArguments + + $SCRIPTDIR/$3.sh + + RunAtLoad + + StandardOutPath + /var/log/$3.log + StandardErrorPath + /var/log/$3.err + + + +EOT + +# Crear un fichero de script vacío. +rm -f $SCRIPTDIR/$3.sh +touch $SCRIPTDIR/$3.sh +chmod +x $SCRIPTDIR/$3.sh +} + + +### PRUEBAS. + +#/** +# ogAddToLaunchDaemon int_ndisk int_nfilesys str_filename str_commands +#@brief Añade comandos al script creado por ogInstalLaunchDaemon. +#@param int_ndisk nº de orden del disco +#@param int_nfilesys nº de orden del sistema de archivos +#@param str_filename nombre del script (siempre se guardará en /usr/share para que sea visible por el sistema +#@param str_commands comando o comandos que se añadiran al fichero +#return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Fichero o directorio no encontrado. +#@version 1.0.6 - Primera versión para OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2014-10-06 +#*/ ## +function ogAddToLaunchDaemon () +{ +# Variables locales. +local SCRIPTFILE +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_filesys str_scriptname" \ + "$FUNCNAME 1 2 postconf \"diskutil enableJournal disk0s2\"" + return +fi + +# Error si no se reciben 4 parámetros. +[ $# == 4 ] || ogRaiseError $OG_ERR_FORMAT || return $? +# Comprobar que existe el fichero de comandos. +SCRIPTFILE=$(ogGetPath $1 $2 "/usr/share/$3.sh") +[ -n "$SCRIPTFILE" ] || ogRaiseError $OG_ERR_NOTFOUND "$1 $2 /usr/share/$3" || return $? + +# Concatenamos el comando en el fichero de comandos +cat >> "$SCRIPTFILE" << EOT +$4 +EOT +} + + +#/** +# ogUninstallLinuxClient int_ndisk int_filesys +#@brief Desinstala el cliente OpenGnSys para sistemas operativos GNU/Linux. +#@param int_ndisk nº de orden del disco +#@param int_filesys nº de orden del sistema de archivos +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_PARTITION Paritición o sistema de archivos incorrectos. +#@exception OG_ERR_LOCKED Sistema de archivos bloqueado. +#@version 1.1.0 - Primera adaptación para OpenGnsys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2016-08-22 +#*/ ## +function ogUninstallLinuxClient () +{ +# Variables locales. +local MNTDIR +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_filesys" \ + "$FUNCNAME 1 1" + return +fi + +# Error si no se reciben 2 parámetros. +[ $# == 2 ] || ogRaiseError $OG_ERR_FORMAT || return $? +# Obtener sistema de archvios. +MNTDIR=$(ogMount $1 $2) || return $? + +# Borrar ficheros y quitar llamada al cliente durante el proceso de inicio. +rm -f $MNTDIR/{usr/sbin,sbin,usr/local/sbin}/ogAdmLnxClient +rm -f $MNTDIR/{etc,usr/local/etc}/ogAdmLnxClient.cfg +sed -i -e '/ogAdmLnxClient/ d' $MNTDIR/{etc,usr/local/etc}/{rc.local,rc.d/rc.local} 2>/dev/null +} + + +#/** +# ogUninstallWindowsClient int_ndisk int_filesys str_filename +#@brief Desinstala el cliente OpenGnSys para sistemas operativos Windows. +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@param str_filename nombre del fichero cmd donde deberemos introducir el comando de ejecutar el script vbs +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_PARTITION Paritición o sistema de archivos incorrectos. +#@exception OG_ERR_LOCKED Sistema de archivos bloqueado. +#@version 1.1.0 - Primera adaptación para OpenGnsys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2016-08-22 +#*/ ## + +function ogUninstallWindowsClient () +{ +# Variables locales. +local MNTDIR +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_filesys str_filename" \ + "$FUNCNAME 1 1 filename.cmd" + return +fi + +# Error si no se reciben 3 parámetros. +[ $# == 3 ] || ogRaiseError $OG_ERR_FORMAT || return $? +# Obtener sistema de archvios. +MNTDIR=$(ogMount "$1" "$2") || return $? + +# Crear órdenes para desinstalar servicio y borrar ejecutable del cliente. +if [ -n "$(ogGetPath $MNTDIR/windows/ogAdmWinClient.exe)" -o -n "$(ogGetPath $MNTDIR/winnt/ogAdmWinClient.exe)" ]; then + ogAddCmd $1 $2 "$3" 'ogAdmWinClient -remove' + ogAddCmd $1 $2 "$3" 'DEL C:\Windows\ogAdmWinClient.exe' + ogAddCmd $1 $2 "$3" 'DEL C:\Winnt\ogAdmWinClient.exe' +fi +} + diff --git a/client/lib/engine/bin/PostConfEAC.lib b/client/lib/engine/bin/PostConfEAC.lib new file mode 100755 index 0000000..d34864d --- /dev/null +++ b/client/lib/engine/bin/PostConfEAC.lib @@ -0,0 +1,699 @@ +#!/bin/bash + +# ogLoadHiveWindows int_ndisk int_partiton +#@brief Localiza los hive del registro de windows (de sistema y usuarios) +#@param int_ndisk nº de orden del disco +#@param int_partition nº de particion +#@return +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. +#@version 0.9 - Adaptación a OpenGNSys. +#@author Antonio J. Doblas Viso. Universidad de Málaga +#@date 2009-09-24 +#*/ ## + + +function ogLoadHiveWindows () { +# Variables locales. +local PART DISK + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_partition" \ + "$FUNCNAME 1 1 " + return +fi + +# Error si no se reciben 2 parámetros. +[ $# == 2 ] || return $(ogRaiseError $OG_ERR_FORMAT; echo $?) + +DISK=$1; PART=$2; + +#Comprobaciones redundantes: borrar" +#ogDiskToDev $DISK $PART || return $(ogRaiseError $OG_ERR_PARTITION "particion de windows no detectada"; echo $?) +#ogGetOsType $DISK $PART | grep "Windows" || return $(ogRaiseError $OG_ERR_NOTOS "no es windows"; echo $?) +#VERSION=$(ogGetOsVersion $DISK $PART) +#Fin Comprobaciones redundantes: borrar" + + +# primera fase, carga de los hive del sistema +if ogGetPath $DISK $PART WINDOWS +then + SYSTEMROOT="Windows" +elif ogGetPath $DISK $PART WINNT +then + SYSTEMROOT="winnt" +else + return $(ogRaiseError $OG_ERR_NOTOS "version windows no detectada"; echo $?) +fi + +hiveSAM=$(ogGetPath $DISK $PART /${SYSTEMROOT}/system32/config/SAM) +[ -n "$hiveSAM" ] && export hiveSAM || return $(ogRaiseError $OG_ERR_NOTOS " hive SAM no detectada"; echo $?) +hiveSYSTEM=$(ogGetPath $DISK $PART /${SYSTEMROOT}/system32/config/system) +[ -n "$hiveSYSTEM" ] && export hiveSYSTEM || return $(ogRaiseError $OG_ERR_NOTOS "hive SYSTEM no detectada"; echo $?) +hiveSOFTWARE=$(ogGetPath $DISK $PART /${SYSTEMROOT}/system32/config/software) +[ -n "$hiveSOFTWARE" ] && export hiveSOFTWARE || return $(ogRaiseError $OG_ERR_NOTOS "hive SOFTWARE no detectada"; echo $?) +export TEMPhive=/tmp/tmpregistry + +# segunda fase, carga de los hive de usuarios windows. +declare -i COUNT +COUNT=3 +#TODO WINDOWS XP WINDOWS7 +BASEHOMEDIR=$(ogGetPath $DISK $PART /"Documents and Settings") +TMPUSERFILE="/tmp/WuserRegAndDAT.tmp" +find "$BASEHOMEDIR/" -type f -name NTUSER.DAT > $TMPUSERFILE +LISTUSERS=$(drbl-chntpw -l $hiveSAM | grep RID | awk -F"<" '{print $2}' | awk -F">" '{print $1}') +#echo "$BASEHOMEDIR" $LISTUSERS +for user in $LISTUSERS +do + # Comprobamos que el usuario registrado tiene .DAT + if HOMEDIR=$(cat $TMPUSERFILE | grep -w $user) + then + #echo "$user exportamos los usuarios de windows como variables, y como valor hiveUSERX; donde la X es 3 4 5 6 ... X" + export `echo $user=hiveUSER$COUNT` + #echo "$user exportamos la variable hiveUSERX con el valor del home de la variable-usuario_windows" + ##export `echo hiveUSER$COUNT`="$(echo $HOMEDIR | sed -e 's/ /\\ /'g | sed -e 's/\\/\\\\/g')" + export `echo hiveUSER$COUNT`="$(echo $HOMEDIR)" + #echo " estas variables \$USUARIO -> Identificador del HIVE ; \${!USUARIO} -> path del HIVE " + COUNT=${COUNT}+1 + fi + +done +COUNT=0 +} + + +# ogUpdateHiveWindows +#@brief Actualiza los hive de windows. +#@param int_ndisk +#@param int_partition +#@return +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. +#@version 0.9 - Adaptación a OpenGNSys. +#@author Antonio J. Doblas Viso. Universidad de Málaga +#@date 2009-09-24 +#*/ ## + + +function ogUpdateHiveWindows (){ +# Variables locales. +local PART DISK FILE + +#TODO detectar llamada a ogLoadHiveWindows + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME " \ + "$FUNCNAME " + return +fi + +echo drbl-chntpw -f $TEMPhive $hiveSAM $hiveSYSTEM $hiveSOFTWARE \"${hiveUSER3}\" \"${hiveUSER4}\" \"${hiveUSER5}\" \"${hiveUSER6}\" \"${hiveUSER7}\" \"${hiveUSER8}\" \"${hiveUSER9}\" > /tmp/run.sh +cat /tmp/run.sh; sh /tmp/run.sh; rm -fr $TEMPhive; rm /tmp/run.sh + +unset hiveSAM hiveSYSTEM hiveSOFTWARE TEMPhive hiveUSER3 hiveUSER4 hiveUSER5 hiveUSER6 hiveUSER7 hiveUSER8 hiveUSER9 + + +} + + + +function ogHiveNTRunMachine () { +#echo sintaxis: PathScripts idScripts +#echo ejemplo: c:\\\\WINDOSWS\\\\crearusuarios.bat scripts1 +#echo IMPORTANTE: el path debe llevar dos barras \\, pero como se deben 'escapar' debes poner cuatro \\\\ +#echo "identifica 0=$hiveSAM 1=$hiveSystem 2=$hiveSoftware 3=$HiveUser3" + +local PART DISK FILE + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME PathScripts|command keyName " \ + "$FUNCNAME c:\\\\Windows\\\\crearusuarios.cmd scripts_crearUsuarios "\ + "$FUNCNAME "cmd /c del c:\ogboot.*" ogcleanboot "\ + "$FUNCNAME Requiere la previa ejecución de ogLoadHive int_disk int_part"\ + "$FUNCNAME Despues requiere el ogUpdateHive" + return +fi + + +# Error si no se reciben al menos 1 parámetros. +[ $# == 2 ] || return $(ogRaiseError $OG_ERR_FORMAT; echo $?) + + +cat >> $TEMPhive << EOF +h 2 +cd \Microsoft\Windows\CurrentVersion\Run +nv 1 $2 +ed $2 +$1 +EOF +#ogGetRegistryValue /mnt/sda1 software '\Microsoft\Windows\CurrentVersion\Run\og3' +} + +function ogNTPolUserOn () { + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME id_hive_user " \ + "$FUNCNAME NombreUsuario"\ + "$FUNCNAME " + return +fi + +# TODO: error si no se ha llamado previamente a ogLoadHiveWindows +[ -n $hiveSAM ] || return $(ogRaiseError $OG_ERR_FORMAT "se debe utilizar primero la utilidad ogLoadHiveWindows"; echo $?) + +# TODO: error si el usuario no tiene cuenta en windows. +drbl-chntpw -l $hiveSAM | grep RID | grep -w $1 || return $(ogRaiseError $OG_ERR_FORMAT "el usuario $1 no tiene cuenta en este windows: Compruebe mayusculas o minusculas"; echo $?) + +# TODO: error si no el usario no no tiene HIVE asociado. +[ -n "${!1}" ] || return $(ogRaiseError $OG_ERR_FORMAT "el usuario no tiene hive creado"; echo $?) + + +HIVEID=$(echo ${!1} | tr -d "hiveUSER") + + +#echo "IMPORTANTE: la variable HiveUser3=/mnt/windows/Document/\ and/\ Seeting\alumnmos\NTUSER.dat" +echo $HIVEID +#cp /var/EAC/admin/utilswin/Fondo.BMP ${particion}/WINDOWS/ + +cat >> $TEMPhive << EOF +h $HIVEID +cd \Control Panel\Desktop +ed Wallpaper +C:\\WINDOWS\\fondo.bmp + +cd \Software\Microsoft\Windows\CurrentVersion\Policies +nk Explorer +cd Explorer + +nv 4 NoDesktop +ed NoDesktop +1 + +nv 4 NoSimpleStartMenu +ed NoSimpleStartMenu +1 +nv 4 NoWindowsUpdate +ed NoWindowsUpdate +1 + +nv 4 NoSMConfigurePrograms +ed NoSMConfigurePrograms +1 + +nv 4 NoChangeStartMenu +ed NoChangeStartMenu +1 + +nv 4 Intellimenus +ed Intellimenus +1 + +nv 4 NoRun +ed NoRun +1 + +nv 4 NoRecentDocsHistory +ed NoRecentDocsHistory +1 +EOF +} + + + + + +########################################################## +########################################################## +#####librerias de PostConfiguracion v0.1para Advanced Deploy enViorenment########### +# Liberado bajo licencia GPL ################ +############# 2008 Antonio Jes�s Doblas Viso adv@uma.es ########################## +########### Universidad de Malaga (Spain)############################ +########################################################## + + + + + +function NTChangeName () { +if [ $# = 0 ] +then +echo sintaxis: NTChangeNAME str_$var +echo ejemplos: NTCHangeName adi${IPcuatro}-xp +fi +cat >> $temporal << EOF +h 1 +ed ControlSet001\Control\ComputerName\ComputerName\ComputerName +$1 +ed ControlSet001\Services\Tcpip\Parameters\Hostname +$1 +ed ControlSet001\Services\Tcpip\Parameters\NV Hostname +$1 +h 2 +cd \Microsoft\Windows NT\CurrentVersion\Winlogon +ed DefaultDomainName +$1 +EOF +} + + + +function NTSetGroupName () { +if [ $# = 0 ] +then +echo sintaxis: NTSetGroupName str_$var +echo ejemplos: NTSetGroupName adi +fi +cat >> $temporal << EOF +h 2 +ed \Microsoft\Windows NT\CurrentVersion\Winlogon\DefaultDomainName +$1 +EOF +} + + +function NTSetOwner (){ +if [ $# = 0 ] +then +echo sintaxis: NtSetOwner str_propietario str_organizacion +echo ejemplos: NTSetOwner eu\ politecnica universidad\ de\ malaga +fi +cat >> $temporal << EOF +h 2 +ed \Microsoft\Windows NT\CurrentVersion\RegisteredOwner +$1 +ed \Microsoft\Windows NT\CurrentVersion\RegisteredOrganization +$2 +EOF +} + + +function NTAutoLogon (){ +if [ $# = 0 ] +then +echo sintaxis: Int_Activar Int_nves str_usuario str_passwd str_equipo +echo ejemplos: 1 2 administrador 3451 $equipo +echo IMPORTANTE: cuando AutoLogonCount llegue a 0, activa el AutoAdminLogon a 0. Pero no borra los valores de DefaultPassword +return 2 +fi +#echo la pass es $4 +export temporal=/tmp/tmpregistry +cat >> $temporal << EOF +hive 2 +cd \Microsoft\Windows NT\CurrentVersion\Winlogon +nv 1 AutoAdminLogon +ed AutoAdminLogon +$1 +nv 1 AutoLogonCount +ed AutoLogonCount +$2 +nv 1 DefaultUserName +ed DefaultUserName +$3 +nv 1 DefaultDomainName +ed DefaultDomainName +$5 +EOF +if [ "$4" == none ] +then +echo "debe aparecer done" $4 +cat >> $temporal << EOF +dv DefaultPassword + + +EOF +else +cat >> $temporal << EOF +nv 1 DefaultPassword +ed DefaultPassword +$4 +EOF +fi +} + +function NTStatusRatonTeclado (){ +if [ $# = 0 ] +then +echo sintaxis: Int-StatusRaton Int-StatusTeclado +echo ejemplos: int=1 activo int=4 desactivado +return 2 +fi +cat >> $temporal << EOF +hive 1 +cd \ControlSet001\Services\Mouclass +ed Start +$1 +cd \ControlSet001\Services\Kbdclass +ed Start +$2 +EOF +} + +function NTRunOnceMachine () { +if [ $# = 0 ] +then +echo sintaxis: PathScripts idScripts +echo "ejemplo: c:\\\\WINDOSWS\\\\crearusuarios.bat scripts1" +echo "IMPORTANTE: el path debe llevar dos barras \\, pero como se deben 'escapar' debes poner cuatro \\\\" +return 2 +fi +export temporal=/tmp/tmpregistry +cat >> $temporal << EOF +h 2 +cd \Microsoft\Windows\CurrentVersion\RunOnce +nv 1 $2 +ed $2 +$1 +EOF +} + +function NTRunMachine () { +if [ $# = 0 ] +then +echo sintaxis: PathScripts idScripts +echo ejemplo: c:\\\\WINDOSWS\\\\crearusuarios.bat scripts1 +echo IMPORTANTE: el path debe llevar dos barras \\, pero como se deben 'escapar' debes poner cuatro \\\\ +return 2 +fi +export temporal=/tmp/tmpregistry +cat >> $temporal << EOF +h 2 +cd \Microsoft\Windows\CurrentVersion\Run +nv 1 $2 +ed $2 +$1 +EOF +} + +function NTRunUser () { +if [ $# = 0 ] +then +echo sintaxis: str_PathWINScripts str_idScripts Int_hive||\$usuario +echo ejemplo: c:\\\\WINDOSWS\\\\crearusuarios.bat scripts1 3 +echo IMPORTANTE: el pathWIN debe llevar dos barras \\, pero como se deben 'escapar' debes poner cuatro \\\\ +echo IMPORTANTE: el pathLinux si lleva espacios debe escaparse con una barra \\ +echo IMPORTANTE Int_hive: 3 para el primer usuario, 4 para el segundo usuario +echo requiere export un HiveUser3=/mnt/windows/Document\ and\ Seeting\alumnmos\NTUSER.dat +return 2 +fi +cat >> $temporal << EOF +h $3 +cd \Software\Microsoft\Windows\CurrentVersion\Run +nv 1 $2 +ed $2 +$1 +EOF +} + + + +function NTPolUserOn () { +if [ $# = 0 ] +then +Msg "requiere LoadRegistryUser str_user1 str_user2..." orange +echo "sintaxis: Int_hive" +echo "ejemplo: NTPolUserOn 3" +echo "IMPORTANTE: la variable HiveUser3=/mnt/windows/Document/\ and/\ Seeting\alumnmos\NTUSER.dat" +return 2 +fi +cp /var/EAC/admin/utilswin/Fondo.BMP ${particion}/WINDOWS/ +cat >> $temporal << EOF +h $1 +cd \Control Panel\Desktop +ed Wallpaper +C:\\WINDOWS\\fondo.bmp + +cd \Software\Microsoft\Windows\CurrentVersion\Policies +nk Explorer +cd Explorer + +nv 4 NoDesktop +ed NoDesktop +1 + +nv 4 NoSimpleStartMenu +ed NoSimpleStartMenu +1 +nv 4 NoWindowsUpdate +ed NoWindowsUpdate +1 + +nv 4 NoSMConfigurePrograms +ed NoSMConfigurePrograms +1 + +nv 4 NoChangeStartMenu +ed NoChangeStartMenu +1 + +nv 4 Intellimenus +ed Intellimenus +1 + +nv 4 NoRun +ed NoRun +1 + +nv 4 NoRecentDocsHistory +ed NoRecentDocsHistory +1 +EOF +} + +function NTPolUserOFF () { +if [ $# = 0 ] +then +Msg "requiere LoadRegistryUser str_user1 str_user2..." orange +echo "sintaxis: Int_hive" +echo "ejemplo: NTPolUserOFF 3" +echo "IMPORTANTE: la variable HiveUser3=/mnt/windows/Document/\ and/\ Seeting\alumnmos\NTUSER.dat" +return 2 +fi +cat >> $temporal << EOF +h $1 +cd \Control Panel\Desktop +ed Wallpaper +C:\\WINDOWS\\web\\wallpaper\\Felicidad.bmp + +cd \Software\Microsoft\Windows\CurrentVersion\ +rdel Policies +nk Policies +1 +EOF +} + + +function ogSetWindowsChkdisk() { +if [ $# = 0 ] +then +echo sintaxis: true|TRUE|0 false|false|1 +echo ejemplos: int=0 desactivado int=1 activado +return 2 +fi +case $1 in + 0|true|TRUE) + valor="autocheck autochk *";; + 1|false|FALSE) + valor="none";; + *) + return 0 ;; +esac + +cat >> $TEMPhive << EOF +hive 1 +cd \ControlSet001\Control\Session Manager +ed BootExecute +$valor +--n +EOF +} + + + +### FASE DE PRUEBAS NO FUNCIONA +function NTStartRecovery () { +if [ $# = 0 ] +then + echo sintaxis: Int-Status + echo ejemplos: int=0 desactivado int=1 activado + return 2 +fi + +[ $1 = 0 ] && valor="none" +[ $1 = 1 ] && valor="00000000" + + +cat >> $TEMPhive << EOF +hive 2 +#cd \Policies\Microsoft\Windows\WinRE +#ed DisableSetup +cd \Policies\Microsoft\Windows +nk WinRE +nv 4 DisableSetup +ed DisableSetup +$valor +--n +EOF + + +#Activado +#[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WinRE] +#"DisableSetup"=- + +# Desactivado +#[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WinRE] +#"DisableSetup"=dword:00000000 + + +} + + +function ogSchrootLinux () { + +# Variables locales. +local PART DISK DIRCONF SCHROOTDEVICE + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_partition" \ + "$FUNCNAME 1 1 " + return +fi + +# Error si no se reciben 2 parámetros. +[ $# == 2 ] || return $(ogRaiseError $OG_ERR_FORMAT; echo $?) + +DISK=$1; PART=$2; DIRCONF="/etc/schroot" + + +VERSION=$(ogGetOsVersion $DISK $PART) +echo $VERSION | grep "Linux" || return $(ogRaiseError $OG_ERR_NOTOS "no es linux"; echo $?) + +ogUnmount $DISK $PART || return $(ogRaiseError $OG_ERR_NOTOS "no es linux"; echo $?) + +SCHROOTDEVICE=$(ogDiskToDev $DISK $PART) + + +rm ${DIRCONF}/mount-defaults +rm ${DIRCONF}/schroot.conf + +cat >> ${DIRCONF}/mount-defaults << EOF +# +proc /proc proc defaults 0 0 +/dev /dev none rw,bind 0 0 +/dev/pts /dev/pts none rw,bind 0 0 +/dev/shm /dev/shm none rw,bind 0 0 +EOF + + +cat >> ${DIRCONF}/schroot.conf << EOF +[linux] +description=$VERSION +type=block-device +device=$SCHROOTDEVICE +EOF + + + + +schroot -c linux + +schroot -end-sessiona --all-sessions +} + + +#/** @function ogDiskToRelativeDev: @brief Traduce los ID de discos o particiones EAC a ID Linux relativos, es decir 1 1 => sda1 +#@param Admite 1 parametro: $1 int_numdisk +#@param Admite 2 parametro: $1 int_numdisk $2 int_partition +#@return Para 1 parametros traduce Discos Duros: Devuelve la ruta relativa linux del disco duro indicado con nomenclatura EAC.........ejemplo: IdPartition 1 => sda +#@return Para 2 parametros traduce Particiones: Devuelve la ruta relativa linux de la particion indicado con nomenclatura EAC........... ejemplo: IdPartition 2 1 => sdb1 +#@warning No definidas +#@attention +#@note Notas sin especificar +#@version 0.1 - Integracion para Opengnsys - EAC: IdPartition en ATA.lib +#@author Antonio J. Doblas Viso. Universidad de Malaga +#@date 27/10/2008 +#*/ +function ogDiskToRelativeDev () { +if [ $# = 0 ] +then + Msg "Info: Traduce el identificador del dispositivo EAC a dispositivo linux \n" info + Msg "Sintaxis1: IdPartition int_disk -----------------Ejemplo1: IdPartition 1 -> sda " example + Msg "Sintaxis2: IdPartition int_disk int_partition --Ejemplo2: IdPartition 1 2 -> sda2 " example + +return +fi +#PART="$(Disk|cut -f$1 -d' ')$2" # se comenta esta linea porque doxygen no reconoce la funcion disk y no crea los enlaces y referencias correctas. +PART=$(ogDiskToDev|cut -f$1 -d' ')$2 +echo $PART | cut -f3 -d \/ +} + + +#/** @function ogDeletePartitionsLabels: @brief Elimina la informacion que tiene el kernel del cliente og sobre los labels de los sistemas de archivos +#@param No requiere +#@return Nada +#@warning +#@attention Requisitos: comando interno linux rm +#@note +#@version 0.1 - Integracion para Opengnsys - EAC: DeletePartitionTable() en ATA.lib +#@author Antonio J. Doblas Viso. Universidad de Malaga +#@date 27/10/2008 +#*/ +function ogDeletePartitionsLabels () { +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME " \ + "$FUNCNAME " + return +fi + +rm /dev/disk/by-label/* # */ COMENTARIO OBLIGATORIO PARA DOXYGEN +} + + +#/** @function ogInfoCache: @brief muestra la informacion de la CACHE. +#@param sin parametros +#@return texto que se almacena en $IP.-InfoCache. punto_montaje, tama?oTotal, TamanioOcupado, TaminioLibre, imagenes dentro de la cahce +#@warning Salidas de errores no determinada +#@warning printf no soportado por busybox +#@attention +#@version 0.1 Date: 27/10/2008 Author Antonio J. Doblas Viso. Universidad de Malaga +#*/ +function ogInfoCache () +{ +local info infoFilesystem infoSize infoUsed infoUsedPorcet infoMountedOn content +if ogMountCache +then + info=`df -h | grep $OGCAC` + infoFilesystem=`echo $info | cut -f1 -d" "` + infoSize=`echo $info | cut -f2 -d" "` + infoUsed=`echo $info | cut -f3 -d" "` + infoAvail=`echo $info | cut -f4 -d" "` + infoUsedPorcet=`echo $info | cut -f5 -d" "` + infoMountedOn=`echo $info | cut -f2 -d" "` + if `ls ${OGCAC}$OGIMG > /dev/null 2>&1` + then + cd ${OGCAC}${OPENGNSYS} + #content=`find images/ -type f -printf "%h/ %f %s \n"` busybox no soporta printf + content=`find images/ -type f` + cd / + echo $info + echo -ne $content + echo " " + #echo "$info" > ${OGLOG}/${IP}-InfoCache + #echo "$content" >> {$OGLOG}/${IP}-InfoCache + else + echo $info + #echo "$info" > {$OGLOG}/${IP}-InfoCache + fi + ogUnmountCache +else + echo " " + #echo " " > {$OGLOG}/${IP}-InfoCache + +fi +} + diff --git a/client/lib/engine/bin/PostConfLib.py b/client/lib/engine/bin/PostConfLib.py deleted file mode 100644 index e97b266..0000000 --- a/client/lib/engine/bin/PostConfLib.py +++ /dev/null @@ -1,320 +0,0 @@ -#/** -#@file PostConfLib.py -#@brief Librería o clase PostConf -#@class PostConf -#@brief Funciones para la postconfiguración de sistemas operativos. -#@warning License: GNU GPLv3+ -#*/ - -import os -import glob -import subprocess - -import ogGlobals -import SystemLib -import FileSystemLib -import FileLib -import NetLib -import RegistryLib -import InventoryLib -import BootLib - -#/** -# ogCleanOs int_ndisk int_nfilesys -#@brief Elimina los archivos que no son necesarios en el sistema operativo. -#@param int_ndisk nº de orden del disco -#@param int_nfilesys nº de orden del sistema de archivos -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. -#@exception OG_ERR_PARTITION Partición desconocida o no accesible. -#@note Antes incluido en la funcion ogReduceFs -#@return (nada) -#*/ ## -#ogCleanOs (1, 1) -def ogCleanOs (disk, par): - t = InventoryLib.ogGetOsType (disk, par) - if 'Linux' == t: - BootLib.ogCleanLinuxDevices (disk, par) - mntdir = FileSystemLib.ogMount (disk, par) - for t in glob.glob ('{mntdir}/tmp/*'): - shutil.rmtree (t) - elif 'Windows' == t: - for f in 'pagefile.sys', 'hiberfil.sys', 'swapfile.sys': - p = FileLib.ogGetPath (src=f'{disk} {par}', file=f) - if p: FileLib.ogDeleteFile (disk=disk, par=par, file=f) - - - -#/** -# ogInstallMiniSetup int_ndisk int_npartition str_filename [str_admuser str_admpassword bool_autologin [str_autouser str_autopassword] ] -#@brief Metafunción para instalar archivo que se ejecutará en el arranque de Windows. -#@see ogInstallFirstBoot ogInstallRunonce -#*/ ## -def ogInstallMiniSetup (disk, par, cmdfile, user=None, pwd=None, autologin=False, userauto=None, pwdauto=None): - if user: - ogInstallRunonce (disk, par, cmdfile, user, pwd, autologin, userauto, pwdauto) - else: - ogInstallFirstBoot (disk, par, cmdfile) - - -#/** -# ogInstallFirstBoot int_ndisk int_npartition str_filename -#@brief Crea unas claves del registro y el archivo cmd que se ejecutara en el primer arranque estando la maquina en un estado bloqueado -#@param int_ndisk nº de orden del disco -#@param int_npartition nº de orden de la partición -#@param str_filename nombre del archivo .cmd a ejecutar en el arranque -#@return (nada) -#@exception OG_ERR_FORMAT Formato incorrecto. -#@note El archivo estará en system32 y será visible por el sistema. -#*/ ## -#ogInstallFirstBoot ('1', '1', 'filename.cmd') -def ogInstallFirstBoot (disk, par, cmdfile): - mntdir = FileSystemLib.ogMount (disk, par) - if not mntdir: return - for i in ['winnt', 'windows']: - dir = FileLib.ogGetPath (file=f'{mntdir}/{i}/system32') - if dir: cmddir = dir - if not cmddir: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'{mntdir}/windows/system32') - return - full_cmdfile = f'{cmddir}/{cmdfile}' - bn = os.path.basename (full_cmdfile) - - # Creamos el archivo cmd y creamos un par de comandos para que una vez acabe la - # postconfiguracion resetee el mini setup, sino lo haria en cada arranque. - with open (full_cmdfile, 'w') as fd: - fd.write (r'REG ADD HKLM\System\Setup /v SystemSetupInProgress /t REG_DWORD /d 0 /f' + '\n') - fd.write (r'REG ADD HKLM\System\Setup /v CmdLine /t REG_SZ /d "" /f' + '\n') - - # Crear los valores de registro necesarios para que se haga la ejecución del .cmd al aranque. - RegistryLib.ogSetRegistryValue (mntdir, 'SYSTEM', r'\Setup\SystemSetupInProgress', 1) - RegistryLib.ogSetRegistryValue (mntdir, 'SYSTEM', r'\Setup\SetupType', 4) - #RegistryLib.ogDeleteRegistryValue (mntdir, 'SYSTEM', r'\Setup\CmdLine') - RegistryLib.ogAddRegistryValue (mntdir, 'SYSTEM', r'\Setup\CmdLine') - RegistryLib.ogSetRegistryValue (mntdir, 'SYSTEM', r'\Setup\CmdLine', f'cmd.exe /c {bn}') - - -#/** -# ogInstallRunonce int_ndisk int_npartition str_filename str_adm_user str_adm_password bool_autologin [str_auto_user str_auto_password] -#@brief Crea el archivo cmd que se ejecutara en el runonce de un usuario administrador -#@param int_ndisk nº de orden del disco -#@param int_npartition nº de orden de la partición -#@param str_filename nombre del archivo .cmd a ejecutar en el arranque (estara en system32 y sera visible por el sistema) -#@param str_adm_user usuario administrador para hacer autologin y ejecutar el runonce -#@param str_adm_password password del usuario administrador -#@param bool_autologin si despues de la postconfiguracion queremos que la maquina haga autologin (0 o 1) -#@param str_auto_user Usuario con el que queremos que haga autologin despues de la postconfiguracion -#@param str_auto_password Password del usuario que hara autologin -#@return (nada) -#@exception OG_ERR_FORMAT Formato incorrecto. -#*/ ## -#ogInstallRunonce ('1', '1', 'filename.cmd', 'administrator', 'passadmin', '1', 'userauto', 'pwdauto') -#ogInstallRunonce ('1', '1', 'filename.cmd', 'administrator', 'passadmin', '0') -def ogInstallRunonce (disk, par, cmdfile, user, pwd, autologin, userauto=None, pwdauto=None): - mountpoint = FileLib.ogGetPath (src=f'{disk} {par}', file='/') - for i in ['winnt', 'windows']: - dir = FileLib.ogGetPath (file=f'{mountpoint}/{i}/system32') - if dir: cmddir = dir - if not cmddir: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'{mountpoint}/Windows/System32') - return - full_cmdfile = f'{cmddir}/{cmdfile}' - if not autologin: - # Si no queremos hacer autologin despues de la postconfiguracion lo indicamos en las claves de registro - with open (full_cmdfile, 'w') as fd: - fd.write (r'DEL C:\ogboot.*' + '\n') - fd.write (r'REG ADD "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v AutoAdminLogon /t REG_SZ /d 0 /f' + '\n') - fd.write (r'REG ADD "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultUserName /t REG_SZ /d "" /f' + '\n') - fd.write (r'REG DELETE "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultPassword /f' + '\n') - else: - # Si queremos hacer autologin despues de la postconfiguracion introducimos la informacion en las claves de registro - with open (full_cmdfile, 'w') as fd: - fd.write (r'DEL C:\ogboot.*' + '\n') - fd.write (r'REG ADD "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v AutoAdminLogon /t REG_SZ /d 1 /f' + '\n') - fd.write (fr'REG ADD "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultUserName /t REG_SZ /d "{userauto}" /f' + '\n') - fd.write (fr'REG ADD "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultPassword /t REG_SZ /d "{pwdauto}" /f' + '\n') - #Creamos las claves de registro necesarias para que meter el cmd en el runonce del usuario y este haga autologin - RegistryLib.ogAddRegistryValue (mountpoint, 'software', r'\Microsoft\Windows\CurrentVersion\RunOnce\PostConfiguracion') - RegistryLib.ogSetRegistryValue (mountpoint, 'software', r'\Microsoft\Windows\CurrentVersion\RunOnce\PostConfiguracion', rf'C:\windows\system32\{cmdfile}') - RegistryLib.ogAddRegistryValue (mountpoint, 'software', r'\Microsoft\Windows NT\CurrentVersion\Winlogon\AutoAdminLogon') - RegistryLib.ogSetRegistryValue (mountpoint, 'software', r'\Microsoft\Windows NT\CurrentVersion\Winlogon\AutoAdminLogon', 1) - RegistryLib.ogAddRegistryValue (mountpoint, 'software', r'\Microsoft\Windows NT\CurrentVersion\Winlogon\DefaultUserName') - RegistryLib.ogSetRegistryValue (mountpoint, 'software', r'\Microsoft\Windows NT\CurrentVersion\Winlogon\DefaultUserName', user) - RegistryLib.ogAddRegistryValue (mountpoint, 'software', r'\Microsoft\Windows NT\CurrentVersion\Winlogon\DefaultDomainName') - RegistryLib.ogSetRegistryValue (mountpoint, 'software', r'\Microsoft\Windows NT\CurrentVersion\Winlogon\DefaultDomainName', '.\\') - RegistryLib.ogAddRegistryValue (mountpoint, 'software', r'\Microsoft\Windows NT\CurrentVersion\Winlogon\DefaultPassword') - RegistryLib.ogSetRegistryValue (mountpoint, 'software', r'\Microsoft\Windows NT\CurrentVersion\Winlogon\DefaultPassword', pwd) - RegistryLib.ogDeleteRegistryValue (mountpoint, 'software', r'\Microsoft\Windows NT\CurrentVersion\Winlogon\ForceAutoLockOnLogon') - RegistryLib.ogDeleteRegistryValue (mountpoint, 'software', r'\Microsoft\Windows NT\CurrentVersion\Winlogon\AutoLogonCount') - -#/** -# ogAddCmd int_ndisk int_npartition str_filename str_commands -#@brief Añade comandos al cmd creado por ogInstalMiniSetup -#@param int_ndisk nº de orden del disco -#@param int_npartition nº de orden de la partición -#@param str_filename nombre del fichero cmd (siempre se guardara en windows\system32\para que sea visible por el sistema -#@param str_commands comando o comandos que se añadiran al fichero -#@return -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. -#*/ ## -#ogAddCmd ('1', '1', 'filename.cmd', 'command') -def ogAddCmd (disk, par, cmdfile, cmd): - mountpoint = FileSystemLib.ogMount (disk, par) - if not mountpoint: return - - full_cmdfile = FileLib.ogGetPath (file=f'{mountpoint}/windows/system32') + '/' + cmdfile - if not full_cmdfile: - ogInstallMiniSetup (disk, par, cmdfile) - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'{mountpoint}/windows/system32/{cmdfile}') - return - - # Concatenamos el comando en el fichero de comandos - with open (full_cmdfile, 'a') as fd: - fd.write (cmd + '\n') - - -#/** -# ogDomainScript int_ndisk int_npartition str_domain str_user str_password -#@brief Crea un script .vbs para unir al dominio una maquina windows y el comando adequado en el archivo cmd creado por ogInstallMiniSetup -#@param int_ndisk nº de orden del disco -#@param int_npartition nº de orden de la partición -#@param str_filename nombre del fichero cmd donde deberemos introducir el comando de ejecutar el script vbs -#@param str_domain dominio donde se quiere conectar -#@param str_user usuario con privilegios para unir al dominio -#@param str_password password del usuario con privilegios -#@return -#@exception OG_ERR_FORMAT Formato incorrecto. -#*/ ## - - -### PRUEBAS. - -#/** -# ogConfigureOgagent int_ndisk int_filesys -#@brief Modifica el fichero de configuración del nuevo agente OGAent para sistemas operativos. -#@param int_ndisk nº de orden del disco -#@param int_filesys nº de orden del sistema de archivos -#@return (nada) -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_NOTFOUND Fichero o dispositivo no encontrado. -#@exception OG_ERR_LOCKED Sistema de archivos bloqueado. -#*/ ## -def ogConfigureOgagent (disk, par): - mntdir = FileSystemLib.ogMount (disk, par) - if not mntdir: - return - - for agentdir in ['usr/share/OGAgent', 'Program Files/OGAgent', 'Program Files (x86)/OGAgent', 'Applications/OGAgent.app']: - cfgfile = FileLib.ogGetPath (file=f'{mntdir}/{agentdir}/cfg/ogagent.cfg') - if cfgfile: break - - if not cfgfile: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, 'ogagent.cfg') - return - - ogcore_scheme = 'https' - ogcore_ip = NetLib.ogGetServerIp() - ogcore_port = NetLib.ogGetServerPort() - cfgfile_patched = cfgfile + '.patched' - in_opengnsys_section = False - with open (cfgfile, 'r') as fdin: - with open (cfgfile_patched, 'w') as fdout: - while True: - lineout = linein = fdin.readline() - if not linein: break - if in_opengnsys_section: - if 'remote' == linein[0:6]: - lineout = f'remote={ogcore_scheme}://{ogcore_ip}:{ogcore_port}/opengnsys/rest/\n' - if '[' == linein[0:1]: - in_opengnsys_section = False - if '[opengnsys]' == linein[0:11]: - in_opengnsys_section = True - fdout.write (lineout) - os.rename (cfgfile_patched, cfgfile) - - -#/** -# ogInstallLaunchDaemon int_ndisk int_nfilesys str_filename -#@brief Instala archivo que se ejecutará en el arranque de macOS. -#@param int_ndisk nº de orden del disco -#@param int_nfilesys nº de orden del sistema de archivos -#@param str_filename nombre del script -#return (nada) -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_NOTFOUND Fichero o directorio no encontrado. -#@npte Crea ficheros de configuración /Library/LaunchDaemon/es.opengnsys.Script.plist. -#*/ ## - - -### PRUEBAS. - -#/** -# ogAddToLaunchDaemon int_ndisk int_nfilesys str_filename str_commands -#@brief Añade comandos al script creado por ogInstalLaunchDaemon. -#@param int_ndisk nº de orden del disco -#@param int_nfilesys nº de orden del sistema de archivos -#@param str_filename nombre del script (siempre se guardará en /usr/share para que sea visible por el sistema -#@param str_commands comando o comandos que se añadiran al fichero -#return (nada) -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_NOTFOUND Fichero o directorio no encontrado. -#*/ ## - - -#/** -# ogUninstallLinuxClient int_ndisk int_filesys -#@brief Desinstala el cliente OpenGnSys para sistemas operativos GNU/Linux. -#@param int_ndisk nº de orden del disco -#@param int_filesys nº de orden del sistema de archivos -#@return (nada) -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_PARTITION Paritición o sistema de archivos incorrectos. -#@exception OG_ERR_LOCKED Sistema de archivos bloqueado. -#*/ ## -def ogUninstallLinuxClient (disk, par): - mntdir = FileSystemLib.ogMount (disk, par) - if not mntdir: - return - - for f in [ - f'{mntdir}/usr/sbin/ogAdmLnxClient', - f'{mntdir}/sbin/ogAdmLnxClient', - f'{mntdir}/usr/local/sbin/ogAdmLnxClient', - f'{mntdir}/etc/ogAdmLnxClient.cfg', - f'{mntdir}/usr/local/etc/ogAdmLnxClient.cfg', - ]: - try: os.remove (f) - except: pass - - for f in [ - f'{mntdir}/etc/rc.local', - f'{mntdir}/etc/rc.d/rc.local', - f'{mntdir}/usr/local/etc/rc.local', - f'{mntdir}/usr/local/etc/rc.d/rc.local', - ]: - subprocess.run (['sed', '-i', '-e', '/ogAdmLnxClient/ d', f], stderr=subprocess.DEVNULL) - - -#/** -# ogUninstallWindowsClient int_ndisk int_filesys str_filename -#@brief Desinstala el cliente OpenGnSys para sistemas operativos Windows. -#@param int_ndisk nº de orden del disco -#@param int_npartition nº de orden de la partición -#@param str_filename nombre del fichero cmd donde deberemos introducir el comando de ejecutar el script vbs -#@return (nada) -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_PARTITION Paritición o sistema de archivos incorrectos. -#@exception OG_ERR_LOCKED Sistema de archivos bloqueado. -#*/ ## -#ogUninstallWindowsClient ('1', '1', 'filename.cmd') -def ogUninstallWindowsClient (disk, par, cmdfile): - mntdir = FileSystemLib.ogMount (disk, par) - if not mntdir: return - - exe1 = FileLib.ogGetPath (file=f'{mntdir}/windows/ogAdmWinClient.exe') - exe2 = FileLib.ogGetPath (file=f'{mntdir}/winnt/ogAdmWinClient.exe') - if exe1 or exe2: - ogAddCmd (disk, par, cmdfile, 'ogAdmWinClient -remove') - ogAddCmd (disk, par, cmdfile, r'DEL C:\Windows\ogAdmWinClient.exe') - ogAddCmd (disk, par, cmdfile, r'DEL C:\Winnt\ogAdmWinClient.exe') diff --git a/client/lib/engine/bin/Protocol.lib b/client/lib/engine/bin/Protocol.lib new file mode 100755 index 0000000..02ccdf9 --- /dev/null +++ b/client/lib/engine/bin/Protocol.lib @@ -0,0 +1,1182 @@ +#!/bin/bash +#/** +#@file Protocol.lib +#@brief Librería o clase Protocol +#@class Protocol +#@brief Funciones para transmisión de datos +#@version 1.0.5 +#@warning License: GNU GPLv3+ +#*/ + + +##################### FUNCIONES UNICAST ################ + +#/** +# ogUcastSyntax +#@brief Función para generar la instrucción de transferencia de datos unicast +#@param 1 Tipo de operación [ SENDPARTITION RECEIVERPARTITION SENDFILE RECEIVERFILE ] +#@param 2 Sesion Unicast +#@param 3 Dispositivo (opción PARTITION) o fichero(opción FILE) que será enviado. +#@param 4 Tools de clonación (opcion PARTITION) +#@param 5 Tools de compresion (opcion PARTITION) +#@return instrucción para ser ejecutada. +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_UCASTSYNTAXT formato de la sesion unicast incorrecta. +#@note Requisitos: mbuffer +#@todo: controlar que mbuffer esta disponible para los clientes. +#@version 1.0 - +#@author Antonio Doblas Viso, Universidad de Málaga +#@date 2011/03/09 +#*/ ## + +function ogUcastSyntax () +{ + +local PARM SESSION SESSIONPARM MODE PORTBASE PERROR ADDRESS +local TOOL LEVEL DEVICE MBUFFER SYNTAXSERVER SYNTAXCLIENT + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" -o "$2" == "help" ]; then + ogHelp "$FUNCNAME SENDPARTITION str_sessionSERVER str_device str_tools str_level" \ + "$FUNCNAME RECEIVERPARTITION str_sessionCLIENT str_device str_tools str_level "\ + "$FUNCNAME SENDFILE str_sessionSERVER str_file "\ + "$FUNCNAME RECEIVERFILE str_sessionCLIENT str_file " \ + "sessionServer syntax: portbase:ipCLIENT-1:ipCLIENT-2:ipCLIENT-N " \ + "sessionServer example: 8000:172.17.36.11:172.17.36.12" \ + "sessionClient syntax: portbase:ipMASTER " \ + "sessionClient example: 8000:172.17.36.249 " + return +fi +PERROR=0 + + + + +# Error si no se reciben $PARM parámetros. +echo "$1" | grep "PARTITION" > /dev/null && PARM=5 || PARM=3 +[ "$#" -eq "$PARM" ] || ogRaiseError $OG_ERR_FORMAT "sin parametros"|| return $? + + +# 1er param check +ogCheckStringInGroup "$1" "SENDPARTITION sendpartition RECEIVERPARTITION receiverpartition SENDFILE sendfile RECEIVERFILE receiverfile" || ogRaiseError $OG_ERR_FORMAT "1st param: $1" || PERROR=1 #return $? + +# 2º param check +echo "$1" | grep "SEND" > /dev/null && MODE=server || MODE=client + +######### No controlamos el numero de elementos de la session unicast porque en el master es variable en numero +#TODO: diferenciamos los paramatros especificos de la sessión unicast +#SI: controlamos todos los parametros de la sessión unicast. +#[ $MODE == "client" ] && SESSIONPARM=2 || SESSIONPARM=6 +OIFS=$IFS; IFS=':' ; SESSION=($2); IFS=$OIFS + + +#[[ ${#SESSION[*]} == $SESSIONPARM ]] || ogRaiseError $OG_ERR_FORMAT "parametros session multicast no completa" || PERROR=2# return $? + + +#controlamos el PORTBASE de la sesion. Comun.- +PORTBASE=${SESSION[0]} +ogCheckStringInGroup ${SESSION[0]} "8000 8001 8002 8003 8004 8005" || ogRaiseError $OG_ERR_FORMAT "McastSession portbase ${SESSION[0]}" || PERROR=3 #return $? + +if [ $MODE == "server" ] +then + SIZEARRAY=${#SESSION[@]} + for (( i = 1 ; i < $SIZEARRAY ; i++ )) + do + ADDRESS="$ADDRESS -O ${SESSION[$i]}:$PORTBASE" + #echo " -O ${SESSION[$i]}:$PORTBASE" + done + +else + ADDRESS=${SESSION[1]}:${PORTBASE} +fi + +#3er param check - que puede ser un dispositvo o un fichero. +#[ -n "$(ogGetPath "$3")" ] || ogRaiseError $OG_ERR_NOTFOUND " device or file $3" || PERROR=9 #return $? +DEVICE=$3 + +#4 y 5 param check . solo si es sobre particiones. +if [ "$PARM" == "5" ] +then + # 4 param check + ogCheckStringInGroup "$4" "partclone PARTCLONE partimage PARTIMAGE ntfsclone NTFSCLONE" || ogRaiseError $OG_ERR_NOTFOUND " herramienta $4 no soportada" || PERROR=10 #return $? + TOOL=$4 + ogCheckStringInGroup "$5" "lzop gzip LZOP GZIP 0 1" || ogRaiseError $OG_ERR_NOTFOUND " compresor $5 no valido" || PERROR=11 #return $? + LEVEL=$5 +fi + +[ "$PERROR" == "0" ] || ogRaiseError $OG_ERR_UCASTSYNTAXT " $PERROR" || return $? + +# Generamos la instrucción base de unicast -Envio,Recepcion- +SYNTAXSERVER="mbuffer $ADDRESS" +SYNTAXCLIENT="mbuffer -I $ADDRESS " + + +case "$1" in +SENDPARTITION) + PROG1=`ogCreateImageSyntax $DEVICE " " $TOOL $LEVEL | awk -F"|" '{print $1 "|" $3}' | tr -d ">"` + echo "$PROG1 | $SYNTAXSERVER" + ;; + RECEIVERPARTITION) + COMPRESSOR=`ogRestoreImageSyntax " " $DEVICE $TOOL $LEVEL | awk -F\| '{print $1}'` + TOOLS=`ogRestoreImageSyntax " " $DEVICE $TOOL $LEVEL | awk -F\| '{print $NF}'` + echo "$SYNTAXCLIENT | $COMPRESSOR | $TOOLS " + ;; + SENDFILE) + echo "$SYNTAXSERVER -i $3" + ;; + RECEIVERFILE) + echo "$SYNTAXCLIENT -i $3" + ;; + *) + ;; +esac +} + + +#/** +# ogUcastSendPartition +#@brief Función para enviar el contenido de una partición a multiples particiones remotas usando UNICAST. +#@param 1 disk +#@param 2 partition +#@param 3 sesionUcast +#@param 4 tool image +#@param 5 tool compresor +#@return +#@exception $OG_ERR_FORMAT +#@exception $OG_ERR_UCASTSENDPARTITION +#@note +#@todo: ogIsLocked siempre devuelve 1 +#@version 1.0 - +#@author Antonio Doblas Viso, Universidad de Málaga +#@date 2011/03/09 +#*/ ## + +function ogUcastSendPartition () +{ + +# Variables locales +local PART COMMAND RETVAL + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_npart SessionUNICAST-SERVER tools compresor" \ + "$FUNCNAME 1 1 8000:172.17.36.11:172.17.36.12 partclone lzop" + return +fi +# Error si no se reciben 5 parámetros. +[ "$#" == 5 ] || ogRaiseError $OG_ERR_FORMAT || return $? +#chequeamos la particion. +PART=$(ogDiskToDev "$1" "$2") || return $? + +#ogIsLocked $1 $2 || ogRaiseError $OG_ERR_LOCKED "$1,$2" || return $? +ogUnmount $1 $2 + +#generamos la instrucción a ejecutar. +COMMAND=`ogUcastSyntax SENDPARTITION "$3" $PART $4 $5` +RETVAL=$? + +if [ "$RETVAL" -gt "0" ] +then + return $RETVAL +else + echo $COMMAND + eval $COMMAND || ogRaiseError $OG_ERR_UCASTSENDPARTITION " "; return $? +fi + +} + + +#/** +# ogUcastReceiverPartition +#@brief Función para recibir directamente en la partición el contenido de un fichero imagen remoto enviado por UNICAST. +#@param 1 disk +#@param 2 partition +#@param 3 session unicast +#@return +#@exception OG_ERR_FORMAT +#@exception OG_ERR_UCASTRECEIVERPARTITION +#@note +#@todo: +#@version 1.0 - Integración para OpenGNSys. +#@author Antonio Doblas Viso, Universidad de Málaga +#@date 2011/03/09 +#*/ ## +function ogUcastReceiverPartition () +{ +# Variables locales +local PART COMMAND RETVAL + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_npart SessionMulticastCLIENT tools compresor" \ + "$FUNCNAME 1 1 8000:ipMASTER partclone lzop" + return +fi +# Error si no se reciben 5 parámetros. +[ "$#" == 5 ] || ogRaiseError $OG_ERR_FORMAT || return $? +#chequeamos la particion. +PART=$(ogDiskToDev "$1" "$2") || return $? + +#ogIsLocked $1 $2 || ogRaiseError $OG_ERR_LOCKED "$1,$2" || return $? +ogUnmount $1 $2 + +#generamos la instrucción a ejecutar. +COMMAND=`ogUcastSyntax RECEIVERPARTITION "$3" $PART $4 $5` +RETVAL=$? + +if [ "$RETVAL" -gt "0" ] +then + return $RETVAL +else + echo $COMMAND + eval $COMMAND || ogRaiseError $OG_ERR_UCASTRECEIVERPARTITION " "; return $? +fi +} + + + +#/** +# ogUcastSendFile [ str_repo | int_ndisk int_npart ] /Relative_path_file sessionMulticast +#@brief Envía un fichero por unicast ORIGEN(fichero) DESTINO(sessionmulticast) +#@param (2 parámetros) $1 path_aboluto_fichero $2 sesionMcast +#@param (3 parámetros) $1 Contenedor REPO|CACHE $2 path_absoluto_fichero $3 sesionMulticast +#@param (4 parámetros) $1 disk $2 particion $3 path_absoluto_fichero $4 sesionMulticast +#@return +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception $OG_ERR_NOTFOUND +#@exception OG_ERR_UCASTSENDFILE +#@note Requisitos: +#@version 1.0 - Definición de Protocol.lib +#@author Antonio Doblas Viso, Universidad de Málaga +#@date 2010/05/09 +#*/ ## +# + +function ogUcastSendFile () +{ +# Variables locales. +local ARG ARGS SOURCE TARGET COMMAND DEVICE RETVAL LOGFILE + + +#ARGS usado para controlar ubicación de la sesion multicast +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME [str_REPOSITORY] [int_ndisk int_npart] /Relative_path_file sesionMcast(puerto:ip:ip:ip)" \ + "$FUNCNAME 1 1 /aula1/winxp.img 8000:172.17.36.11:172.17.36.12" \ + "$FUNCNAME REPO /aula1/ubuntu.iso sesionUcast" \ + "$FUNCNAME CACHE /aula1/winxp.img sesionUcast" \ + "$FUNCNAME /opt/opengnsys/images/aula1/hd500.vmx sesionUcast" + return +fi + +ARGS="$@" +case "$1" in + /*) # Camino completo. */ (Comentrio Doxygen) + SOURCE=$(ogGetPath "$1") + ARG=2 + DEVICE="$1" + ;; + [1-9]*) # ndisco npartición. + SOURCE=$(ogGetPath "$1" "$2" "$3") + ARG=4 + DEVICE="$1 $2 $3" + ;; + *) # Otros: repo, cache, cdrom (no se permiten caminos relativos). + SOURCE=$(ogGetPath "$1" "$2") + ARG=3 + DEVICE="$1 $2 " + ;; +esac + + +# Error si no se reciben los argumentos ARG necesarios según la opcion. +[ $# == "$ARG" ] || ogRaiseError $OG_ERR_FORMAT || return $? + +# Comprobar fichero origen +[ -n "$(ogGetPath $SOURCE)" ] || ogRaiseError $OG_ERR_NOTFOUND " device or file $DEVICE not found" || return $? + + +SESSION=${!ARG} + +#generamos la instrucción a ejecutar. +COMMAND=`ogUcastSyntax "SENDFILE" "$SESSION" "$SOURCE"` +RETVAL=$? + +if [ "$RETVAL" -gt "0" ] +then + return $RETVAL +else + echo $COMMAND + eval $COMMAND || ogRaiseError $OG_ERR_UCASTSENDFILE " "; return $? +fi + +} + + + +#/** +# ogMcastSyntax +#@brief Función para generar la instrucción de ejucción la transferencia de datos multicast +#@param 1 Tipo de operación [ SENDPARTITION RECEIVERPARTITION SENDFILE RECEIVERFILE ] +#@param 2 Sesión Mulicast +#@param 3 Dispositivo (opción PARTITION) o fichero(opción FILE) que será enviado. +#@param 4 Tools de clonación (opcion PARTITION) +#@param 5 Tools de compresion (opcion PARTITION) +#@return instrucción para ser ejecutada. +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTEXEC +#@exception OG_ERR_MCASTSYNTAXT +#@note Requisitos: upd-cast 2009 o superior +#@todo localvar check versionudp +#@version 1.0 - +#@author Antonio Doblas Viso, Universidad de Málaga +#@date 2010/05/09 +#@version 2.0 - cambios en udp-receiver para permitir multicast entre subredes +#@author Juan Carlos Garcia, Universidad de Zaragoza +#@date 2015/11/17 +#@version 1.1 - Control de errores en transferencia multicast (ticket #781) +#@author Irina Gomez, ETSII Universidad de Sevilla +#@date 2017/04/20 +#@version 1.1.0.a - Parametros de clientes como sesision de multicast (ticket #851) +#@author Antonio J. Doblas Viso +#@date 2018/09/22 +#*/ ## +# + +function ogMcastSyntax () +{ + +local ISUDPCAST RECEIVERTIMEOUT STARTTIMEOUT PARM SESSION SESSIONPARM MODE PORTBASE PERROR +local METHOD ADDRESS BITRATE NCLIENTS MAXTIME CERROR +local TOOL LEVEL DEVICE MBUFFER SYNTAXSERVER SYNTAXCLIENT + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" -o "$2" == "help" ]; then + ogHelp "$FUNCNAME SENDPARTITION str_sessionSERVER str_device str_tools str_level" \ + "$FUNCNAME RECEIVERPARTITION str_sessionCLIENT str_device str_tools str_level "\ + "$FUNCNAME SENDFILE str_sessionSERVER str_file "\ + "$FUNCNAME RECEIVERFILE str_sessionCLIENT str_file " \ + "sessionServer syntax: portbase:method:mcastaddress:speed:nclients:ntimeWaitingUntilNclients " \ + "sessionServer example: 9000:full-duplex|half-duplex|broadcast:239.194.17.36:80M:50:60 " \ + "sessionClient syntax: portbase " \ + "sessionClient example: 9000 "\ + "sessionClient syntax: portbase:serverIP:TimeOut_session:TimeOut_transmision" \ + "sessionClient example: 9000:172.17.88.161:40:120" + return +fi +PERROR=0 + +#si no tenemos updcast o su version superior 2009 udpcast error. +ISUDPCAST=$(udp-receiver --help 2>&1) +echo $ISUDPCAST | grep "not found" > /dev/null && (ogRaiseError $OG_ERR_NOTEXEC "upd-cast no existe " || return $?) + +############ BEGIN NUMBERS PARAMETERS CHECK AND SESSION OPTIONS IF CLIENT OR SERVER ############## +# Definimos los parametros de la funcion segun la opcion de envio/recepcion. +echo "$1" | grep "PARTITION" > /dev/null && PARM=5 || PARM=3 +[ "$#" -eq "$PARM" ] || ogRaiseError $OG_ERR_FORMAT "sin parametros"|| return $? +# 1er param check: opcion de envio/recepcion +ogCheckStringInGroup "$1" "SENDPARTITION sendpartition RECEIVERPARTITION receiverpartition SENDFILE sendfile RECEIVERFILE receiverfile" || ogRaiseError $OG_ERR_FORMAT "1st param: $1" || PERROR=1 #return $? +# 1º param check : opcion de cliente/servidor +echo "$1" | grep "SEND" > /dev/null && MODE=server || MODE=client + +# 2º param check: sesion multicast cliente/servidor. comprobamos el numero de parametros segun el tipo de sesion cliente o servidor. +#Definimos los parametros de la sesion multicast. La sesion de cliente seran 3, aunque uno es el obligado y dos opcionales. puerto:server:autostart +[ $MODE == "client" ] && SESSIONPARM=1 || SESSIONPARM=6 +#Controlamos el numero de paratros incluidos en la sesion usada como paraetro $2 +OIFS=$IFS; IFS=':' ; SESSION=($2); IFS=$OIFS +#Controlamos la sesion multicast del server +if [ $MODE == "server" ] +then + [[ ${#SESSION[*]} == $SESSIONPARM ]] || ogRaiseError $OG_ERR_FORMAT "parametros session de servidor multicast no completa" || PERROR=2# return $? +fi +#controlamos la sesion de cliente. +if [ $MODE == "client" ] +then + [[ ${#SESSION[*]} -ge $SESSIONPARM ]] || ogRaiseError $OG_ERR_FORMAT "parametros session de cliente multicast no completa" || PERROR=2# return $? +fi +############ END NUMBERS PARAMETERS CHECK ############## + +##### BEGIN SERVER SESSION ##### +# 2º param check: controlamos el primer componente comun de las sesiones de servidor y cliente: PORTBASE +PORTBASE=${SESSION[0]} +ogCheckStringInGroup ${SESSION[0]} "$(seq 9000 2 9098)" || ogRaiseError $OG_ERR_FORMAT "McastSession portbase ${SESSION[0]}" || PERROR=3 #return $? +# 2º param check: Controlamos el resto de componenentes de la sesion del servidor. +if [ $MODE == "server" ] +then + ogCheckStringInGroup ${SESSION[1]} "full-duplex FULL-DUPLEX half-duplex HALF-DUPLEX broadcast BROADCAST" || ogRaiseError $OG_ERR_FORMAT "McastSession method ${SESSION[1]}" || PERROR=4 #return $? + METHOD=${SESSION[1]} + ogCheckIpAddress ${SESSION[2]} || ogRaiseError $OG_ERR_FORMAT "McastSession address ${SESSION[2]}" || PERROR=5 #return $? + ADDRESS=${SESSION[2]} + ogCheckStringInReg ${SESSION[3]} "^[0-9]{1,3}\M$" || ogRaiseError $OG_ERR_FORMAT "McastSession bitrate ${SESSION[3]}" || PERROR=6 # return $? + BITRATE=${SESSION[3]} + ogCheckStringInReg ${SESSION[4]} "^[0-9]{1,10}$" || ogRaiseError $OG_ERR_FORMAT "McastSession nclients ${SESSION[4]}" || PERROR=7 # return $? + NCLIENTS=${SESSION[4]} + ogCheckStringInReg ${SESSION[5]} "^[0-9]{1,10}$" || ogRaiseError $OG_ERR_FORMAT "McastSession maxtime ${SESSION[5]}" || PERROR=8 # return $? + MAXTIME=${SESSION[5]} +fi + +#3er param check - que puede ser un dispositvo o un fichero. +# [ -n "$(ogGetPath $3)" ] || ogRaiseError $OG_ERR_NOTFOUND " device or file $3" || PERROR=9 #return $? +DEVICE=$3 + +#4 y 5 param check . solo si es sobre particiones. +if [ "$PARM" == "5" ] +then + # 4 param check + ogCheckStringInGroup "$4" "partclone PARTCLONE partimage PARTIMAGE ntfsclone NTFSCLONE" || ogRaiseError $OG_ERR_NOTFOUND " herramienta $4 no soportada" || PERROR=10 #return $? + TOOL=$4 + ogCheckStringInGroup "$5" "lzop LZOP gzip GZIP 0 1" || ogRaiseError $OG_ERR_NOTFOUND " compresor $5 no valido" || PERROR=11 #return $? + LEVEL=$5 +fi +# Controlamos si ha habido errores en la comprobacion de la sesion de servidor. +if [ "$PERROR" != "0" ]; then + ogRaiseError $OG_ERR_MCASTSYNTAXT " $PERROR"; return $? +fi +# Asignamos mas valores no configurables a la sesioe servidor. +CERROR="8x8/128" +# opcion del usuo de tuberia intermedia en memoria mbuffer. +which mbuffer > /dev/null && MBUFFER=" --pipe 'mbuffer -q -m 20M' " + +# Generamos la instruccion base del servidor de multicast -Envio- +SYNTAXSERVER="udp-sender $MBUFFER --nokbd --portbase $PORTBASE --$METHOD --mcast-data-address $ADDRESS --fec $CERROR --max-bitrate $BITRATE --ttl 16 --min-clients $NCLIENTS --max-wait $MAXTIME --autostart $MAXTIME --log /tmp/mcast.log" +########################################################################## +#### END SERVER SESSION ############## + + +##### BEGIN CLIENT SESSION ##### +#La primera opcion PORTBASE, ya esta controlado. Porque es comun al server y al cliente. +#La segunda opcion de la sesion para el cliente:: SERVERADDRES +if ogCheckIpAddress ${SESSION[1]} 2>/dev/null +then + SERVERADDRESS=" --mcast-rdv-address ${SESSION[1]}" +else + # Deteccion automatica de la subred del cliente para anadir la IP del repositorio a la orden udp-receiver en el caso de encontrarse en distinta subred del repo + REPOIP="$(ogGetRepoIp)" + CLIENTIP=$(ip -o address show up | awk '$2!~/lo/ {if ($3~/inet$/) {printf ("%s ", $4)}}') + MASCARA=`echo $CLIENTIP | cut -f2 -d/` + CLIENTIP=`echo $CLIENTIP | cut -f1 -d/` + RIPBT="" + IPBT="" + for (( i = 1 ; i < 5 ; i++ )) + do + RIP=`echo $REPOIP | cut -f$i -d.` + RIP=`echo "$[$RIP + 256]"` + RIPB="" + while [ $RIP -gt 0 ] + do + let COCIENTE=$RIP/2 + let RESTO=$RIP%2 + RIPB=$RESTO$RIPB + RIP=$COCIENTE + done + RIPB=`echo "$RIPB" | cut -c2-` + RIPBT=$RIPBT$RIPB + IP=`echo $CLIENTIP | cut -f$i -d.` + IP=`echo "$[$IP + 256]"` + IPB="" + while [ $IP -gt 0 ] + do + let COCIENTE=$IP/2 + let RESTO=$IP%2 + IPB=$RESTO$IPB + IP=$COCIENTE + done + IPB=`echo "$IPB" | cut -c2-` + IPBT=$IPBT$IPB + done + REPOSUBRED=`echo $RIPBT | cut -c1-$MASCARA` + CLIENTSUBRED=`echo $IPBT | cut -c1-$MASCARA` + if [ $REPOSUBRED == $CLIENTSUBRED ]; then + SERVERADDRESS=" " + else + SERVERADDRESS=" --mcast-rdv-address $REPOIP" + fi +fi +#La tercera opcion de la sesion para el cliente: ${SESSION[2]} ERRORSESSION - TIMEOUT ERROR IF NO FOUNT SESSEION MULTICAST +if ogCheckStringInReg ${SESSION[2]} "^[0-9]{1,10}$" &>/dev/null +then + case ${SESSION[2]} in + 0) + STARTTIMEOUT=" " + ;; + *) + STARTTIMEOUT=" --start-timeout ${SESSION[2]}" + ;; + esac +else + #asignamos valor definido en el engine.cfg + STARTTIMEOUT=" --start-timeout $MCASTERRORSESSION" +fi +#Verificamos que la opcion start-time out esta soportada por la version del cliente +echo $ISUDPCAST | grep start-timeout > /dev/null || STARTTIMEOUT=" " + +#La cuarta opcion de la sesion para el cliente: ${SESSION[2]} ERROR TRANSFER - TIMEOUT EEOR IF NOT RECEIVER DATA FROM SERVER +if ogCheckStringInReg ${SESSION[3]} "^[0-9]{1,10}$" &>/dev/null +then + case ${SESSION[3]} in + 0) + RECEIVERTIMEOUT=" " + ;; + *) + RECEIVERTIMEOUT=" --receive-timeout ${SESSION[3]}" + ;; + esac +else + #asignamos valor definido en el engine.cfg + RECEIVERTIMEOUT=" --receive-timeout $MCASTWAIT" +fi +#Verificamos que la opcion receive-timeou esta soportada por la version del cliente +echo $ISUDPCAST | grep receive-timeout > /dev/null || RECEIVERTIMEOUT=" " + +#Componenemos la sesion multicast del cliente +SYNTAXCLIENT="udp-receiver $MBUFFER --portbase $PORTBASE $SERVERADDRESS $STARTTIMEOUT $RECEIVERTIMEOUT --log /tmp/mcast.log" +########################################################################## +#### END CLIENT SESSION ############## + + ######## BEGIN MAIN PROGAM ##### +case "$1" in + SENDPARTITION) + PROG1=`ogCreateImageSyntax $DEVICE " " $TOOL $LEVEL | awk -F"|" '{print $1 "|" $3}' | tr -d ">"` + echo "$PROG1 | $SYNTAXSERVER" + ;; + RECEIVERPARTITION) + COMPRESSOR=`ogRestoreImageSyntax " " $DEVICE $TOOL $LEVEL | awk -F\| '{print $1}'` + TOOLS=`ogRestoreImageSyntax " " $DEVICE $TOOL $LEVEL | awk -F\| '{print $NF}'` + echo "$SYNTAXCLIENT | $COMPRESSOR | $TOOLS " + ;; + SENDFILE) + echo "$SYNTAXSERVER --file $3" + ;; + RECEIVERFILE) + echo "$SYNTAXCLIENT --file $3" + ;; + *) + ;; +esac +######## END MAIN PROGAM ##### +} + + + +#/** +# ogMcastSendFile [ str_repo | int_ndisk int_npart ] /Relative_path_file sessionMulticast +#@brief Envía un fichero por multicast ORIGEN(fichero) DESTINO(sessionmulticast) +#@param (2 parámetros) $1 path_aboluto_fichero $2 sesionMcast +#@param (3 parámetros) $1 Contenedor REPO|CACHE $2 path_absoluto_fichero $3 sesionMulticast +#@param (4 parámetros) $1 disk $2 particion $3 path_absoluto_fichero $4 sesionMulticast +#@return +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception $OG_ERR_NOTFOUND +#@exception OG_ERR_MCASTSENDFILE +#@note Requisitos: +#@version 1.0 - Definición de Protocol.lib +#@author Antonio Doblas Viso, Universidad de Málaga +#@date 2010/05/09 +#*/ ## +# + +function ogMcastSendFile () +{ +# Variables locales. +local ARGS ARG SOURCE TARGET COMMAND DEVICE RETVAL LOGFILE + +#LOGFILE="/tmp/mcast.log" + +#ARGS usado para controlar ubicación de la sesion multicast +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME [str_REPOSITORY] [int_ndisk int_npart] /Relative_path_file sesionMcast" \ + "$FUNCNAME 1 1 /aula1/winxp.img sesionMcast" \ + "$FUNCNAME REPO /aula1/ubuntu.iso sesionMcast" \ + "$FUNCNAME CACHE /aula1/winxp.img sesionMcast" \ + "$FUNCNAME /opt/opengnsys/images/aula1/hd500.vmx sesionMcast" + return +fi + +ARGS="$@" +case "$1" in + /*) # Camino completo. */ (Comentrio Doxygen) + SOURCE=$(ogGetPath "$1") + ARG=2 + DEVICE="$1" + ;; + [1-9]*) # ndisco npartición. + SOURCE=$(ogGetPath "$1" "$2" "$3") + ARG=4 + DEVICE="$1 $2 $3" + ;; + *) # Otros: repo, cache, cdrom (no se permiten caminos relativos). + SOURCE=$(ogGetPath "$1" "$2") + ARG=3 + DEVICE="$1 $2 " + ;; +esac + + +# Error si no se reciben los argumentos ARG necesarios según la opcion. +[ $# == "$ARG" ] || ogRaiseError $OG_ERR_FORMAT || return $? + +# Comprobar fichero origen +[ -n "$(ogGetPath $SOURCE)" ] || ogRaiseError $OG_ERR_NOTFOUND " device or file $DEVICE not found" || return $? + +# eliminamos ficheros antiguos de log +#rm $LOGFILE + +SESSION=${!ARG} + + +#generamos la instrucción a ejecutar. +COMMAND=`ogMcastSyntax "SENDFILE" "$SESSION" "$SOURCE"` +RETVAL=$? + +if [ "$RETVAL" -gt "0" ] +then + return $RETVAL +else + echo $COMMAND + eval $COMMAND || ogRaiseError $OG_ERR_MCASTSENDFILE " "; return $? + #[ -s "$LOGFILE" ] || return 21 +fi + +} + + + +#/** +# ogMcastReceiverFile sesion Multicast [ str_repo | int_ndisk int_npart ] /Relative_path_file +#@brief Recibe un fichero multicast ORIGEN(sesionmulticast) DESTINO(fichero) +#@param (2 parámetros) $1 sesionMcastCLIENT $2 path_aboluto_fichero_destino +#@param (3 parámetros) $1 sesionMcastCLIENT $2 Contenedor REPO|CACHE $3 path_absoluto_fichero_destino +#@param (4 parámetros) $1 sesionMcastCLIENT $2 disk $3 particion $4 path_absoluto_fichero_destino +#@return +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception $OG_ERR_MCASTRECEIVERFILE +#@note Requisitos: +#@version 1.0 - Definición de Protocol.lib +#@author Antonio Doblas Viso, Universidad de Málaga +#@date 2010/05/09 +#*/ ## +# + +function ogMcastReceiverFile () +{ + +# Variables locales. +local ARGS ARG TARGETDIR TARGETFILE + + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME [ str_portMcast] [ [Relative_path_file] | [str_REPOSITORY path_file] | [int_ndisk int_npart path_file ] ]" \ + "$FUNCNAME 9000 /PS1_PH1.img" \ + "$FUNCNAME 9000 CACHE /aula1/PS2_PH4.img" \ + "$FUNCNAME 9000 1 1 /isos/linux.iso" + return +fi + +ARGS="$@" +case "$2" in + /*) # Camino completo. */ (Comentrio Doxygen) + TARGETDIR=$(ogGetParentPath "$2") + ARG=2 + ;; + [1-9]*) # ndisco npartición. + TARGETDIR=$(ogGetParentPath "$2" "$3" "$4") + ARG=4 + ;; + *) # Otros: repo, cache, cdrom (no se permiten caminos relativos). + TARGETDIR=$(ogGetParentPath "$2" "$3") + ARG=3 + ;; +esac + +# Error si no se reciben los argumentos ARG necesarios según la opcion. +[ $# == "$ARG" ] || ogRaiseError $OG_ERR_FORMAT "Parametros no admitidos"|| return $? + +#obtenemos el nombre del fichero a descargar. +TARGETFILE=`basename ${!ARG}` + +#generamos la instrucción a ejecutar. +COMMAND=`ogMcastSyntax RECEIVERFILE "$1" $TARGETDIR/$TARGETFILE ` +RETVAL=$? + +if [ "$RETVAL" -gt "0" ] +then + return $RETVAL +else + echo $COMMAND + eval $COMMAND || ogRaiseError $OG_ERR_MCASTRECEIVERFILE "$TARGETFILE"; return $? + #[ -s "$LOGFILE" ] || return 21 +fi +} + + +#/** +# ogMcastSendPartition +#@brief Función para enviar el contenido de una partición a multiples particiones remotas. +#@param 1 disk +#@param 2 partition +#@param 3 session multicast +#@param 4 tool clone +#@param 5 tool compressor +#@return +#@exception OG_ERR_FORMAT +#@exception OG_ERR_MCASTSENDPARTITION +#@note +#@todo: ogIsLocked siempre devuelve 1. crear ticket +#@version 1.0 - Definición de Protocol.lib +#@author Antonio Doblas Viso, Universidad de Málaga +#@date 2010/05/09 +#*/ ## + +function ogMcastSendPartition () +{ + +# Variables locales +local PART COMMAND RETVAL + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_npart SessionMulticastSERVER tools compresor" \ + "$FUNCNAME 1 1 9000:full-duplex:239.194.37.31:50M:20:2 partclone lzop" + return +fi +# Error si no se reciben 5 parámetros. +[ "$#" == 5 ] || ogRaiseError $OG_ERR_FORMAT || return $? +#chequeamos la particion. +PART=$(ogDiskToDev "$1" "$2") || return $? + +#ogIsLocked $1 $2 || ogRaiseError $OG_ERR_LOCKED "$1,$2" || return $? +ogUnmount $1 $2 + +#generamos la instrucción a ejecutar. +COMMAND=`ogMcastSyntax SENDPARTITION "$3" $PART $4 $5` +RETVAL=$? + +if [ "$RETVAL" -gt "0" ] +then + return $RETVAL +else + echo $COMMAND + eval $COMMAND || ogRaiseError $OG_ERR_MCASTSENDPARTITION " "; return $? +fi + + +} + +#/** +# ogMcastReceiverPartition +#@brief Función para recibir directamente en la partición el contenido de un fichero imagen remoto enviado por multicast. +#@param 1 disk +#@param 2 partition +#@param 3 session multicast +#@param 4 tool clone +#@param 5 tool compressor +#@return +#@exception $OG_ERR_FORMAT +#@note +#@todo: +#@version 1.0 - Definición de Protocol.lib +#@author Antonio Doblas Viso, Universidad de Málaga +#@date 2010/05/09 +#*/ ## +function ogMcastReceiverPartition () +{ +# Variables locales +local PART COMMAND RETVAL + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_npart SessionMulticastCLIENT tools compresor" \ + "$FUNCNAME 1 1 9000 partclone lzop" + return +fi +# Error si no se reciben 5 parámetros. +[ "$#" == 5 ] || ogRaiseError $OG_ERR_FORMAT || return $? +#chequeamos la particion. +PART=$(ogDiskToDev "$1" "$2") || return $? + +#ogIsLocked $1 $2 || ogRaiseError $OG_ERR_LOCKED "$1,$2" || return $? +ogUnmount $1 $2 + +#generamos la instrucción a ejecutar. +COMMAND=`ogMcastSyntax RECEIVERPARTITION "$3" $PART $4 $5` +RETVAL=$? + +if [ "$RETVAL" -gt "0" ] +then + return $RETVAL +else + echo $COMMAND + eval $COMMAND || ogRaiseError $OG_ERR_MCASTSENDPARTITION " "; return $? +fi + +} + + +#/** +# ogMcastRequest +#@brief Función temporal para solicitar al ogRepoAux el envio de un fichero por multicast +#@param 1 Fichero a enviar ubicado en el REPO. puede ser ruta absoluta o relatica a /opt/opengnsys/images +#@param 2 PROTOOPT opciones protocolo multicast +#@return +#@exception +#@note +#@todo: +#@version 1.0.5 +#@author Antonio Doblas Viso, Universidad de Málaga +#@date 2012/05/29 +#@version 1.1 - Control de errores en transferencia multicast (ticket #781) +#@author Irina Gomez, ETSII Universidad de Sevilla +#@date 2017/04/20 +#@version 1.1 - Unidades organizativas con directorio de imágenes separado. (ticket #678) +#@author Irina Gomez, ETSII Universidad de Sevilla +#@date 2017/06/23 +#*/ ## +function ogMcastRequest () { return 0; } + + +########################################## +############## funciones torrent +#/** +# ogTorrentStart [ str_repo | int_ndisk int_npart ] Relative_path_file.torrent | SessionProtocol +#@brief Función iniciar P2P - requiere un tracker para todos los modos, y un seeder para los modos peer y leecher y los ficheros .torrent. +#@param str_pathDirectory str_Relative_path_file +#@param int_disk int_partition str_Relative_path_file +#@param str_REPOSITORY(CACHE - LOCAL) str_Relative_path_file +#@param (2 parámetros) $1 path_aboluto_fichero_torrent $2 Parametros_Session_Torrent +#@param (3 parámetros) $1 Contenedor CACHE $2 path_absoluto_fichero_Torrent $3 Parametros_Session_Torrent +#@param (4 parámetros) $1 disk $2 particion $3 path_absoluto_fichero_Torrent 4$ Parametros_Session_Torrent +#@return +#@note protocoloTORRENT=mode:time mode=seeder -> Dejar el equipo seedeando hasta que transcurra el tiempo indicado o un kill desde consola, mode=peer -> seedear mientras descarga mode=leecher -> NO seedear mientras descarga time tiempo que una vez descargada la imagen queremos dejar al cliente como seeder. +#@todo: +#@version 0.1 - Integración para OpenGNSys. +#@author Antonio J. Doblas Viso. Universidad de Málaga +#@date +#@version 0.2 - Chequeo del tamaño de imagen descargado. +#@author Irina . Univesidad de Sevilla. +#@date +#@version 0.3 - Control de los modos de operación, y estado de descarga. +#@author Antonio J. Doblas Viso. Univesidad de Málaga. +#@date +#@version 0.4 - Enviadando señal (2) a ctorrent permiendo la comunicación final con tracker +#@author Antonio J. Doblas Viso. Univesidad de Málaga. +#@date +#*/ ## +function ogTorrentStart () +{ + +# Variables locales. +local ARGS ARG TARGETDIR TARGETFILE SESSION ERROR +ERROR=0 + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME $FUNCNAME [ str_repo] [ [Relative_path_fileTORRENT] | [str_REPOSITORY path_fileTORRENT] | [int_ndisk int_npart path_fileTORRENT ] ] SessionTorrent" \ + "$FUNCNAME CACHE /PS1_PH1.img.torrent seeder:10000" \ + "$FUNCNAME /opt/opengnsys/cache/linux.iso peer:60" \ + "$FUNCNAME 1 1 /linux.iso.torrent leecher:60" + return +fi + +case "$1" in + /*) # Camino completo. */ (Comentrio Doxygen) + SOURCE=$(ogGetPath "$1") + ARG=2 + ;; + [1-9]*) # ndisco npartición. + SOURCE=$(ogGetPath "$1" "$2" "$3") + ARG=4 + ;; + *) # Otros: Solo cache (no se permiten caminos relativos). + SOURCE=$(ogGetPath "$1" "$2" 2>/dev/null) + ARG=3 + ;; +esac + +# Error si no se reciben los argumentos ARG necesarios según la opcion. +[ $# == "$ARG" ] || ogRaiseError $OG_ERR_FORMAT "Parametros no admitidos"|| return $? + +#controlar source, que no se haga al repo. +if [ $ARG == "3" ] +then + ogCheckStringInGroup "$1" "CACHE cache" || ogRaiseError $OG_ERR_FORMAT "La descarga torrent solo se hace desde local, copia el torrent a la cache y realiza la operación desde esa ubicación" || return $? +fi +if [ $ARG == "2" ] +then + if `ogCheckStringInReg "$1" "^/opt/opengnsys/images"` + then + ogRaiseError $OG_ERR_FORMAT "La descarga torrent solo se hace desde local, copia el torrent a la cache y realiza la operación desde esa ubicación" + return $? + fi +fi + +#controlar el source, para que sea un torrent. +ctorrent -x ${SOURCE} &> /dev/null; [ $? -eq 0 ] || ogRaiseError $OG_ERR_NOTFOUND "${ARGS% $*}" || return $? + +TARGET=`echo $SOURCE | awk -F.torrent '{print $1}'` +DIRSOURCE=`ogGetParentPath $SOURCE` +cd $DIRSOURCE + + + +SESSION=${!ARG} +OIFS=$IFS; IFS=':' ; SESSION=($SESSION); IFS=$OIFS +[[ ${#SESSION[*]} == 2 ]] || ogRaiseError $OG_ERR_FORMAT "parametros session Torrent no completa: modo:tiempo" || ERROR=1# return $? +#controlamos el modo de operación del cliente- +ogCheckStringInGroup ${SESSION[0]} "seeder SEEDER peer PEER leecher LEECHER" || ogRaiseError $OG_ERR_FORMAT "valor modo Torrent no valido ${SESSION[0]}" || ERROR=1 #return $? +MODE=${SESSION[0]} +#contolamos el tiempo para el seeder o una vez descargada la imagen como peer o leecher. +ogCheckStringInReg ${SESSION[1]} "^[0-9]{1,10}$" || ogRaiseError $OG_ERR_FORMAT "valor tiempo no valido ${SESSION[1]}" || ERROR=1 # return $? +TIME=${SESSION[1]} +# si ha habido error en el control de parametros error. +[ "$ERROR" == "1" ] && return 1 + + +#SYNTAXSEEDER="echo MODE seeder ctorrent ; (sleep \$TIME && kill -9 \`pidof ctorrent\`) & ; ctorrent \${SOURCE}" + +# si No fichero .bf, y Si fichero destino imagen ya descargada y su chequeo fue comprobado en su descarga inicial. +if [ ! -f ${SOURCE}.bf -a -f ${TARGET} ] +then + echo "imagen ya descargada" + case "$MODE" in + seeder|SEEDER) + echo "MODE seeder ctorrent" #### ${SOURCE} -X 'sleep $TIME; kill -9 \$(pidof ctorrent)' -C 100" + (sleep $TIME && kill -2 `pidof ctorrent`) & + ctorrent -f ${SOURCE} + esac + return 0 +fi + +#Si no existe bf ni fichero destino descarga inicial. +if [ ! -f ${SOURCE}.bf -a ! -f ${TARGET} ] +then + OPTION=DOWNLOAD + echo "descarga inicial" +fi + +# Si fichero bf descarga anterior no completada -. +if [ -f ${SOURCE}.bf -a -f ${TARGET} ] +then + echo Continuar con Descargar inicial no terminada. + OPTION=DOWNLOAD +fi + +if [ "$OPTION" == "DOWNLOAD" ] +then + case "$MODE" in + peer|PEER) + echo "Donwloading Torrent as peer" ### echo "ctorrent -X 'sleep $TIME; kill -9 \$(pidof ctorrent)' -C 100 $SOURCE -s $TARGET -b ${SOURCE}" + # Creamos el fichero de resumen por defecto + touch ${SOURCE}.bf + # ctorrent controla otro fichero -b ${SOURCE}.bfog + ctorrent -f -c -X "sleep $TIME; kill -2 \$(pidof ctorrent)" -C 100 ${SOURCE} -s ${TARGET} -b ${SOURCE}.bfog + ;; + leecher|LEECHER) + echo "Donwloading Torrent as leecher" # echo "ctorrent ${SOURCE} -X 'sleep 30; kill -9 \$(pidof ctorrent)' -C 100 -U 0" + ctorrent ${SOURCE} -X "sleep 30; kill -2 \$(pidof ctorrent)" -C 100 -U 0 + ;; + seeder|SEEDER) + echo "MODE seeder ctorrent" #### ${SOURCE} -X 'sleep $TIME; kill -9 \$(pidof ctorrent)' -C 100" + # Creamos el fichero de resumen por defecto + touch ${SOURCE}.bf + # ctorrent controla otro fichero -b ${SOURCE}.bfog + ctorrent -f -c -X "sleep $TIME; kill -2 \$(pidof ctorrent)" -C 100 ${SOURCE} -s ${TARGET} -b ${SOURCE}.bfog + ;; + esac +fi +cd /tmp +} + +#/** +# ogCreateTorrent [ str_repo | int_ndisk int_npart ] Relative_path_file +#@brief Función para crear el fichero torrent. +#@param str_pathDirectory str_Relative_path_file +#@param int_disk int_partition str_Relative_path_file +#@param str_REPOSITORY(CACHE - LOCAL) str_Relative_path_file +#@return +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. +#@exception OG_ERR_NOTOS La partición no tiene instalado un sistema operativo. +#@note +#@version 0.1 - Integración para OpenGNSys. +#@author Antonio J. Doblas Viso. Universidad de Málaga +#@date +#@version 0.2 - Integración para btlaunch. +#@author Irina . Univesidad de Sevilla. +#@date +#*/ ## + +function ogCreateTorrent () +{ +# Variables locales. +local ARGS ARG SOURCE EXT IPTORRENT + + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME [str_REPOSITORY] [int_ndisk int_npart] Relative_path_file IpBttrack" \ "$FUNCNAME 1 1 /aula1/winxp 10.1.15.23" \ + "$FUNCNAME REPO /aula1/winxp 10.1.15.45" + + return +fi + +# Error si se quiere crear el fichero en cache y no existe +[ "$1" != "CACHE" ] || `ogFindCache >/dev/null` || ogRaiseError $OG_ERR_NOTFOUND "CACHE"|| return $? + +case "$1" in + /*) # Camino completo. */ (Comentrio Doxygen) + SOURCE=$(ogGetPath "$1.img") + ARG=2 + ;; + [1-9]*) # ndisco npartición. + SOURCE=$(ogGetPath "$1" "$2" "$3.img") + ARG=4 + ;; + *) # Otros: repo, cache, cdrom (no se permiten caminos relativos). + EXT=$(ogGetImageType "$1" "$2") + SOURCE=$(ogGetPath "$1" "$2.$EXT") + ARG=3 + ;; +esac + +# Error si no se reciben los argumentos ARG necesarios según la opcion. +[ $# -eq "$ARG" ] || ogRaiseError $OG_ERR_FORMAT || return $? + + +# Error si no existe la imagen +[ $SOURCE ] || ogRaiseError $OG_ERR_NOTFOUND || return $? + +[ -r $SOURCE.torrent ] && mv "$SOURCE.torrent" "$SOURCE.torrent.ant" && echo "Esperamos que se refresque el servidor" && sleep 20 + +IPTORRENT="${!#}" +# Si ponemos el path completo cuando creamos el fichero torrent da error +cd `dirname $SOURCE` +echo ctorrent -t `basename $SOURCE` -u http://$IPTORRENT:6969/announce -s $SOURCE.torrent +ctorrent -t `basename $SOURCE` -u http://$IPTORRENT:6969/announce -s $SOURCE.torrent + +} + + +#/** +# ogUpdateCacheIsNecesary [ str_repo ] Relative_path_file_OGIMG_with_/ +#@brief Comprueba que el fichero que se desea almacenar en la cache del cliente, no esta. +#@param 1 str_REPO +#@param 2 str_Relative_path_file_OGIMG_with_/ +#@param 3 md5 to check: use full to check download image torrent +#@return 0 (true) cache sin imagen, SI es necesario actualizar el fichero. +#@return 1 (false) imagen en la cache, NO es necesario actualizar el fichero +#@return >1 (false) error de sintaxis (TODO) +#@note +#@todo: Proceso en el caso de que el fichero tenga el mismo nombre, pero su contenido sea distinto. +#@todo: Se dejan mensajes mientras se confirma su funcionamiento. +#@version 0.1 - Integracion para OpenGNSys. +#@author Antonio J. Doblas Viso. Universidad de Malaga +#@date +#@version 1.6 - gestiona ficheros hash full.sum (TORRENT) y .sum (MULTICAST) +#@author Antonio J. Doblas Viso. Universidad de Malaga +#@date +#*/ ## +function ogUpdateCacheIsNecesary () +{ +#echo "admite full check con 3param TORRENT" +# Variables locales. +local ERROR SOURCE CACHE FILESOURCE MD5SOURCE FILETARGET MD5TARGET +ERROR=0 + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME str_repo relative_path_image [protocol|FULL]" \ + "$FUNCNAME REPO /PS1_PH1.img UNICAST" \ + "$FUNCNAME REPO /ogclient.sqfs FULL" + + return +fi + +#Control de la cache +ogFindCache &>/dev/null || return $(ogRaiseError $OG_ERR_NOTCACHE; echo $?) + +#Control de parametros: ahora admite tres. +[ $# -ge 2 ] || return $(ogRaiseError $OG_ERR_FORMAT "$MSG_FORMAT: $PROG str_repo relative_path_image [protocol|FULL]"; echo $?) + +ogCheckStringInGroup "$1" "REPO repo" || return $(ogRaiseError $OG_ERR_NOTFOUND " $1 $2"; echo $?) +FILESOURCE=`ogGetPath $1 $2` +[ -n "$FILESOURCE" ] || return $(ogRaiseError $OG_ERR_NOTFOUND " $1 $2"; echo $?) + +#echo "paso 1. si no existe la imagen, confirmar que es necesario actualizar la cache." +FILETARGET=`ogGetPath CACHE $2` +if [ -z "$FILETARGET" ] +then + # borramos el fichero bf del torrent, en el caso de que se hubiese quedado de algun proceso fallido + [ -n "$(ogGetPath CACHE "/$2.torrent.bf")" ] && ogDeleteFile CACHE "/$2.torrent.bf" &> /dev/null + [ -n "$(ogGetPath CACHE "/$2.sum")" ] && ogDeleteFile CACHE "/$2.sum" &> /dev/null + [ -n "$(ogGetPath CACHE "/$2.full.sum")" ] && ogDeleteFile CACHE "/$2.full.sum" &> /dev/null + echo "TRUE(0), es necesario actualizar. Paso 1, la cache no contiene esa imagen " + return 0 +fi + +#echo "Paso 2. Comprobamos que la imagen no estuviese en un proceso previo torrent" +if [ -n "$(ogGetPath "$FILETARGET.torrent.bf")" ]; then + #TODO: comprobar los md5 del fichero .torrent para asegurarnos que la imagen a descarga es la misma. + echo "TRUE(0), es necesario actualizar. Paso 2, la imagen esta en un estado de descarga torrent interrumpido" + return 0 +fi + +## En este punto la imagen en el repo y en la cache se llaman igual, +#echo "paso 4. Obtener los md5 del fichero imagen en la cacha segun PROTOCOLO $3" +case "${3^^}" in + FULL|TORRENT) + #Buscamos MD5 en el REPO SOURCE + if [ -f $FILESOURCE.full.sum ] + then + MD5SOURCE=$(cat $FILESOURCE.full.sum) + else + MD5SOURCE=$(ogCalculateFullChecksum $FILESOURCE) + fi + # Generamos el MD5 (full) en la CACHE + [ ! -f $FILETARGET.full.sum ] && ogCalculateFullChecksum $FILETARGET > $FILETARGET.full.sum + MD5TARGET=$(cat $FILETARGET.full.sum) + # Generamos el MD5 (little) en la CACHE para posteriores usos del protocolo MULTICAST + [ ! -f $FILETARGET.sum ] && ogCalculateChecksum $FILETARGET > $FILETARGET.sum + ;; + *) + #Buscamos MD5 en el REPO SOURCE + if [ -f $FILESOURCE.sum ] + then + MD5SOURCE=$(cat $FILESOURCE.sum) + else + MD5SOURCE=$(ogCalculateChecksum $FILESOURCE) + fi + # Generamos el MD5 (little) en la CACHE + [ ! -f $FILETARGET.sum ] && ogCalculateChecksum $FILETARGET > $FILETARGET.sum + MD5TARGET=$(cat $FILETARGET.sum) + #Generamos o copiamos MD5 (full) en la CACHE para posteriores usos con Torrent + # Si no existe el full.sum y si existe el .sum es porque el upateCACHE multicast o unicast ha sido correcto. + if [ ! -f $FILETARGET.full.sum -a $FILETARGET.sum ] + then + if [ -f $FILESOURCE.full.sum ] + then + #Existe el .full.sum en REPO realizamos COPIA + cp $FILESOURCE.full.sum $FILETARGET.full.sum + else + #No existe .full.sum no en REPO LO GENERAMOS en la cache: situacion dificil que ocurra + ogCalculateFullChecksum $FILETARGET > $FILETARGET.full.sum + fi + fi + +esac + +#echo "Paso 5. comparar los md5" +if [ "$MD5SOURCE" == "$MD5TARGET" ] +then + echo "FALSE (1), No es neceario actualizar. Paso5.A la imagen esta en cache" + return 1 +else + echo "imagen en cache distinta, borramos la imagen anterior" + rm -f $FILETARGET $FILETARGET.sum $FILETARGET.torrent $FILETARGET.full.sum + echo "TRUE (0), Si es necesario actualizar." + return 0 +fi +} + diff --git a/client/lib/engine/bin/ProtocolLib.py b/client/lib/engine/bin/ProtocolLib.py deleted file mode 100644 index 35b8a1e..0000000 --- a/client/lib/engine/bin/ProtocolLib.py +++ /dev/null @@ -1,915 +0,0 @@ -#!/usr/bin/python3 - -import subprocess -import re -import json -import os.path -import shutil - -import ogGlobals -import SystemLib -import ImageLib -import FileSystemLib -import StringLib -import NetLib -import DiskLib -import FileLib -import CacheLib - -#/** -#@file ProtocolLib.py -#@brief Librería o clase Protocol -#@class Protocol -#@brief Funciones para transmisión de datos -#@warning License: GNU GPLv3+ -#*/ - - -##################### FUNCIONES UNICAST ################ - -#/** -# ogUcastSyntax -#@brief Función para generar la instrucción de transferencia de datos unicast -#@param 1 Tipo de operación [ SENDPARTITION RECEIVERPARTITION SENDFILE RECEIVERFILE ] -#@param 2 Sesion Unicast -#@param 3 Dispositivo (opción PARTITION) o fichero(opción FILE) que será enviado. -#@param 4 Tools de clonación (opcion PARTITION) -#@param 5 Tools de compresion (opcion PARTITION) -#@return instrucción para ser ejecutada. -#@exception OG_ERR_FORMAT formato incorrecto. -#@exception OG_ERR_UCASTSYNTAXT formato de la sesion unicast incorrecta. -#@note Requisitos: mbuffer -#@todo: controlar que mbuffer esta disponible para los clientes. -#*/ ## - -#ogUcastSyntax SENDPARTITION 8000:172.17.36.11:172.17.36.12 device tool level -#ogUcastSyntax RECEIVERPARTITION 8000:172.17.36.249 device tool level - -#ogUcastSyntax SENDFILE 8000:172.17.36.11:172.17.36.12 file -#ogUcastSyntax RECEIVERFILE 8000:172.17.36.249 file - -def ogUcastSyntax (op, sess, file=None, device=None, tool=None, level=None): - if 'SENDPARTITION' == op or 'RECEIVERPARTITION' == op: - if device is None: - raise TypeError ('missing required argument: "device"') - if tool is None: - raise TypeError ('missing required argument: "tool"') - if tool.lower() not in ['partclone', 'partimage', 'ntfsclone']: - raise TypeError (f'argument "tool" has unsupported value "{tool}"') - if level is None: - raise TypeError ('missing required argument: "level"') - if level.lower() not in ['lzop', 'gzip', '0', '1']: - raise TypeError (f'argument "level" has unsupported value "{level}"') - elif 'SENDFILE' == op or 'RECEIVERFILE' == op: - if file is None: - raise TypeError ('missing required argument: "file"') - else: - raise TypeError ('first parameter should match (SEND|RECEIVER)(PARTITION|FILE), eg. "SENDFILE"') - - if 'SEND' in op: mode = 'server' - else: mode = 'client' - - session = sess.split (':') - - portbase = int (session[0]) - if portbase not in range (8000, 8006): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'McastSession portbase {portbase}') ## || PERROR=3 - return - - if 'server' == mode: - address = '' - for i in range (1, len (session)): - address += f' -O {session[i]}:{portbase}' - else: - address = f'{session[1]}:{portbase}' - - if 'SENDPARTITION' == op: - syn = ImageLib.ogCreateImageSyntax (device, ' ', tool, level) - ## REQUIRES package mbuffer to be installed!! - ## otherwise, param2 in ImageLib.ogCreateImageSyntax() is not '| mbuffer' but empty - ## and then parts[2] is out of range - parts = syn.split ('|') - prog1 = f'{parts[0]}|{parts[2]}'.strip() - prog1 = prog1.replace ('>', '').strip() - return f'{prog1} | mbuffer {address}' - elif 'RECEIVERPARTITION' == op: - syn = ImageLib.ogRestoreImageSyntax (' ', device, tool, level) - parts = syn.split ('|') - compressor = parts[0].strip() - tools = parts[-1].strip() - return f'mbuffer -I {address} | {compressor} | {tools}' - elif 'SENDFILE' == op: - return f'mbuffer {address} -i {file}' - elif 'RECEIVERFILE' == op: - return f'mbuffer -I {address} -i {file}' - else: - pass ## shouldn't happen - - -#/** -# ogUcastSendPartition -#@brief Función para enviar el contenido de una partición a multiples particiones remotas usando UNICAST. -#@param 1 disk -#@param 2 partition -#@param 3 sesionUcast -#@param 4 tool image -#@param 5 tool compresor -#@return -#@exception $OG_ERR_FORMAT -#@exception $OG_ERR_UCASTSENDPARTITION -#@note -#@todo: ogIsLocked siempre devuelve 1 -#*/ ## - -def ogUcastSendPartition (disk, par, sess, tool, level): - PART = DiskLib.ogDiskToDev (disk, par) - if not PART: return None - - FileSystemLib.ogUnmount (disk, par) - - cmd = ogUcastSyntax ('SENDPARTITION', sess, device=PART, tool=tool, level=level) - if not cmd: return None - try: - subprocess.run (cmd, shell=True, check=True) - except subprocess.CalledProcessError: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_UCASTSENDPARTITION, ' ') - return None - - - -#/** -# ogUcastReceiverPartition -#@brief Función para recibir directamente en la partición el contenido de un fichero imagen remoto enviado por UNICAST. -#@param 1 disk -#@param 2 partition -#@param 3 session unicast -#@param 4 tool image -#@param 5 tool compresor -#@return -#@exception OG_ERR_FORMAT -#@exception OG_ERR_UCASTRECEIVERPARTITION -#@note -#@todo: -#*/ ## -def ogUcastReceiverPartition (disk, par, sess, tool, level): - PART = DiskLib.ogDiskToDev (disk, par) - if not PART: return None - - FileSystemLib.ogUnmount (disk, par) - - cmd = ogUcastSyntax ('RECEIVERPARTITION', sess, device=PART, tool=tool, level=level) - if not cmd: return None - try: - subprocess.run (cmd, shell=True, check=True) - except subprocess.CalledProcessError: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_UCASTRECEIVERPARTITION, ' ') - return None - - - -#/** -# ogUcastSendFile [ str_repo | int_ndisk int_npart ] /Relative_path_file sessionMulticast -#@brief Envía un fichero por unicast ORIGEN(fichero) DESTINO(sessionmulticast) -#@param (2 parámetros) $1 path_aboluto_fichero $2 sesionMcast -#@param (3 parámetros) $1 Contenedor REPO|CACHE $2 path_absoluto_fichero $3 sesionMulticast -#@param (4 parámetros) $1 disk $2 particion $3 path_absoluto_fichero $4 sesionMulticast -#@return -#@exception OG_ERR_FORMAT formato incorrecto. -#@exception $OG_ERR_NOTFOUND -#@exception OG_ERR_UCASTSENDFILE -#@note Requisitos: -#*/ ## -# - -## TODO esta función es idéntica a ogMcastSendFile pero con s/Ucast/Mcast/; - -#ogUcastSendFile ([str_REPOSITORY] [int_ndisk int_npart] /Relative_path_file sesionMcast(puerto:ip:ip:ip)" \ -#ogUcastSendFile (disk=1, par=1, file='/aula1/winxp.img', sess='8000:172.17.36.11:172.17.36.12') -#ogUcastSendFile (container='REPO', file='/aula1/ubuntu.iso', sess='sesionUcast') -#ogUcastSendFile (container='CACHE', file='/aula1/winxp.img', sess='sesionUcast') -#ogUcastSendFile ( file='/opt/opengnsys/images/aula1/hd500.vmx', sess='sesionUcast') -def ogUcastSendFile (disk=None, par=None, container=None, file=None, sess=None): - if file is None: - raise TypeError ('missing required argument: "file"') - if sess is None: - raise TypeError ('missing required argument: "sess"') - - if container is not None: - if disk is None and par is None: - ## we were given container= - source = FileLib.ogGetPath (src=container, file=file) - dev_err = f'{container} {file}' - else: - raise TypeError ('argument "container" can be specified along neither "disk" nor "par"') - - else: - if disk is not None and par is not None: - ## we were given disk= par= - source = FileLib.ogGetPath (src=f'{disk} {par}', file=file) - dev_err = f'{disk} {par} {file}' - elif disk is None and par is None: - ## we were given nothing - source = FileLib.ogGetPath (file=file) - dev_err = file - else: - raise TypeError ('if one of "disk" and "par" are specified, then both must be') - - if not source: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'device or file {dev_err} not found') - return - - path2 = FileLib.ogGetPath (file=source) - if not path2: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'device or file {dev_err} not found') - return - - cmd = ogUcastSyntax ('SENDFILE', sess, file=source) - if not cmd: return None - try: - subprocess.run (cmd, shell=True, check=True) - except subprocess.CalledProcessError: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_UCASTSENDFILE, ' ') - return None - -def _clientip(): - ipas = subprocess.run (['ip', '-json', 'address', 'show', 'up'], capture_output=True, text=True).stdout - ipasj = json.loads (ipas) - addresses = [] - for e in ipasj: - if 'lo' == e['ifname']: continue - if 'addr_info' not in e: continue - addrs = e['addr_info'] - for a in addrs: - if 'inet' != a['family']: continue - addresses.append ({ 'local': a['local'], 'prefixlen': a['prefixlen'] }) - return addresses - -def _binary_ip (ip): - for l in subprocess.run (['ipcalc', '--nocolor', ip ], capture_output=True, text=True).stdout.splitlines(): - if 'Address' not in l: continue - match = re.search (r'^(Address:)\s+(\S+)\s+(.*$)', l).group(3).replace (' ', '').replace ('.', '') - break - return match - -#/** -# ogMcastSyntax -#@brief Función para generar la instrucción de ejucción la transferencia de datos multicast -#@param 1 Tipo de operación [ SENDPARTITION RECEIVERPARTITION SENDFILE RECEIVERFILE ] -#@param 2 Sesión Mulicast -#@param 3 Dispositivo (opción PARTITION) o fichero(opción FILE) que será enviado. -#@param 4 Tools de clonación (opcion PARTITION) -#@param 5 Tools de compresion (opcion PARTITION) -#@return instrucción para ser ejecutada. -#@exception OG_ERR_FORMAT formato incorrecto. -#@exception OG_ERR_NOTEXEC -#@exception OG_ERR_MCASTSYNTAXT -#@note Requisitos: upd-cast 2009 o superior -#@todo localvar check versionudp -#*/ ## -# - -#ogMcastSyntax SENDPARTITION 9000:full-duplex|half-duplex|broadcast:239.194.17.36:80M:50:60 device tools level -#ogMcastSyntax RECEIVERPARTITION 9000 device tools level -#ogMcastSyntax RECEIVERPARTITION 9000:172.17.88.161:40:120 device tools level - -#ogMcastSyntax SENDFILE 9000:full-duplex|half-duplex|broadcast:239.194.17.36:80M:50:60 file -#ogMcastSyntax RECEIVERFILE 9000 file -#ogMcastSyntax RECEIVERFILE 9000:172.17.88.161:40:120 file -def ogMcastSyntax (op, sess, file=None, device=None, tool=None, level=None): - if 'SENDPARTITION' == op or 'RECEIVERPARTITION' == op: - if device is None: - raise TypeError ('missing required argument: "device"') - if tool is None: - raise TypeError ('missing required argument: "tool"') - if tool.lower() not in ['partclone', 'partimage', 'ntfsclone']: - raise TypeError (f'argument "tool" has unsupported value "{tool}"') - if level is None: - raise TypeError ('missing required argument: "level"') - if level.lower() not in ['lzop', 'gzip', '0', '1']: - raise TypeError (f'argument "level" has unsupported value "{level}"') - elif 'SENDFILE' == op or 'RECEIVERFILE' == op: - if file is None: - raise TypeError ('missing required argument: "file"') - else: - raise TypeError ('first parameter should match (SEND|RECEIVER)(PARTITION|FILE), eg. "SENDFILE"') - - if 'SEND' in op: mode = 'server' - else: mode = 'client' - - try: - isudpcast = subprocess.run (['udp-receiver', '--help'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True).stdout - except subprocess.CalledProcessError: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTEXEC, 'upd-cast no existe') - return - - session = sess.split (':') - - PERROR = 0 - if 'server' == mode: - if 6 != len (session): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, 'parametros session de servidor multicast no completa') - PERROR = 2 - elif 'client' == mode: - if 4 < len (session): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, 'parametros session de cliente multicast no completa') - PERROR = 2 - - mbuffer = " --pipe 'mbuffer -q -m 20M' " - portbase = int (session[0]) - if portbase not in range (9000, 9100, 2): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'McastSession portbase {portbase}') - PERROR = 3 - - if 'server' == mode: - method, address, bitrate, nclients, maxtime = session[1:] - - if method.lower() not in ['full-duplex', 'half-duplex', 'broadcast']: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'McastSession method {method}') - PERROR = 4 - - if not StringLib.ogCheckIpAddress (address): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'McastSession address {address}') - PERROR = 5 - - ## the original regex has a backslash: ^[0-9]{1,3}\M$ - ## not sure why - if not re.search (r'^[0-9]{1,3}M$', bitrate): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'McastSession bitrate {bitrate}') - PERROR = 6 - - if not re.search (r'^[0-9]{1,10}$', nclients): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'McastSession nclients {nclients}') - PERROR = 7 - - if not re.search (r'^[0-9]{1,10}$', maxtime): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'McastSession maxtime {maxtime}') - PERROR = 8 - - cerror = '8x8/128' - syntaxserver = f'udp-sender {mbuffer} --nokbd --portbase {portbase} --{method} --mcast-data-address {address} --fec {cerror} --max-bitrate {bitrate} --ttl 16 --min-clients {nclients} --max-wait {maxtime} --autostart {maxtime} --log /tmp/mcast.log' - - if PERROR: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_MCASTSYNTAXT, f' {PERROR}') - return - - - if 'client' == mode: - other = session[1:] - serveraddress = other[0] if len (other) > 0 else '' - starttimeout = other[1] if len (other) > 1 else '' - receivertimeout = other[2] if len (other) > 2 else '' - - ## serveraddres - if StringLib.ogCheckIpAddress (serveraddress): - serveraddress = f' --mcast-rdv-address {serveraddress}' - else: - repoip = NetLib.ogGetRepoIp() - clientip = _clientip() - if 1 != len (clientip): - raise Exception ('more than one local IP address found') - c = clientip[0] - clientip = c['local'] - mascara = c['prefixlen'] - - ripbt = _binary_ip (repoip) - ipbt = _binary_ip (clientip) - reposubred = ripbt[0:mascara] - clientsubred = ipbt[0:mascara] - if reposubred == clientsubred: serveraddress = ' ' - else: serveraddress = f' --mcast-rdv-address {repoip}' - - ## starttimeout - if re.search (r'^[0-9]{1,10}$', starttimeout): - if 0 == starttimeout: starttimeout = ' ' - else: starttimeout = f' --start-timeout {starttimeout}' - else: - starttimeout = f' --start-timeout {ogGlobals.MCASTERRORSESSION}' - if 'start-timeout' not in isudpcast: starttimeout = ' ' - - ## receivertimeout - if re.search (r'^[0-9]{1,10}$', receivertimeout): - if 0 == receivertimeout: receivertimeout = ' ' - else: receivertimeout = f' --receive-timeout {receivertimeout}' - else: - receivertimeout = f' --receive-timeout {ogGlobals.MCASTWAIT}' - if 'receive-timeout' not in isudpcast: receivertimeout = ' ' - - syntaxclient = f'udp-receiver {mbuffer} --portbase {portbase} {serveraddress} {starttimeout} {receivertimeout} --log /tmp/mcast.log' - - if 'SENDPARTITION' == op: - syn = ImageLib.ogCreateImageSyntax (device, ' ', tool, level) - ## REQUIRES package mbuffer to be installed!! - ## otherwise, param2 in ImageLib.ogCreateImageSyntax() is not '| mbuffer' but empty - ## and then parts[2] is out of range - parts = syn.split ('|') - prog1 = f'{parts[0]}|{parts[2]}'.strip() - prog1 = prog1.replace ('>', '').strip() - return f'{prog1} | {syntaxserver}' - - elif 'RECEIVERPARTITION' == op: - syn = ImageLib.ogRestoreImageSyntax (' ', device, tool, level) - parts = syn.split ('|') - compressor = parts[0].strip() - tools = parts[-1].strip() - return f'{syntaxclient} | {compressor} | {tools} ' - - elif 'SENDFILE' == op: - return f'{syntaxserver} --file {file}' - - elif 'RECEIVERFILE' == op: - return f'{syntaxclient} --file {file}' - - else: - raise Exception (f'unknown op ({op})--this should not happen') - - - -#/** -# ogMcastSendFile [ str_repo | int_ndisk int_npart ] /Relative_path_file sessionMulticast -#@brief Envía un fichero por multicast ORIGEN(fichero) DESTINO(sessionmulticast) -#@param (2 parámetros) $1 path_aboluto_fichero $2 sesionMcast -#@param (3 parámetros) $1 Contenedor REPO|CACHE $2 path_absoluto_fichero $3 sesionMulticast -#@param (4 parámetros) $1 disk $2 particion $3 path_absoluto_fichero $4 sesionMulticast -#@return -#@exception OG_ERR_FORMAT formato incorrecto. -#@exception $OG_ERR_NOTFOUND -#@exception OG_ERR_MCASTSENDFILE -#*/ ## -# - -#ogMcastSendFile [str_REPOSITORY] [int_ndisk int_npart] /Relative_path_file sesionMcast" \ -#ogMcastSendFile (disk=1, par=1, file='/aula1/winxp.img', sess='sesionMcast') -#ogMcastSendFile (container='REPO', file='/aula1/ubuntu.iso', sess='sesionMcast') -#ogMcastSendFile (container='CACHE', file='/aula1/winxp.img', sess='sesionMcast') -#ogMcastSendFile ( file='/opt/opengnsys/images/aula1/hd500.vmx', sess='sesionMcast') -def ogMcastSendFile (disk=None, par=None, container=None, file=None, sess=None): - if file is None: - raise TypeError ('missing required argument: "file"') - if sess is None: - raise TypeError ('missing required argument: "sess"') - - if container is not None: - if disk is None and par is None: - ## we were given container= - source = FileLib.ogGetPath (src=container, file=file) - dev_err = f'{container} {file}' - else: - raise TypeError ('argument "container" can be specified along neither "disk" nor "par"') - - else: - if disk is not None and par is not None: - ## we were given disk= par= - source = FileLib.ogGetPath (src=f'{disk} {par}', file=file) - dev_err = f'{disk} {par} {file}' - elif disk is None and par is None: - ## we were given nothing - source = FileLib.ogGetPath (file=file) - dev_err = file - else: - raise TypeError ('if one of "disk" and "par" are specified, then both must be') - - if not source: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'device or file {dev_err} not found') - return - - path2 = FileLib.ogGetPath (file=source) - if not path2: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'device or file {dev_err} not found') - return - - cmd = ogMcastSyntax ('SENDFILE', sess, file=source) - if not cmd: return None - try: - subprocess.run (cmd, shell=True, check=True) - except subprocess.CalledProcessError: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_MCASTSENDFILE, ' ') - return None - - - -#/** -# ogMcastReceiverFile sesion Multicast [ str_repo | int_ndisk int_npart ] /Relative_path_file -#@brief Recibe un fichero multicast ORIGEN(sesionmulticast) DESTINO(fichero) -#@param (2 parámetros) $1 sesionMcastCLIENT $2 path_aboluto_fichero_destino -#@param (3 parámetros) $1 sesionMcastCLIENT $2 Contenedor REPO|CACHE $3 path_absoluto_fichero_destino -#@param (4 parámetros) $1 sesionMcastCLIENT $2 disk $3 particion $4 path_absoluto_fichero_destino -#@return -#@exception OG_ERR_FORMAT formato incorrecto. -#@exception $OG_ERR_MCASTRECEIVERFILE -#@note Requisitos: -#*/ ## -# - -#ogMcastReceiverFile ([ str_portMcast] [ [Relative_path_file] | [str_REPOSITORY path_file] | [int_ndisk int_npart path_file ] ]" \ -#ogMcastReceiverFile ( file='/PS1_PH1.img', sess='9000') -#ogMcastReceiverFile (container='CACHE', file='/aula1/PS2_PH4.img', sess='9000') -#ogMcastReceiverFile (disk=1, par=1, file='/isos/linux.iso', sess='9000') -def ogMcastReceiverFile (disk=None, par=None, container=None, file=None, sess=None): - if file is None: - raise TypeError ('missing required argument: "file"') - if sess is None: - raise TypeError ('missing required argument: "sess"') - - if container is not None: - if disk is None and par is None: - ## we were given container= - targetdir = FileLib.ogGetParentPath (src=container, file=file) - dev_err = f'{container} {file}' - else: - raise TypeError ('argument "container" can be specified along neither "disk" nor "par"') - - else: - if disk is not None and par is not None: - ## we were given disk= par= - targetdir = FileLib.ogGetParentPath (src=f'{disk} {par}', file=file) - dev_err = f'{disk} {par} {file}' - elif disk is None and par is None: - ## we were given nothing - targetdir = FileLib.ogGetParentPath (file=file) - dev_err = file - else: - raise TypeError ('if one of "disk" and "par" are specified, then both must be') - - if not targetdir: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'target directory {targetdir} not found') - return - - targetfile = os.path.basename (file) - - cmd = ogMcastSyntax ('RECEIVERFILE', sess, file=os.path.join (targetdir, targetfile)) - if not cmd: return None - try: - subprocess.run (cmd, shell=True, check=True) - except subprocess.CalledProcessError: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_MCASTRECEIVERFILE, targetfile) - return None - - -#/** -# ogMcastSendPartition -#@brief Función para enviar el contenido de una partición a multiples particiones remotas. -#@param 1 disk -#@param 2 partition -#@param 3 session multicast -#@param 4 tool clone -#@param 5 tool compressor -#@return -#@exception OG_ERR_FORMAT -#@exception OG_ERR_MCASTSENDPARTITION -#@note -#@todo: ogIsLocked siempre devuelve 1. crear ticket -#*/ ## - -#ogMcastSendPartition (disk, par, SessionMulticastSERVER, tools, compresor) -#ogMcastSendPartition (1, 1, '9000:full-duplex:239.194.37.31:50M:20:2', 'partclone', 'lzop') -def ogMcastSendPartition (disk, par, sess, tool, compressor): - PART = DiskLib.ogDiskToDev (disk, par) - if not PART: return - - FileSystemLib.ogUnmount (disk, par) - cmd = ogMcastSyntax ('SENDPARTITION', sess, device=PART, tool=tool, level=compressor) - if not cmd: return None - try: - subprocess.run (cmd, shell=True, check=True) - except subprocess.CalledProcessError: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_MCASTSENDPARTITION, ' ') - return None - -#/** -# ogMcastReceiverPartition -#@brief Función para recibir directamente en la partición el contenido de un fichero imagen remoto enviado por multicast. -#@param 1 disk -#@param 2 partition -#@param 3 session multicast -#@param 4 tool clone -#@param 5 tool compressor -#@return -#@exception $OG_ERR_FORMAT -#*/ ## -def ogMcastReceiverPartition (disk, par, sess, tool, compressor): - PART = DiskLib.ogDiskToDev (disk, par) - if not PART: return - - FileSystemLib.ogUnmount (disk, par) - cmd = ogMcastSyntax ('RECEIVERPARTITION', sess, device=PART, tool=tool, level=compressor) - if not cmd: return None - try: - subprocess.run (cmd, shell=True, check=True) - except subprocess.CalledProcessError: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_MCASTRECEIVERPARTITION, ' ') ## original code has OG_ERR_MCASTSENDPARTITION - return None - - - -#/** -# ogMcastRequest -#@brief Función temporal para solicitar al ogRepoAux el envio de un fichero por multicast -#@param 1 Fichero a enviar ubicado en el REPO. puede ser ruta absoluta o relatica a /opt/opengnsys/images -#@param 2 PROTOOPT opciones protocolo multicast -#*/ ## -## now ogCore takes this responsibility -def ogMcastRequest (img, proto): - return True - - -########################################## -############## funciones torrent -#/** -# ogTorrentStart [ str_repo | int_ndisk int_npart ] Relative_path_file.torrent | SessionProtocol -#@brief Función iniciar P2P - requiere un tracker para todos los modos, y un seeder para los modos peer y leecher y los ficheros .torrent. -#@param str_pathDirectory str_Relative_path_file -#@param int_disk int_partition str_Relative_path_file -#@param str_REPOSITORY(CACHE - LOCAL) str_Relative_path_file -#@param (2 parámetros) $1 path_aboluto_fichero_torrent $2 Parametros_Session_Torrent -#@param (3 parámetros) $1 Contenedor CACHE $2 path_absoluto_fichero_Torrent $3 Parametros_Session_Torrent -#@param (4 parámetros) $1 disk $2 particion $3 path_absoluto_fichero_Torrent 4$ Parametros_Session_Torrent -#@return -#@note protocoloTORRENT=mode:time mode=seeder -> Dejar el equipo seedeando hasta que transcurra el tiempo indicado o un kill desde consola, mode=peer -> seedear mientras descarga mode=leecher -> NO seedear mientras descarga time tiempo que una vez descargada la imagen queremos dejar al cliente como seeder. -#*/ ## -#ogTorrentStart ( torrentfile='/opt/opengnsys/cache/linux.iso', torrentsess='peer:60') -#ogTorrentStart (container='CACHE', torrentfile='/PS1_PH1.img.torrent', torrentsess='seeder:10000') -#ogTorrentStart (disk=1, par=1, torrentfile='/linux.iso.torrent', torrentsess='leecher:60') -def ogTorrentStart (disk=None, par=None, container=None, torrentfile=None, torrentsess=None): - if torrentfile is None: - raise TypeError ('missing required argument: "torrentfile"') - if torrentsess is None: - raise TypeError ('missing required argument: "torrentsess"') - - if container is not None: - if disk is None and par is None: - ## we were given container= - if 'CACHE' != container.upper(): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, 'La descarga torrent solo se hace desde local, copia el torrent a la cache y realiza la operación desde esa ubicación') - return None - source = FileLib.ogGetPath (src=container, file=torrentfile) - dev_err = f'{container} {torrentfile}' - else: - raise TypeError ('argument "container" can be specified along neither "disk" nor "par"') - - else: - if disk is not None and par is not None: - ## we were given disk= par= - source = FileLib.ogGetPath (src=f'{disk} {par}', file=torrentfile) - dev_err = f'{disk} {par} {torrentfile}' - elif disk is None and par is None: - ## we were given nothing - if torrentfile.startswith ('/opt/opengnsys/images'): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, 'La descarga torrent solo se hace desde local, copia el torrent a la cache y realiza la operación desde esa ubicación') - return None - source = FileLib.ogGetPath (file=torrentfile) - dev_err = torrentfile - else: - raise TypeError ('if one of "disk" and "par" are specified, then both must be') - - if not source: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'device or torrentfile {dev_err} not found') - return - - if subprocess.run (['ctorrent', '-x', source]).returncode: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, '') - return None - - target = re.sub (r'\.torrent$', '', source) - dirsource = FileLib.ogGetParentPath (file=source) - - ERROR = None - sess = torrentsess.split (':') - if 2 != len (sess): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, 'parametros session Torrent no completa: modo:tiempo') - return None - - mode = sess[0].lower() - if mode not in ['seeder', 'peer', 'leecher']: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'valor modo Torrent no valido {sess[0]}') - return None - - time = sess[1] - if not re.search (r'^[0-9]{1,10}$', time): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'valor tiempo no valido {sess[1]}') - return None - time = int (time) - - OPTION = None - cwd = os.getcwd() - # si No fichero .bf, y Si fichero destino imagen ya descargada y su chequeo fue comprobado en su descarga inicial. - if not os.path.exists (f'{source}.bf') and os.path.exists (target): - print ('imagen ya descargada') - if 'seeder' != mode: return 'success' ## return any true value - - print ('MODE seeder ctorrent') - os.chdir (dirsource) - subprocess.run (['timeout', '--signal', 'INT', time, 'ctorrent', '-f', source]) - os.chdir (cwd) - return 'success' - - #Si no existe bf ni fichero destino descarga inicial. - if not os.path.exists (f'{source}.bf') and not os.path.exists (target): - print ('descarga inicial') - OPTION = 'DOWNLOAD' - - # Si fichero bf descarga anterior no completada -. - if os.path.exists (f'{source}.bf') and os.path.exists (target): - print ('Continuar con Descargar inicial no terminada.') - OPTION = 'DOWNLOAD' - - if 'DOWNLOAD' != OPTION: return 'success' - - os.chdir (dirsource) - if 'peer' == mode: - print ('Donwloading Torrent as peer') - # Creamos el fichero de resumen por defecto - open (f'{source}.bf', 'w').close() - # ctorrent controla otro fichero -b ${SOURCE}.bfog - subprocess.run (['ctorrent', '-f', '-c', '-X', f'sleep {time}; kill -2 $(pidof ctorrent)', '-C', '100', source, '-s', target, '-b', f'{source}.bfog']) - elif 'leecher' == mode: - print ('Donwloading Torrent as leecher') - subprocess.run (['ctorrent', '${SOURCE}', '-X', 'sleep 30; kill -2 $(pidof ctorrent)', '-C', '100', '-U', '0']) - elif 'seeder' == mode: - print ('MODE seeder ctorrent') - # Creamos el fichero de resumen por defecto - open (f'{source}.bf', 'w').close() - # ctorrent controla otro fichero -b ${SOURCE}.bfog - subprocess.run (['ctorrent', '-f', '-c', '-X', f'sleep {time}; kill -2 $(pidof ctorrent)', '-C', '100', source, '-s', target, '-b', f'{source}.bfog']) - else: - print ('this should not happen') - return None - - os.chdir (cwd) - - -#/** -# ogCreateTorrent [ str_repo | int_ndisk int_npart ] Relative_path_file -#@brief Función para crear el fichero torrent. -#@param str_pathDirectory str_Relative_path_file -#@param int_disk int_partition str_Relative_path_file -#@param str_REPOSITORY(CACHE - LOCAL) str_Relative_path_file -#@return -#@exception OG_ERR_FORMAT Formato incorrecto. -#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. -#@exception OG_ERR_PARTITION Tipo de partición desconocido o no se puede montar. -#@exception OG_ERR_NOTOS La partición no tiene instalado un sistema operativo. -#*/ ## - -#ogCreateTorrent ([str_REPOSITORY] [int_ndisk int_npart] Relative_path_file IpBttrack) -#ogCreateTorrent (disk=1, par=1, file='/aula1/winxp', ip_bttrack='10.1.15.23') -#ogCreateTorrent (container='REPO', file='/aula1/winxp', ip_bttrack='10.1.15.45') -#ogCreateTorrent (container='CACHE', file='/aula1/winxp', ip_bttrack='10.1.15.45') -def ogCreateTorrent (disk=None, par=None, container=None, file=None, ip_bttrack=None): - if file is None: - raise TypeError ('missing required argument: "file"') - if ip_bttrack is None: - raise TypeError ('missing required argument: "ip_bttrack"') - - from_cache = False - - if container is not None: - if disk is None and par is None: - ## we were given container= - if 'CACHE' == container: from_cache = True - ext = ImageLib.ogGetImageType (container, file) - if ext is None: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'{container} {file}') - return - f = f'{file}.{ext}' - source = FileLib.ogGetPath (src=container, file=f) - else: - raise TypeError ('argument "container" can be specified along neither "disk" nor "par"') - - else: - if disk is not None and par is not None: - ## we were given disk= par= - f = f'{file}.img' - source = FileLib.ogGetPath (src=f'{disk} {par}', file=f) - elif disk is None and par is None: - ## we were given nothing - f = f'{file}.img' - source = FileLib.ogGetPath (file=f) - else: - raise TypeError ('if one of "disk" and "par" are specified, then both must be') - - if not source: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, '') - return - - if from_cache: - if not CacheLib.ogFindCache(): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, "CACHE") - #return None - - if os.path.exists (f'{source}.torrent'): - os.rename (f'{source}.torrent', f'{source}.torrent.ant') - print ('Esperamos que se refresque el servidor') - time.sleep (20) - - cwd = os.getcwd() - os.chdir (os.path.dirname (source)) - print (f'ctorrent -t {os.path.basename (source)} -u http://{ip_bttrack}:6969/announce -s {source}.torrent') - subprocess.run (['ctorrent', '-t', os.path.basename (source), '-u', f'http://{ip_bttrack}:6969/announce', '-s', f'{source}.torrent']) - os.chdir (cwd) - - -#/** -# ogUpdateCacheIsNecesary [ str_repo ] Relative_path_file_OGIMG_with_/ -#@brief Comprueba que el fichero que se desea almacenar en la cache del cliente, no esta. -#@param 1 str_REPO -#@param 2 str_Relative_path_file_OGIMG_with_/ -#@param 3 md5 to check: use full to check download image torrent -#@return True cache sin imagen, SI es necesario actualizar el fichero. -#@return False imagen en la cache, NO es necesario actualizar el fichero -#@return None error de sintaxis (TODO) -#@note -#@todo: Proceso en el caso de que el fichero tenga el mismo nombre, pero su contenido sea distinto. -#@todo: Se dejan mensajes mientras se confirma su funcionamiento. -#*/ ## -#ogUpdateCacheIsNecesary ('REPO', '/PS1_PH1.img', 'UNICAST') -#ogUpdateCacheIsNecesary ('REPO', '/ogclient.sqfs', 'FULL') -#ogUpdateCacheIsNecesary ('REPO', '/ogclient.sqfs', 'TORRENT') -def ogUpdateCacheIsNecesary (repo, file, proto): - if not CacheLib.ogFindCache(): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTCACHE, '') - return None - - if repo.lower() != 'repo': - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f' {repo} {file}') - return None - - filesource = FileLib.ogGetPath (src=repo, file=file) - if not filesource: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f' {repo} {file}') - return None - - # paso 1. si no existe la imagen, confirmar que es necesario actualizar la cache. - filetarget = FileLib.ogGetPath (src='CACHE', file=file) - if not filetarget: - # borramos el fichero bf del torrent, en el caso de que se hubiese quedado de algun proceso fallido - if FileLib.ogGetPath (src='CACHE', file=f'/{file}.torrent.bf'): ogDeleteFile (container='CACHE', file=f'{file}.torrent.bf') - if FileLib.ogGetPath (src='CACHE', file=f'/{file}.sum'): ogDeleteFile (container='CACHE', file=f'{file}.sum') - if FileLib.ogGetPath (src='CACHE', file=f'/{file}.full.sum'): ogDeleteFile (container='CACHE', file=f'{file}.full.sum') - print ('TRUE(0), es necesario actualizar. Paso 1, la cache no contiene esa imagen ') - return True - - # Paso 2. Comprobamos que la imagen no estuviese en un proceso previo torrent - if FileLib.ogGetPath (file=f'{filetarget}.torrent.bf'): - #TODO: comprobar los md5 del fichero .torrent para asegurarnos que la imagen a descarga es la misma. - print ('TRUE(0), es necesario actualizar. Paso 2, la imagen esta en un estado de descarga torrent interrumpido') - return True - - ## En este punto la imagen en el repo y en la cache se llaman igual, - # paso 4. Obtener los md5 del fichero imagen en la cacha segun PROTOCOLO $3 - if proto.lower() in ['full', 'torrent']: - #Buscamos MD5 en el REPO SOURCE - if os.path.exists (f'{filesource}.full.sum'): - with open (f'{filesource}.full.sum', 'r') as fd: - md5source = fd.read().strip() - else: - md5source = FileLib.ogCalculateFullChecksum (file=filesource) - - # Generamos el MD5 (full) en la CACHE - if not os.path.exists (f'{filetarget}.full.sum'): - fullck = FileLib.ogCalculateFullChecksum (file=filetarget) - with open (f'{filetarget}.full.sum', 'w') as fd: - fd.write (fullck + '\n') - with open (f'{filetarget}.full.sum', 'r') as fd: - md5target = fd.read().strip() - # Generamos el MD5 (little) en la CACHE para posteriores usos del protocolo MULTICAST - if not os.path.exists (f'{filetarget}.sum'): - ck = FileLib.ogCalculateChecksum (file=filetarget) - with open (f'{filetarget}.sum', 'w') as fd: - fd.write (ck + '\n') - else: - #Buscamos MD5 en el REPO SOURCE - if os.path.exists (f'{filesource}.sum'): - with open (f'{filesource}.sum', 'r') as fd: - md5source = fd.read().strip() - else: - md5source = FileLib.ogCalculateChecksum (file=filesource) - - # Generamos el MD5 (little) en la CACHE - if not os.path.exists (f'{filetarget}.sum'): - ck = FileLib.ogCalculateChecksum (file=filetarget) - with open (f'{filetarget}.sum', 'w') as fd: - fd.write (ck + '\n') - with open (f'{filetarget}.sum', 'r') as fd: - md5target = fd.read().strip() - #Generamos o copiamos MD5 (full) en la CACHE para posteriores usos con Torrent - # Si no existe el full.sum y si existe el .sum es porque el upateCACHE multicast o unicast ha sido correcto. - if not os.path.exists (f'{filetarget}.full.sum') and os.path.exists (f'{filetarget}.sum'): - if os.path.exists (f'{filesource}.full.sum'): - #Existe el .full.sum en REPO realizamos COPIA - shutil.copy2 (f'{filesource}.full.sum', f'{filetarget}.full.sum') - else: - #No existe .full.sum no en REPO LO GENERAMOS en la cache: situacion dificil que ocurra - fullck = FileLib.ogCalculateFullChecksum (file=filetarget) - with open (f'{filetarget}.full.sum', 'w') as fd: - fd.write (fullck + '\n') - - # Paso 5. comparar los md5 - if md5source == md5target: - print ('FALSE (1), No es neceario actualizar. Paso5.A la imagen esta en cache') - return False - else: - print ('imagen en cache distinta, borramos la imagen anterior') - for f in [f'{filetarget}', f'{filetarget}.sum', f'{filetarget}.torrent', f'{filetarget}.full.sum']: - os.unlink (f) - print ('TRUE (0), Si es necesario actualizar.') - return True diff --git a/client/lib/engine/bin/Registry.lib b/client/lib/engine/bin/Registry.lib new file mode 100755 index 0000000..60f7124 --- /dev/null +++ b/client/lib/engine/bin/Registry.lib @@ -0,0 +1,455 @@ +#!/bin/bash +#/** +#@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+ +#*/ + + +# Función ficticia para lanzar chntpw con timeout de 5 s., evitando cuelgues del programa. +function chntpw () +{ +local CHNTPW +CHNTPW=$(which drbl-chntpw) +CHNTPW=${CHNTPW:-$(which chntpw)} +timeout --foreground 5s $CHNTPW -e "$@" +} + + +#/** +# 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. +#@version 1.0.1 - Nueva función +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2011-05-25 +#*/ ## +function ogAddRegistryKey () +{ +# Variables locales. +local FILE + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME path_mountpoint str_hive str_key" \ + "$FUNCNAME /mnt/sda1 SOFTWARE '\Microsoft\NewKey'" + return +fi +# Error si no se reciben 3 parámetros. +[ $# == 3 ] || ogRaiseError $OG_ERR_FORMAT || return $? +# Camino del fichero de registro. +FILE=$(ogGetHivePath "$1" "$2") || return $? + +# Añadir nueva clave. +chntpw "$FILE" << EOT &> /dev/null +cd ${3%\\*} +nk ${3##*\\} +q +y +EOT +} + +#/** +# 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. +#@version 1.0.1 - Nueva función +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2011-05-25 +#*/ ## +function ogAddRegistryValue () +{ +# Variables locales. +local FILE TYPE + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME path_mountpoint str_hive str_valuename [str_valuetype]" \ + "$FUNCNAME /mnt/sda1 SOFTWARE '\Microsoft\NewKey\Value1'" \ + "$FUNCNAME /mnt/sda1 SOFTWARE '\Microsoft\NewKey\Value1' DWORD" + return +fi +# Error si no se reciben 3 o 4 parámetros. +[ $# == 3 -o $# == 4 ] || ogRaiseError $OG_ERR_FORMAT || return $? +# Camino del fichero de registro. +FILE=$(ogGetHivePath "$1" "$2") || return $? +case "${4^^}" in + STRING|"") TYPE=1 ;; + BINARY) TYPE=3 ;; + DWORD) TYPE=4 ;; + *) ogRaiseError $OG_ERR_OUTOFLIMIT "$4" + return $? ;; +esac + +# Devolver el dato del valor de registro. +# /* (comentario Doxygen) +chntpw "$FILE" << EOT &> /dev/null +cd ${3%\\*} +nv $TYPE ${3##*\\} +q +y +EOT +# (comentario Doxygen) */ +} + + +#/** +# 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. +#@version 1.0.1 - Nueva función +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2011-05-25 +#*/ ## +function ogDeleteRegistryKey () +{ +# Variables locales. +local FILE + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME path_mountpoint str_hive str_key" \ + "$FUNCNAME /mnt/sda1 SOFTWARE '\Microsoft\NewKey'" + return +fi +# Error si no se reciben 3 parámetros. +[ $# == 3 ] || ogRaiseError $OG_ERR_FORMAT || return $? +# Camino del fichero de registro. +FILE=$(ogGetHivePath "$1" "$2") || return $? + +# Añadir nueva clave. +chntpw "$FILE" << EOT &> /dev/null +cd ${3%\\*} +dk ${3##*\\} +q +y +EOT +} + + +#/** +# 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. +#@version 1.0.1 - Nueva función +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2011-05-25 +#*/ ## +function ogDeleteRegistryValue () +{ +# Variables locales. +local FILE + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME path_mountpoint str_hive str_valuename" \ + "$FUNCNAME /mnt/sda1 SOFTWARE '\Microsoft\NewKey\Value1'" + return +fi +# Error si no se reciben 3 parámetros. +[ $# == 3 ] || ogRaiseError $OG_ERR_FORMAT || return $? +# Camino del fichero de registro. +FILE=$(ogGetHivePath "$1" "$2") || return $? + +# Devolver el dato del valor de registro. +# /* (comentario Doxygen) +chntpw "$FILE" << EOT &> /dev/null +cd ${3%\\*} +dv ${3##*\\} +q +y +EOT +# (comentario Doxygen) */ +} + + +#/** +# 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. +#@version 1.0.1 - Nueva función +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2011-05-18 +#@version 1.1.0 - Soportar registro de un usuario local. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2015-10-14 +#*/ ## +function ogGetHivePath () +{ +# Variables locales. +local FILE HIVE + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME path_mountpoint [str_hive|str_user]" \ + "$FUNCNAME /mnt/sda1 SOFTWARE => /mnt/sda1/WINDOWS/System32/config/SOFTWARE" \ + "$FUNCNAME /mnt/sda1 user1 => /mnt/sda1/Users/user1/NTUSER.DAT" + return +fi +# Error si no se reciben 2 parámetros. +[ $# == 2 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +# Camino del fichero de registro de usuario o de sistema (de menor a mayor prioridad). +FILE="$(ogGetPath "/$1/Windows/System32/config/$2")" +[ -z "$FILE" ] && FILE="$(ogGetPath "/$1/Users/$2/NTUSER.DAT")" +[ -z "$FILE" ] && FILE="$(ogGetPath "/$1/winnt/system32/config/$2")" +[ -z "$FILE" ] && FILE="$(ogGetPath "/$1/Documents and Settings/$2/NTUSER.DAT")" +[ -f "$FILE" ] && echo "$FILE" || ogRaiseError $OG_ERR_NOTFOUND "$1 $2" || return $? +} + + +#/** +# 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. +#@version 0.9 - Adaptación para OpenGNSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2009-09-11 +#@version 1.1.0 - Soportar tipos BINARY (parejas hexadecimales separadas por espacio). +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2015-09-28 +#*/ ## +function ogGetRegistryValue () +{ +# Variables locales. +local FILE + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME path_mountpoint str_hive str_valuename" \ + "$FUNCNAME /mnt/sda1 SOFTWARE '\Microsoft\NewKey\Value1' ==> 1" + return +fi +# Error si no se reciben 3 parámetros. +[ $# == 3 ] || ogRaiseError $OG_ERR_FORMAT || return $? +# Camino del fichero de registro. +FILE=$(ogGetHivePath "$1" "$2") || return $? + +# Devolver el dato del valor de registro. +# /* (comentario Doxygen) +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 ${3%\\*} +cat ${3##*\\} +q +EOT +# (comentario Doxygen) */ +} + + +#/** +# 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. +#@version 0.9 - Adaptación para OpenGNSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2009-09-23 +#*/ ## +function ogListRegistryKeys () +{ +# Variables locales. +local FILE + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME path_mountpoint str_hive str_key" \ + "$FUNCNAME /mnt/sda1 SOFTWARE '\Microsoft\Windows\CurrentVersion'" + return +fi +# Error si no se reciben 3 parámetros. +[ $# == 3 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +# Camino del fichero de registro. +FILE=$(ogGetHivePath "$1" "$2") || return $? + +# Devolver la lista de claves de registro. +chntpw "$FILE" << EOT 2> /dev/null | awk 'BEGIN {FS="[<>]"} $1~/^ $/ {print $2}' +ls $3 +q +EOT +} + + +#/** +# 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. +#@version 1.0.1 - Nueva función. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2011-05-26 +#*/ ## +function ogListRegistryValues () +{ +# Variables locales. +local FILE + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME path_mountpoint str_hive str_key" \ + "$FUNCNAME /mnt/sda1 SOFTWARE '\Microsoft\Windows\CurrentVersion'" + return +fi +# Error si no se reciben 3 parámetros. +[ $# == 3 ] || ogRaiseError $OG_ERR_FORMAT || return $? +# Camino del fichero de registro. +FILE=$(ogGetHivePath "$1" "$2") || return $? + +# Devolver la lista de claves de registro. +chntpw "$FILE" << EOT 2> /dev/null | awk 'BEGIN {FS="[<>]"} $1~/REG_/ {print $2}' +ls $3 +q +EOT +} + + +#/** +# 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. +#@version 0.9 - Adaptación para OpenGNSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2009-09-24 +#@version 1.1.0 - Soportar tipos BINARY (parejas hexadecimales separadas por espacio). +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2015-09-28 +#*/ ## +function ogSetRegistryValue () +{ +# Variables locales. +local FILE i n tmpfile + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME path_mountpoint str_hive str_valuename str_data" \ + "$FUNCNAME /mnt/sda1 SOFTWARE '\Key\SubKey\StringValue' \"Abcde Fghij\"" \ + "$FUNCNAME /mnt/sda1 SOFTWARE '\Key\SubKey\DwordValue' 1" \ + "$FUNCNAME /mnt/sda1 SOFTWARE '\Key\SubKey\BinaryValue' \"04 08 0C 10\"" + return +fi +# Error si no se reciben 4 parámetros. +[ $# == 4 ] || ogRaiseError $OG_ERR_FORMAT || return $? +# Camino del fichero de registro. +FILE=$(ogGetHivePath "$1" "$2") || return $? + +# Fichero temporal para componer la entrada al comando "chntpw". +tmpfile=/tmp/chntpw$$ +trap "rm -f $tmpfile" 1 2 3 9 15 + +# Comprobar tipo de datos del valor del registro. +cat << EOT >$tmpfile +ls ${3%\\*} +q +EOT +if [ -n "$(chntpw "$FILE" < $tmpfile 2> /dev/null | grep "BINARY.*<${3##*\\}>")" ]; then + # Procesar tipo binario (incluir nº de bytes y líneas de 16 parejas hexadecimales). + [[ "$4 " =~ ^([0-9A-F]{2} )*$ ]] || ogRaiseError $OG_ERR_FORMAT "\"$4\"" || return $? + let n=${#4}+1 + cat << EOT >$tmpfile +cd ${3%\\*} +ed ${3##*\\} +$[n/3] +EOT + # Formato de líneas hexadecimales: :OFFSET XX YY ZZ ... (hasta 16 parejas). + for (( i=0; i> $tmpfile + done + echo -e "s\nq\ny" >> $tmpfile +else + # Cambiar el dato del valor de registro para cadenas y bytes. + cat << EOT >$tmpfile +cd ${3%\\*} +ed ${3##*\\} +$4 +q +y +EOT + +fi + +# Aplicar cambios. +chntpw "$FILE" < $tmpfile &> /dev/null +rm -f $tmpfile +} + + diff --git a/client/lib/engine/bin/RegistryLib.py b/client/lib/engine/bin/RegistryLib.py deleted file mode 100755 index 11a2c08..0000000 --- a/client/lib/engine/bin/RegistryLib.py +++ /dev/null @@ -1,380 +0,0 @@ -#/** -#@file RegistryLib.py -#@brief Librería o clase Registry -#@class Boot -#@brief Funciones para gestión del registro de Windows. -#@warning License: GNU GPLv3+ -#*/ - -import subprocess -import os -import re -import shutil -import tempfile - -import ogGlobals -import SystemLib -import FileLib - -# Función ficticia para lanzar chntpw con timeout de 5 s., evitando cuelgues del programa. -chntpw_exe = shutil.which ('drbl-chntpw') or shutil.which ('chntpw') -def chntpw (hivefile, input_file): - with open (input_file, 'r') as fd: - input_contents = fd.read() - return subprocess.run ([chntpw_exe, '-e', hivefile], timeout=5, input=input_contents, capture_output=True, text=True).stdout - -## en el codigo bash aparecen "${3%\\*}" y "${3##*\\}" varias veces -## ${3%\\*} es el "dirname" de una key del registro -## ${3##*\\} es el "basename" -def _split_k (k): - k_elems = k.split ('\\') - k_dirname = '\\'.join (k_elems[0:-1]) - k_basename = k_elems[-1] - return k_dirname, k_basename - -#/** -# 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 (mntpt, hive, k): - hivefile = ogGetHivePath (mntpt, hive) - if not hivefile: return - - k_dirname, k_basename = _split_k (k) - - with tempfile.NamedTemporaryFile (delete_on_close=False, prefix='chntpw-', mode='w') as f: - f.write (f'cd {k_dirname}\n') - f.write (f'nk {k_basename}\n') - f.write ('q\ny\n') - f.close() - chntpw (hivefile, f.name) - os.remove (f.name) - -#/** -# 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. -#*/ ## -#ogAddRegistryValue ('/mnt/sda1', 'SOFTWARE', '\Microsoft\NewKey\Value1') ## type STRING by default -#ogAddRegistryValue ('/mnt/sda1', 'SOFTWARE', '\Microsoft\NewKey\Value1', 'STRING') -#ogAddRegistryValue ('/mnt/sda1', 'SOFTWARE', '\Microsoft\NewKey\Value1', 'BINARY') -#ogAddRegistryValue ('/mnt/sda1', 'SOFTWARE', '\Microsoft\NewKey\Value1', 'DWORD') -def ogAddRegistryValue (mntpt, hive, k, vtype='STRING'): - hivefile = ogGetHivePath (mntpt, hive) - if not hivefile: return - - k_dirname, k_basename = _split_k (k) - - # Determine the value type. - if 'STRING' == vtype.upper(): TYPE = 1 - elif 'BINARY' == vtype.upper(): TYPE = 3 - elif 'DWORD' == vtype.upper(): TYPE = 4 - else: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_OUTOFLIMIT, vtype) - return - - with tempfile.NamedTemporaryFile (delete_on_close=False, prefix='chntpw-', mode='w') as f: - f.write (f'cd {k_dirname}\n') - f.write (f'nv {TYPE} {k_basename}\n') - f.write ('q\ny\n') - f.close() - chntpw (hivefile, f.name) - os.remove (f.name) - - -#/** -# 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 (mntpt, hive, k): - hivefile = ogGetHivePath (mntpt, hive) - if not hivefile: return - - k_dirname, k_basename = _split_k (k) - - with tempfile.NamedTemporaryFile (delete_on_close=False, prefix='chntpw-', mode='w') as f: - f.write (f'cd {k_dirname}\n') - f.write (f'dk {k_basename}\n') - f.write ('q\ny\n') - f.close() - chntpw (hivefile, f.name) - os.remove (f.name) - - -#/** -# 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. -#*/ ## -#ogDeleteRegistryValue ('/mnt/sda1', 'SOFTWARE', '\Microsoft\NewKey\Value1') -def ogDeleteRegistryValue (mntpt, hive, k): - hivefile = ogGetHivePath (mntpt, hive) - if not hivefile: return - - k_dirname, k_basename = _split_k (k) - - with tempfile.NamedTemporaryFile (delete_on_close=False, prefix='chntpw-', mode='w') as f: - f.write (f'cd {k_dirname}\n') - f.write (f'dv {k_basename}\n') - f.write ('q\ny\n') - f.close() - chntpw (hivefile, f.name) - os.remove(f.name) - - -#/** -# 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', 'user1') => /mnt/sda1/Users/user1/NTUSER.DAT -#ogGetHivePath ('/mnt/sda1', 'SYSTEM') => //mnt/sda1/Windows/System32/config/SYSTEM -#ogGetHivePath ('/mnt/sda1', 'IEUser') => //mnt/sda1/Users/IEUser/NTUSER.DAT -def ogGetHivePath(mntpt, hive): - # Camino del fichero de registro de usuario o de sistema (de menor a mayor prioridad). - FILE = FileLib.ogGetPath(file=f"/{mntpt}/Windows/System32/config/{hive}") - if not FILE: FILE = FileLib.ogGetPath(file=f"/{mntpt}/Users/{hive}/NTUSER.DAT") - if not FILE: FILE = FileLib.ogGetPath(file=f"/{mntpt}/winnt/system32/config/{hive}") - if not FILE: FILE = FileLib.ogGetPath(file=f"/{mntpt}/Documents and Settings/{hive}/NTUSER.DAT") - if FILE and os.path.isfile(FILE): - return FILE - else: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'{mntpt} {hive}') - return None - - -## simulate 'grep --after-context 1' -def _grep_A1 (strings, search_term): - results = [] - for i in range (len (strings)): - if search_term in strings[i]: - results.append (strings[i]) - if i + 1 < len(strings): - results.append (strings[i + 1]) - - return results - -#/** -# 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 (mntpt, hive, k): - hivefile = ogGetHivePath(mntpt, hive) - if not hivefile: return - - k_dirname, k_basename = _split_k (k) - - with tempfile.NamedTemporaryFile (delete_on_close=False, prefix='chntpw-', mode='w') as f: - f.write (f'cd {k_dirname}\n') - f.write (f'cat {k_basename}\n') - f.write ('q\n') - f.close() - chntpw_out = chntpw (hivefile, f.name) - os.remove (f.name) - - lines = chntpw_out.splitlines() - lines = _grep_A1 (lines, '> Value') - if 2 != len (lines): - return None - - ret = None - if 'REG_BINARY' in lines[0]: - if re.search ('^:[0-9A-F]+ ', lines[1]): - ret = lines[1][8:56] - else: - ret = lines[1] - return ret - - -#/** -# 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. -#*/ ## -#ogListRegistryKeys ('/mnt/sda1', 'SOFTWARE', '\Microsoft\Windows\CurrentVersion') -def ogListRegistryKeys (mntpt, hive, k): - hivefile = ogGetHivePath(mntpt, hive) - if not hivefile: return - - with tempfile.NamedTemporaryFile (delete_on_close=False, prefix='chntpw-', mode='w') as f: - f.write (f'ls {k}\n') - f.write ('q\n') - f.close() - chntpw_out = chntpw (hivefile, f.name) - os.remove (f.name) - - lines = chntpw_out.splitlines() - ret = [] - for l in lines: - elems = re.split ('[<>]', l) - if len(elems) < 2: continue - if ' ' == elems[0]: - ret.append (elems[1]) - return ret - - -#/** -# 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. -#*/ ## -#ogListRegistryValues ('/mnt/sda1', 'SOFTWARE', '\Microsoft\Windows\CurrentVersion') -def ogListRegistryValues (mntpt, hive, k): - hivefile = ogGetHivePath(mntpt, hive) - if not hivefile: return - - with tempfile.NamedTemporaryFile (delete_on_close=False, prefix='chntpw-', mode='w') as f: - f.write (f'ls {k}\n') - f.write ('q\n') - f.close() - chntpw_out = chntpw (hivefile, f.name) - os.remove (f.name) - - lines = chntpw_out.splitlines() - ret = [] - for l in lines: - elems = re.split ('[<>]', l) - if len(elems) < 2: continue - if 'REG_' in elems[0]: - ret.append (elems[1]) - return ret - - -def _format_hex (hex_string): - result = [] - offset = 0 - - hex_values = hex_string.strip().split() - result.append (str (len (hex_values))) - - while hex_values: - chunk = hex_values[:16] - hex_values = hex_values[16:] - - offset_str = f':{offset:05x} ' - hex_line = ' '.join (chunk) - result.append (offset_str + hex_line) - - offset += 16 - - return '\n'.join (result) - -#/** -# 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. -#*/ ## -#ogSetRegistryValue ('/mnt/sda1', 'SOFTWARE', '\Key\SubKey\StringValue', 'Abcde Fghij') -#ogSetRegistryValue ('/mnt/sda1', 'SOFTWARE', '\Key\SubKey\DwordValue', 1) -#ogSetRegistryValue ('/mnt/sda1', 'SOFTWARE', '\Key\SubKey\BinaryValue', '04 08 0C 10') -def ogSetRegistryValue (mntpt, hive, k, v): - hivefile = ogGetHivePath (mntpt, hive) - if not hivefile: return - - k_dirname, k_basename = _split_k (k) - - with tempfile.NamedTemporaryFile (delete_on_close=False, prefix='chntpw-', mode='w') as f: - f.write (f"ls {k_dirname}\n") - f.write ('q\n') - f.close() - chntpw_out = chntpw (hivefile, f.name) - os.remove(f.name) - - if re.search (f"BINARY.*<{k_basename}>", chntpw_out): - ## the entry in the registry is binary. Our input should be a sequence of bytes - - if ' ' != v[-1]: v += ' ' ## the regex below requires a trailing space - if not re.match (r'^([0-9A-F]{2} )*$', v.upper()): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'"{v}"') - return - - formatted = _format_hex (v.upper()) - formatted += '\ns' - else: - formatted = v - - with tempfile.NamedTemporaryFile (delete_on_close=False, prefix='chntpw-', mode='w') as f: - f.write (f'cd {k_dirname}\n') - f.write (f'ed {k_basename}\n') - f.write (f'{formatted}\n') - f.write ('q\ny\n') - f.close() - chntpw (hivefile, f.name) - os.remove(f.name) diff --git a/client/lib/engine/bin/String.lib b/client/lib/engine/bin/String.lib new file mode 100755 index 0000000..5774fe7 --- /dev/null +++ b/client/lib/engine/bin/String.lib @@ -0,0 +1,122 @@ +#!/bin/bash + +#/** +# ogCheckStringInGroup +#@brief Función para determinar si el elemento pertenece a un conjunto +#@param 1 elemento a comprobar +#@param 2 grupo de elementos para comprobar tipo "valor1 valor2 valor3" +#@return 0 si pertenece al grupo +#@return 1 si NO pertenece al grupo +#@exception OG_ERR_FORMAT formato incorrecto. +#@note +#@todo +#@version 0.91 - Definición de +#@author Antonio Doblas Viso, Universidad de Málaga +#@date 2010/05/09 +#*/ ## + +function ogCheckStringInGroup () +{ +local i +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME str_elemento str_grupo" \ + "$FUNCNAME full-duplex \"full-duplex half-duplex broadcast\" " + return +fi + +# Error si no se recibe 2 parámetro. +[ $# == 2 ] || ogRaiseError $OG_ERR_FORMAT || return $? + + +for i in `echo $2` +do + if [ "$1" == "$i" ] + then + return 0 + fi +done + +return 1 +} + +#/** +# ogCheckStringInReg +#@brief Función para determinar si el elemento contiene una "expresión regular" +#@param 1 elemento a comprobar +#@param 2 expresión regular" +#@return 0 si coincide con la expresión +#@return 1 si NO coincide con la expresión +#@exception OG_ERR_FORMAT formato incorrecto. +#@note +#@todo +#@version 0.91 - Definición de +#@author Antonio Doblas Viso, Universidad de Málaga +#@date 2010/05/09 +#*/ ## + +function ogCheckStringInReg() +{ + +local REG + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME str_elemento str_expresión_regular" \ + "$FUNCNAME 50M \"^[0-9]{1,2}\M$\" " + return +fi + +# Error si no se recibe 2 parámetro. +[ $# == 2 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +REG=$2 +[[ $1 =~ $REG ]] && return 0 || return 1 +} + + + +#/** +# ogCheckIpAddress +#@brief Función para determinar si una cadena es una dirección ipv4 válida +#@param 1 string de la ip a comprobar +#@return 0 si es una dirección válida +#@return 1 si NO es una dirección válida +#@exception OG_ERR_FORMAT formato incorrecto. +#@note +#@todo +#@version 0.91 - Definición de +#@author Antonio Doblas Viso, Universidad de Málaga +#@date 2010/05/09 +#*/ ## + +function ogCheckIpAddress() +{ +local REG IP arrIP + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME str_IpAddressToCheck" \ + "$FUNCNAME 192.18.35.3" + return +fi + +# Error si no se recibe 1 parámetro. +[ $# == 1 ] || ogRaiseError $OG_ERR_FORMAT || return $? + + +IP=$1 +REG="^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$" +if [[ "$IP" =~ $REG ]] +then + OIFS=$IFS; + IFS='.' ; + arrIP=($IP) + IFS=$OIFS + if [[ ${arrIP[0]} -le 255 && ${arrIP[1]} -le 255 && ${arrIP[2]} -le 255 && ${arrIP[3]} -le 255 ]] + then + return 0 + fi +fi +return 1 +} diff --git a/client/lib/engine/bin/StringLib.py b/client/lib/engine/bin/StringLib.py deleted file mode 100755 index eda1c93..0000000 --- a/client/lib/engine/bin/StringLib.py +++ /dev/null @@ -1,31 +0,0 @@ -import re - - - -#/** -# ogCheckIpAddress -#@brief Función para determinar si una cadena es una dirección ipv4 válida -#@param 1 string de la ip a comprobar -#@return 0 si es una dirección válida -#@return 1 si NO es una dirección válida -#@exception OG_ERR_FORMAT formato incorrecto. -#@note -#@todo -#*/ ## -def ogCheckIpAddress(ip): - """ - Función para determinar si una cadena es una dirección ipv4 válida. - - :param ip: string de la ip a comprobar - :return: True si es una dirección válida, False si NO es una dirección válida - """ - if not isinstance(ip, str): - raise ValueError("Formato incorrecto, el parámetro debe ser una cadena.") - - regex = r"^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$" - if re.match(regex, ip): - parts = ip.split('.') - if all(0 <= int(part) <= 255 for part in parts): - return True - return False - diff --git a/client/lib/engine/bin/System.lib b/client/lib/engine/bin/System.lib new file mode 100755 index 0000000..5124ce1 --- /dev/null +++ b/client/lib/engine/bin/System.lib @@ -0,0 +1,339 @@ +#!/bin/bash +#/** +#@file System.lib +#@brief Librería o clase System +#@class System +#@brief Funciones básicas del sistema. +#@version 1.1.0 +#@warning License: GNU GPLv3+ +#*/ + + +#/** +# ogEcho [str_logtype ...] [str_loglevel] "str_message" ... +#@brief Muestra mensajes en consola y lo registra en fichero de incidencias. +#@param str_logtype tipo de registro de incidencias. +#@param str_loglevel nivel de registro de incidencias. +#@param str_message mensaje (puede recibir más de 1 parámetro. +#@return Mensaje mostrado. +#@warning Si no se indica nivel de registro, solo muestra mensaje en pantalla. +#@warning Si DEBUG="no", no se registran mensajes de error. +#@note logfile = { log, command, session }; usa "log" si se indica nivel de registro. +#@note loglevel = { help, info, warning, error } +#@note El nivel de ayuda \c (help) no se registra en el fichero de incidencias. +#@version 0.9 - Primera versión para OpenGnSys +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2009-07-23 +#@version 1.0.5 - Elegir fichero de log. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2014-03-17 +#@version 1.1.0 - Posibilidad de no registrar mensajes en ficheros. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2015-11-10 +#*/ +function ogEcho () { + +# Variables locales +local CONT=1 LOGS LOGLEVEL DATETIME + +# Selección de ficheros de rgistro de incidencias. +while [ $CONT ]; do + case "${1,,}" in + log) LOGS="$LOGS $OGLOGFILE"; shift ;; + command) LOGS="$LOGS $OGLOGCOMMAND"; shift ;; + session) LOGS="$LOGS $OGLOGSESSION"; shift ;; + *) CONT= ;; + esac +done + +# Selección del nivel de registro (opcional). +case "${1,,}" in + help) shift ;; + info) LOGLEVEL="$1"; shift ;; + warning) LOGLEVEL="$1"; shift ;; + error) LOGLEVEL="$1"; shift ;; + *) ;; +esac + +if [ -n "$LOGLEVEL" ]; then + DATETIME=$(date +"%F %T") + # Registrar mensajes en fichero de log si la depuración no está desactivada. + [ "${DEBUG,,}" != "no" ] && LOGS="$OGLOGFILE $LOGS" + echo "OpenGnsys $LOGLEVEL" "$DATETIME $*" 2>&1 | tee -a $LOGS +else + echo "$*" | tee -a $LOGS +fi +} + + +#/** +# ogExecAndLog str_logfile ... str_command ... +#@brief Ejecuta un comando y guarda su salida en fichero de registro. +#@param str_logfile fichero de registro (pueden ser varios). +#@param str_command comando y comandos a ejecutar. +#@return Salida de ejecución del comando. +#@note str_logfile = { LOG, SESSION, COMMAND } +#@version 1.0.6 - Primera versión para OpenGnSys +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2013-07-02 +#*/ +function ogExecAndLog () { + +# Variables locales +local ISCOMMAND ISLOG ISSESSION COMMAND CONTINUE=1 FILES REDIREC + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME str_logfile ... str_command ..." \ + "$FUNCNAME COMMAND ls -al /" + return +fi + +# Procesar parámetros. +while [ $CONTINUE ]; do + case "${1,,}" in + command) ISCOMMAND=1; shift ;; + log) ISLOG=1; shift ;; + session) ISSESSION=1; shift ;; + *) COMMAND="$@" + CONTINUE= ;; + esac +done +# Error si no se recibe un comando que ejecutar. +[ -n "$COMMAND" ] || ogRaiseError $OG_ERR_FORMAT || return $? + +# Componer lista de ficheros de registro. +if [ $ISCOMMAND ]; then + FILES="$OGLOGCOMMAND" + > $FILES + REDIREC="2>&1" +fi +[ $ISLOG ] && FILES="$FILES $OGLOGFILE" +[ $ISSESSION ] && FILES="$FILES $OGLOGSESSION" + +# Ejecutar comando. +eval $COMMAND $REDIREC | tee -a $FILES +# Salida de error del comando ejecutado. +return ${PIPESTATUS[0]} +} + + +#/** +# ogGetCaller +#@brief Devuelve nombre del programa o script ejecutor (padre). +#@param No. +#@return str_name - Nombre del programa ejecutor. +#@version 0.10 - Primera versión para OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2011-01-17 +#*/ +function ogGetCaller () { + +# Obtener el nombre del programa o del script que ha llamado al proceso actual. +basename "$(COLUMNS=200 ps hp $PPID -o args | \ + awk '{if ($1~/bash/ && $2!="") { print $2; } + else { sub(/^-/,"",$1); print $1; } }')" +} + + +#/** +# ogHelp ["str_function" ["str_format" ["str_example" ... ]]] +#@brief Muestra mensaje de ayuda para una función determinda. +#@param str_function Nombre de la función. +#@param str_format Formato de ejecución de la función. +#@param str_example Ejemplo de ejecución de la función. +#@return str_help - Salida de ayuda. +#@note Si no se indican parámetros, la función se toma de la variable \c $FUNCNAME +#@note La descripción de la función se toma de la variable compuesta por \c MSG_FUNC_$función incluida en el fichero de idiomas. +#@note Pueden especificarse varios mensajes con ejemplos. +#@version 0.9 - Primera versión para OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2009-07-27 +#*/ +function ogHelp () { + +# Variables locales. +local FUNC MSG + +# Mostrar función, descripción y formato. +FUNC="${1:-${FUNCNAME[${#FUNCNAME[*]}-1]}}" +MSG="MSG_HELP_$FUNC" +ogEcho help "$MSG_FUNCTION $FUNC: ${!MSG}" +[ -n "$2" ] && ogEcho help " $MSG_FORMAT: $2" +# Mostrar ejemplos (si existen). +shift 2 +while [ $# -gt 0 ]; do + ogEcho help " $MSG_EXAMPLE: $1" + shift +done +} + + +#/** +# ogRaiseError [str_logtype ...] int_errcode ["str_errmessage" ...] +#@brief Devuelve el mensaje y el código de error correspondiente. +#@param str_logtype tipo de registro de incidencias. +#@param int_errcode código de error. +#@param str_errmessage mensajes complementarios de error. +#@return str_message - Mensaje de error, incluyendo las funciones relacionadas. +#@warning No definidas +#@note Mensajes internacionales del fichero de idiomas. +#@version 0.9 - Primera versión para OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2009-07-21 +#@version 1.0.5 - Muestra en el mensaje todas las funciones relacionadas (separadas por <-). +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2014-03-17 +#*/ +function ogRaiseError () { + +# Variables locales +local CONT=1 LOGS MSG CODE FUNCS + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME [str_logfile ...] int_errorcode str_errormessage" + return +fi + +# Selección de rgistros de incidencias. +while [ $CONT ]; do + case "${1,,}" in + log|command|session) LOGS="$LOGS $1"; shift ;; + *) CONT= ;; + esac +done + +# Obtener código y mensaje de error. +CODE="$1" +case "$CODE" in + $OG_ERR_FORMAT) MSG="$MSG_ERR_FORMAT \"$2\"" ;; + $OG_ERR_NOTFOUND) MSG="$MSG_ERR_NOTFOUND \"$2\"" ;; + $OG_ERR_OUTOFLIMIT) MSG="$MSG_ERR_OUTOFLIMIT \"$2\"" ;; + $OG_ERR_PARTITION) MSG="$MSG_ERR_PARTITION \"$2\"" ;; + $OG_ERR_LOCKED) MSG="$MSG_ERR_LOCKED \"$2\"" ;; + $OG_ERR_CACHE) MSG="$MSG_ERR_CACHE \"$2\"" ;; + $OG_ERR_NOGPT) MSG="$MSG_ERR_NOGPT \"$2\"" ;; + $OG_ERR_REPO) MSG="$MSG_ERR_REPO \"$2\"" ;; + $OG_ERR_FILESYS) MSG="$MSG_ERR_FILESYS \"$2\"" ;; + $OG_ERR_IMAGE) MSG="$MSG_ERR_IMAGE \"$2\"" ;; + $OG_ERR_NOTOS) MSG="$MSG_ERR_NOTOS \"$2\"" ;; + $OG_ERR_NOTEXEC) MSG="$MSG_ERR_NOTEXEC \"$2\"" ;; + $OG_ERR_NOTWRITE) MSG="$MSG_ERR_NOTWRITE \"$2\"" ;; + $OG_ERR_NOTCACHE) MSG="$MSG_ERR_NOTCACHE \"$2\"" ;; + $OG_ERR_CACHESIZE) MSG="$MSG_ERR_CACHESIZE \"$2\"" ;; + $OG_ERR_REDUCEFS) MSG="$MSG_ERR_REDUCEFS \"$2\"" ;; + $OG_ERR_EXTENDFS) MSG="$MSG_ERR_EXTENDFS \"$2\"" ;; + $OG_ERR_IMGSIZEPARTITION) MSG="$MSG_ERR_IMGSIZEPARTITION \"$2\"" ;; + $OG_ERR_UPDATECACHE) MSG="$MSG_ERR_UPDATECACHE \"$2\"" ;; + $OG_ERR_DONTFORMAT) MSG="$MSG_ERR_DONTFORMAT \"$2\"" ;; + $OG_ERR_IMAGEFILE) MSG="$MSG_ERR_IMAGEFILE \"$2\"" ;; + $OG_ERR_UCASTSYNTAXT) MSG="$MSG_ERR_UCASTSYNTAXT \"$2\"" ;; + $OG_ERR_UCASTSENDPARTITION) MSG="$MSG_ERR_UCASTSENDPARTITION \"$2\"" ;; + $OG_ERR_UCASTSENDFILE) MSG="$MSG_ERR_UCASTSENDFILE \"$2\"" ;; + $OG_ERR_UCASTRECEIVERPARTITION) MSG="$MSG_ERR_UCASTRECEIVERPARTITION \"$2\"" ;; + $OG_ERR_UCASTRECEIVERFILE) MSG="$MSG_ERR_UCASTRECEIVERFILE \"$2\"" ;; + $OG_ERR_MCASTSYNTAXT) MSG="$MSG_ERR_MCASTSYNTAXT \"$2\"" ;; + $OG_ERR_MCASTSENDFILE) MSG="$MSG_ERR_MCASTSENDFILE \"$2\"" ;; + $OG_ERR_MCASTRECEIVERFILE) MSG="$MSG_ERR_MCASTRECEIVERFILE \"$2\"" ;; + $OG_ERR_MCASTSENDPARTITION) MSG="$MSG_ERR_MCASTSENDPARTITION \"$2\"" ;; + $OG_ERR_MCASTRECEIVERPARTITION) MSG="$MSG_ERR_MCASTRECEIVERPARTITION \"$2\"" ;; + $OG_ERR_PROTOCOLJOINMASTER) MSG="$MSG_ERR_PROTOCOLJOINMASTER \"$2\"" ;; + $OG_ERR_DONTMOUNT_IMAGE) MSG="$MSG_ERR_DONTMOUNT_IMAGE \"$2\"" ;; + $OG_ERR_DONTUNMOUNT_IMAGE) MSG="$MSG_ERR_DONTUNMOUNT_IMAGE \"$2\"" ;; + $OG_ERR_DONTSYNC_IMAGE) MSG="$MSG_ERR_DONTSYNC_IMAGE \"$2\"" ;; + $OG_ERR_NOTDIFFERENT) MSG="$MSG_ERR_NOTDIFFERENT \"$2\"" ;; + $OG_ERR_SYNCHRONIZING) MSG="$MSG_ERR_SYNCHRONIZING \"$2\"" ;; + $OG_ERR_NOTUEFI) MSG="$MSG_ERR_NOTUEFI \"$2\"" ;; + $OG_ERR_NOMSDOS) MSG="$MSG_ERR_NOMSDOS \"$2\"" ;; + $OG_ERR_NOTBIOS) MSG="$MSG_ERR_NOTBIOS \"$2\"" ;; + *) MSG="$MSG_ERR_GENERIC"; CODE=$OG_ERR_GENERIC ;; +esac + +# Obtener lista de funciones afectadas, incluyendo el script que las llama. +FUNCS="${FUNCNAME[@]:1}" +FUNCS="${FUNCS/main/$(basename $0 2>/dev/null)}" + +# Mostrar mensaje de error si es función depurable y salir con el código indicado. +if [ $CODE == $OG_ERR_FORMAT ] || ogCheckStringInGroup "$FUNCS" "$NODEBUGFUNCTIONS" || ! ogCheckStringInGroup "${FUNCS%% *}" "$NODEBUGFUNCTIONS"; then + ogEcho $LOGS error "${FUNCS// /<-}: $MSG" >&2 +fi +return $CODE +} + + +#/** +# ogIsRepoLocked +#@brief Comprueba si el repositorio está siendo usado (tiene ficheros abiertos). +#@param No. +#@return Código de salida: 0 - bloqueado, 1 - sin bloquear o error. +#@version 0.10 - Primera versión para OpenGnSys. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2011-01-17 +#@version 1.0.1 - Devolver falso en caso de error. +#@author Ramon Gomez, ETSII Universidad de Sevilla +#@date 2011-05-18 +#*/ +function ogIsRepoLocked () +{ +# Variables locales. +local f FILES + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME" "if $FUNCNAME; then ...; fi" + return +fi + +# No hacer nada, si no está definido el punto de montaje del repositorio. +[ -z "$OGIMG" ] && return 1 + +# Comprobar si alguno de los ficheros abiertos por los procesos activos está en el +# punto de montaje del repositorio de imágenes. +FILES=$(for f in /proc/[0-9]*/fd/*; do readlink -f "$f"; done | grep "^$OGIMG") # */ (comentario Doxygen) +test -n "$FILES" +} + + +function ogCheckProgram () +{ +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME \"str_program ...\"" \ + "$FUNCNAME \"partimage partclone mbuffer\"" + return +fi + +# Error si no se recibe 1 parámetro. +[ $# == 1 ] || ogRaiseError $OG_ERR_FORMAT || return $? + +local PERROR PLOG i +PERROR=0 +PLOG=" " +for i in `echo $1` +do + if [ ! `which $i` ] + then + PERROR=1 + PLOG="$PLOG $i" + fi +done +if [ "$PERROR" == "1" ] +then + ogRaiseError $OG_ERR_NOTEXEC "$PLOG" || return $? +else + return 0 +fi +} + + + +#### PRUEBA +function ogIsVirtualMachine() { +case "$(dmidecode -s system-product-name)" in + KVM|VirtualBox) + return 1 ;; + *) return 0 ;; +esac +} + diff --git a/client/lib/engine/bin/SystemLib.py b/client/lib/engine/bin/SystemLib.py deleted file mode 100755 index 338a5e3..0000000 --- a/client/lib/engine/bin/SystemLib.py +++ /dev/null @@ -1,291 +0,0 @@ -import subprocess -import datetime -from zoneinfo import ZoneInfo -import sys -import os -import shutil -import inspect -import glob - -## for ogExecAndLog -from io import StringIO -from contextlib import redirect_stdout, redirect_stderr - -import ogGlobals -import StringLib -import SystemLib - -#NODEBUGFUNCTIONS, OGIMG, OG_ERR_CACHESIZE, OG_ERR_NOTCACHE, OG_ERR_NOTWRITE, OG_ERR_FILESYS -#OG_ERR_REPO, OG_ERR_NOTOS, OG_ERR_NOGPT, OG_ERR_OUTOFLIMIT, OG_ERR_IMAGE, OG_ERR_CACHE -#OGLOGSESSION, OGLOGCOMMAND, OGLOGFILE, OG_ERR_LOCKED, OG_ERR_PARTITION, OG_ERR_FORMAT, OG_ERR_NOTEXEC, OG_ERR_NOTFOUND - -def _logtype2logfile (t): - if 'log' == t.lower(): return ogGlobals.OGLOGFILE - elif 'command' == t.lower(): return ogGlobals.OGLOGCOMMAND - elif 'session' == t.lower(): return ogGlobals.OGLOGSESSION - else: raise Exception (f'unknown log type ({t})') -#/** -# ogEcho [str_logtype ...] [str_loglevel] "str_message" ... -#@brief Muestra mensajes en consola y lo registra en fichero de incidencias. -#@param str_logtype tipo de registro de incidencias ("log", "command", "session") -#@param str_loglevel nivel de registro de incidencias ("info", "warning", "error") -#@param str_message mensaje (puede recibir más de 1 parámetro. -#@return Mensaje mostrado. -#*/ -def ogEcho (logtypes, loglevel, msg): - logfiles = ['/dev/stdout'] - if type (logtypes) is list: - for l in logtypes: - logfiles.append (_logtype2logfile (l)) - else: ## string - logfiles.append (_logtype2logfile (logtypes)) - - if loglevel is None or 'help' == loglevel: - if ogGlobals.DEBUG.lower() != "no": - logfiles.append (ogGlobals.OGLOGFILE) - for f in logfiles: - with open (f, 'a') as fd: - fd.write (msg + '\n') - return - - if 'info' == loglevel or 'warning' == loglevel or 'error' == loglevel: - DATETIME = datetime.datetime.now(ZoneInfo(ogGlobals.TZ)).strftime("%F %T %Z") - - for f in logfiles: - with open (f, 'a') as fd: - fd.write (f"OpenGnsys {loglevel} {DATETIME} {msg}\n") - else: - raise Exception (f'unknown loglevel ({loglevel})') - - -#/** -# ogExecAndLog str_logfile ... str_command ... -#@brief Ejecuta un comando y guarda su salida en fichero de registro. -#@param str_logfile fichero de registro (pueden ser varios). -#@param str_command comando y comandos a ejecutar. -#@return Salida de ejecución del comando. -#@note str_logfile = { LOG, SESSION, COMMAND } -#*/ -#ogHelp (str_logfile ... str_command ...", -#ogHelp ([], ogMyLib.ogSomeMethod, *args, **kwargs) -#ogHelp ('command', ogMyLib.ogSomeMethod, *args, **kwargs) -#ogHelp (['command'], ogMyLib.ogSomeMethod, *args, **kwargs) -#ogHelp (['log', 'command'], ogMyLib.ogSomeMethod, *args, **kwargs) -def ogExecAndLog (logtypes, fun, *args, **kwargs): - logfiles = ['/dev/stdout'] - if type (logtypes) is list: - for l in logtypes: - logtypes = list (map (lambda x: x.lower(), logtypes)) - logfiles.append (_logtype2logfile (l)) - else: ## string - logtypes = logtypes.lower() - logfiles.append (_logtype2logfile (logtypes)) - - if not fun: - ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, 'no function provided') - return - - ## the original bash code does something like this: - #if [ $ISCOMMAND ]; then - # > $OGLOGCOMMAND - # REDIREC="2>&1" - #fi - #eval $COMMAND $REDIREC | tee -a $FILES - - ## a hybrid bash/python pseudocode would end up being like the following: - #if 'command' in logtypes: - # rm $OGLOGCOMMAND - # touch $OGLOGCOMMAND - # - #if 'command' in logtypes: - # ## redirect both stdout and stderr - # eval $COMMAND 2>&1 | tee -a $FILES - #else: - # ## redirect stdout only - # eval $COMMAND | tee -a $FILES - - sout = serr = '' - if 'command' in logtypes: - os.unlink (ogGlobals.OGLOGCOMMAND) - open (ogGlobals.OGLOGCOMMAND, 'w').close() - with redirect_stdout (StringIO()) as r_stdout, redirect_stderr (StringIO()) as r_stderr: - rc = fun (*args, **kwargs) - sout = r_stdout.getvalue() - serr = r_stderr.getvalue() - else: - with redirect_stdout (StringIO()) as r_stdout: - rc = fun (*args, **kwargs) - sout = r_stdout.getvalue() - - rc_str = str (rc) - if sout or serr or ('True' != rc_str and 'False' != rc_str and 'None' != rc_str): - for f in logfiles: - with open (f, 'a') as fd: - if sout: fd.write (f'{sout}\n') - if serr: fd.write (f'{serr}\n') - if rc_str: fd.write (f'{rc_str}\n') - - return rc - -#/** -# ogGetCaller -#@brief Devuelve nombre del programa o script ejecutor (padre). -#@return str_name - Nombre del programa ejecutor. -#*/ -def ogGetCaller(): - if 'COLUMNS' in os.environ: - cols = os.environ['COLUMNS'] - else: - cols = None - - lines = subprocess.run (["ps", "hp", str(os.getppid()), "-o", "args"], capture_output=True, text=True).stdout.splitlines() - if 0 == len (lines): - return '' - - line = lines[0] - words = line.split() - if "bash" in line and len(words)>1: - caller = words[1] - else: - caller = words[0].lstrip("-") - - if cols is None: - del (os.environ['COLUMNS']) - else: - os.environ['COLUMNS'] = cols - - return os.path.basename(caller) - -#/** -# ogHelp ["str_function" ["str_format" ["str_example" ... ]]] -#@brief Muestra mensaje de ayuda para una función determinda. -#@param str_function Nombre de la función. -#@param str_format Formato de ejecución de la función. -#@param str_example Ejemplo de ejecución de la función. -#@return str_help - Salida de ayuda. -#@note Si no se indican parámetros, la función se toma de la variable \c $FUNCNAME -#@note La descripción de la función se toma de la variable compuesta por \c MSG_FUNC_$función incluida en el fichero de idiomas. -#@note Pueden especificarse varios mensajes con ejemplos. -#*/ -def ogHelp (fname, fmt=None, examples=[]): - FUNC = fname or inspect.stack()[1][3] - MSG = f'ogGlobals.lang.MSG_HELP_{FUNC}' - try: - MSG = eval (MSG) - except: - MSG = '' - ogEcho ([], "help", f"{ogGlobals.lang.MSG_FUNCTION} {FUNC}: {MSG}") - if fmt: - ogEcho([], "help", f" {ogGlobals.lang.MSG_FORMAT}: {fmt}") - - if type (examples) is list: - for example in examples: - ogEcho([], "help", f" {ogGlobals.lang.MSG_EXAMPLE}: {example}") - else: ## string - ogEcho([], "help", f" {ogGlobals.lang.MSG_EXAMPLE}: {examples}") - -#/** -# ogRaiseError [str_logtype ...] int_errcode ["str_errmessage" ...] -#@brief Devuelve el mensaje y el código de error correspondiente. -#@param str_logtype tipo de registro de incidencias. -#@param int_errcode código de error. -#@param str_errmessage mensajes complementarios de error. -#@return str_code - código de error -#*/ -def ogRaiseError (logtypes, code, msg): - if code == ogGlobals.OG_ERR_FORMAT: MSG = f'{ogGlobals.lang.MSG_ERR_FORMAT} "{msg}"' - elif code == ogGlobals.OG_ERR_NOTFOUND: MSG = f'{ogGlobals.lang.MSG_ERR_NOTFOUND} "{msg}"' - elif code == ogGlobals.OG_ERR_OUTOFLIMIT: MSG = f'{ogGlobals.lang.MSG_ERR_OUTOFLIMIT} "{msg}"' - elif code == ogGlobals.OG_ERR_PARTITION: MSG = f'{ogGlobals.lang.MSG_ERR_PARTITION} "{msg}"' - elif code == ogGlobals.OG_ERR_LOCKED: MSG = f'{ogGlobals.lang.MSG_ERR_LOCKED} "{msg}"' - elif code == ogGlobals.OG_ERR_CACHE: MSG = f'{ogGlobals.lang.MSG_ERR_CACHE} "{msg}"' - elif code == ogGlobals.OG_ERR_NOGPT: MSG = f'{ogGlobals.lang.MSG_ERR_NOGPT} "{msg}"' - elif code == ogGlobals.OG_ERR_REPO: MSG = f'{ogGlobals.lang.MSG_ERR_REPO} "{msg}"' - elif code == ogGlobals.OG_ERR_FILESYS: MSG = f'{ogGlobals.lang.MSG_ERR_FILESYS} "{msg}"' - elif code == ogGlobals.OG_ERR_IMAGE: MSG = f'{ogGlobals.lang.MSG_ERR_IMAGE} "{msg}"' - elif code == ogGlobals.OG_ERR_NOTOS: MSG = f'{ogGlobals.lang.MSG_ERR_NOTOS} "{msg}"' - elif code == ogGlobals.OG_ERR_NOTEXEC: MSG = f'{ogGlobals.lang.MSG_ERR_NOTEXEC} "{msg}"' - elif code == ogGlobals.OG_ERR_NOTWRITE: MSG = f'{ogGlobals.lang.MSG_ERR_NOTWRITE} "{msg}"' - elif code == ogGlobals.OG_ERR_NOTCACHE: MSG = f'{ogGlobals.lang.MSG_ERR_NOTCACHE} "{msg}"' - elif code == ogGlobals.OG_ERR_CACHESIZE: MSG = f'{ogGlobals.lang.MSG_ERR_CACHESIZE} "{msg}"' - elif code == ogGlobals.OG_ERR_REDUCEFS: MSG = f'{ogGlobals.lang.MSG_ERR_REDUCEFS} "{msg}"' - elif code == ogGlobals.OG_ERR_EXTENDFS: MSG = f'{ogGlobals.lang.MSG_ERR_EXTENDFS} "{msg}"' - elif code == ogGlobals.OG_ERR_IMGSIZEPARTITION: MSG = f'{ogGlobals.lang.MSG_ERR_IMGSIZEPARTITION} "{msg}"' - elif code == ogGlobals.OG_ERR_UPDATECACHE: MSG = f'{ogGlobals.lang.MSG_ERR_UPDATECACHE} "{msg}"' - elif code == ogGlobals.OG_ERR_DONTFORMAT: MSG = f'{ogGlobals.lang.MSG_ERR_DONTFORMAT} "{msg}"' - elif code == ogGlobals.OG_ERR_IMAGEFILE: MSG = f'{ogGlobals.lang.MSG_ERR_IMAGEFILE} "{msg}"' - elif code == ogGlobals.OG_ERR_UCASTSYNTAXT: MSG = f'{ogGlobals.lang.MSG_ERR_UCASTSYNTAXT} "{msg}"' - elif code == ogGlobals.OG_ERR_UCASTSENDPARTITION: MSG = f'{ogGlobals.lang.MSG_ERR_UCASTSENDPARTITION} "{msg}"' - elif code == ogGlobals.OG_ERR_UCASTSENDFILE: MSG = f'{ogGlobals.lang.MSG_ERR_UCASTSENDFILE} "{msg}"' - elif code == ogGlobals.OG_ERR_UCASTRECEIVERPARTITION: MSG = f'{ogGlobals.lang.MSG_ERR_UCASTRECEIVERPARTITION} "{msg}"' - elif code == ogGlobals.OG_ERR_UCASTRECEIVERFILE: MSG = f'{ogGlobals.lang.MSG_ERR_UCASTRECEIVERFILE} "{msg}"' - elif code == ogGlobals.OG_ERR_MCASTSYNTAXT: MSG = f'{ogGlobals.lang.MSG_ERR_MCASTSYNTAXT} "{msg}"' - elif code == ogGlobals.OG_ERR_MCASTSENDFILE: MSG = f'{ogGlobals.lang.MSG_ERR_MCASTSENDFILE} "{msg}"' - elif code == ogGlobals.OG_ERR_MCASTRECEIVERFILE: MSG = f'{ogGlobals.lang.MSG_ERR_MCASTRECEIVERFILE} "{msg}"' - elif code == ogGlobals.OG_ERR_MCASTSENDPARTITION: MSG = f'{ogGlobals.lang.MSG_ERR_MCASTSENDPARTITION} "{msg}"' - elif code == ogGlobals.OG_ERR_MCASTRECEIVERPARTITION: MSG = f'{ogGlobals.lang.MSG_ERR_MCASTRECEIVERPARTITION} "{msg}"' - elif code == ogGlobals.OG_ERR_PROTOCOLJOINMASTER: MSG = f'{ogGlobals.lang.MSG_ERR_PROTOCOLJOINMASTER} "{msg}"' - elif code == ogGlobals.OG_ERR_DONTMOUNT_IMAGE: MSG = f'{ogGlobals.lang.MSG_ERR_DONTMOUNT_IMAGE} "{msg}"' - elif code == ogGlobals.OG_ERR_DONTUNMOUNT_IMAGE: MSG = f'{ogGlobals.lang.MSG_ERR_DONTUNMOUNT_IMAGE} "{msg}"' - elif code == ogGlobals.OG_ERR_DONTSYNC_IMAGE: MSG = f'{ogGlobals.lang.MSG_ERR_DONTSYNC_IMAGE} "{msg}"' - elif code == ogGlobals.OG_ERR_NOTDIFFERENT: MSG = f'{ogGlobals.lang.MSG_ERR_NOTDIFFERENT} "{msg}"' - elif code == ogGlobals.OG_ERR_SYNCHRONIZING: MSG = f'{ogGlobals.lang.MSG_ERR_SYNCHRONIZING} "{msg}"' - elif code == ogGlobals.OG_ERR_NOTUEFI: MSG = f'{ogGlobals.lang.MSG_ERR_NOTUEFI} "{msg}"' - elif code == ogGlobals.OG_ERR_NOMSDOS: MSG = f'{ogGlobals.lang.MSG_ERR_NOMSDOS} "{msg}"' - elif code == ogGlobals.OG_ERR_NOTBIOS: MSG = f'{ogGlobals.lang.MSG_ERR_NOTBIOS} "{msg}"' - else: - MSG = ogGlobals.lang.MSG_ERR_GENERIC - CODE = ogGlobals.OG_ERR_GENERIC - - # Obtener lista de funciones afectadas, incluyendo el script que las llama. - call_stack = [i[3] for i in inspect.stack()] - if len (call_stack) < 2: return ## shouldn't happen - call_stack.pop() ## remove '' - call_stack.pop(0) ## remove 'ogRaiseError' - str_call_stack = ' '.join (call_stack) - - # Mostrar mensaje de error si es función depurable y salir con el código indicado. - if code == ogGlobals.OG_ERR_FORMAT or \ - (str_call_stack in ogGlobals.NODEBUGFUNCTIONS) or \ - not (len(call_stack)>0 and (call_stack[0] in ogGlobals.NODEBUGFUNCTIONS)): - ogEcho (logtypes, "error", f"{str_call_stack.replace(' ', '<-')}: {MSG}") - - return code - -#/** -# ogIsRepoLocked -#@brief Comprueba si el repositorio está siendo usado (tiene ficheros abiertos). -#@param No. -#@return Código de salida: 0 - bloqueado, 1 - sin bloquear o error. -#*/ -def ogIsRepoLocked(): -# No hacer nada, si no está definido el punto de montaje del repositorio. - if not ogGlobals.OGIMG: - return False - -# Comprobar si alguno de los ficheros abiertos por los procesos activos está en el -# punto de montaje del repositorio de imágenes. - proc_entries = glob.glob ('/proc/[0-9]*/fd/*') - for e in proc_entries: - p = os.path.realpath (e) - if ogGlobals.OGIMG in p: - return True - return False - -## has no users -#def ogCheckProgram(program): -# FUNCNAME = ogCheckProgram.__name__ -# -# if not program or not isinstance(program, str): -# SystemLib.ogRaiseError ("session", ogGlobals.OG_ERR_FORMAT, f"Error: {ogGlobals.lang.MSG_ERR_FORMAT} {FUNCNAME} \"program\"") -# return -# -# if not shutil.which(program): -# SystemLib.ogRaiseError ( "session", ogGlobals.OG_ERR_NOTEXEC, f"Error: The program '{program}' is not available on the system.") -# return -# -# return 0 - -def ogIsVirtualMachine(): - output = subprocess.run (["dmidecode", "-s", "system-product-name"], capture_output=True, text=True).stdout - return "KVM" in output or "VirtualBox" in output diff --git a/client/lib/engine/bin/UEFI.lib b/client/lib/engine/bin/UEFI.lib new file mode 100755 index 0000000..f7fe367 --- /dev/null +++ b/client/lib/engine/bin/UEFI.lib @@ -0,0 +1,679 @@ +#!/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. +#*/ ## +function ogNvramActiveEntry () { +local NUMENTRY + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME [ Num_order_entry | Label_entry ] " \ + "$FUNCNAME 2" \ + "$FUNCNAME \"Windows Boot Manager\"" + return +fi + +# Error si no se recibe 1 parámetro. +[ $# -eq 1 ] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME [ Num_order_entry | Label_entry ]" || return $? + +# Si no es equipo UEFI salir con error +ogIsEfiActive || ogRaiseError $OG_ERR_NOTUEFI || return $? + +# Distingo si es número de orden o etiqueta +if [[ $1 =~ ^([0-9a-fA-F]+)$ ]]; then + NUMENTRY=$( efibootmgr |awk -v NUM="$(printf %04x 0x$1|tr '[:lower:]' '[:upper:]')" '{ if($1~NUM) print substr($1,5,4)}') +else + NUMENTRY=$(efibootmgr |awk -v LABEL="$1" '{ if(substr($0, index($0,$2))==LABEL) print substr($1,5,4)}') +fi + +[ "$NUMENTRY" == "" ] && return $(ogRaiseError $OG_ERR_NOTFOUND "NVRAM entry '$1'") + +efibootmgr -a -b $NUMENTRY &>/dev/null +} + +#/** +# 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. +#*/ ## +function ogNvramAddEntry () { +local EFIDISK EFIPART BOOTLABEL BOOTLOADER ADDORDER + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME Str_label_entry Str_boot_loader [ Bool_add_bootorder ]" \ + "$FUNCNAME 1 2 TRUE" \ + "$FUNCNAME grub /EFI/grub/grubx64.efi TRUE" \ + "$FUNCNAME Windows /EFI/Microsoft/Boot/bootmgfw.efi" + return +fi + +# Error si no se recibe 1 parámetro. +[ $# -ge 2 ] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME Str_label_entry Str_boot_locader" || return $? + +# Si no es equipo UEFI salir con error +ogIsEfiActive || ogRaiseError $OG_ERR_NOTUEFI || return $? + +read -e EFIDISK EFIPART <<<"$(ogGetEsp)" +[ -n "$EFIPART" ] || ogRaiseError $OG_ERR_NOTFOUND "ESP" || return $? + +# Recogemos parámetros +# Distinguimos si es disco/partición o etiqueta/cargador +if [[ "$1$2" =~ ^([0-9]+)$ ]]; then + BOOTLABEL=$(printf "Part-%02d-%02d" $1 $2) + BOOTLOADER="/EFI/$BOOTLABEL/Boot/ogloader.efi" +else + BOOTLABEL="$1" + BOOTLOADER="$2" +fi + + +# Si existe entrada con la misma etiqueta la borramos +ogNvramDeleteEntry "$BOOTLABEL" 2>/dev/null + +efibootmgr -C -d $(ogDiskToDev $EFIDISK) -p $EFIPART -L "$BOOTLABEL" -l "$BOOTLOADER" &>/dev/null + +# Incluimos la entrada en el orden de arranque (opcional) +if [ "${3^^}" == "TRUE" ]; then + NUMENTRY=$(efibootmgr |awk -v LABEL="$BOOTLABEL" '{ if(substr($0, index($0,$2))==LABEL) print substr($1,5,4)}') + ogNvramSetOrder $(ogNvramGetOrder |tr , " ") $NUMENTRY +fi +} + + +#/** +# 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 +#*/ ## +function ogCopyEfiBootLoader () { +# Variables locales +local MNTDIR EFIDIR BOOTLABEL OSVERSION LOADER f + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_part" \ + "$FUNCNAME 1 2" + return +fi + +# Error si no se reciben 2 arámetros. +[ $# == 2 ] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME int_ndisk int_part" || return $? + +# Comprobamos que exista partición de sistema y la ESP +MNTDIR=$(ogMount $1 $2) || ogRaiseError $OG_ERR_PARTITION "$DISK $PART" || return $? +EFIDIR=$(ogMount $(ogGetEsp)) || ogRaiseError $OG_ERR_PARTITION "ESP" || return $? + +# Comprobamos que exista el cargador +BOOTLABEL=$(printf "Part-%02d-%02d" $1 $2) +OSVERSION=$(ogGetOsVersion $1 $2) +case $OSVERSION in + *Windows\ 10*) + for f in $EFIDIR/EFI/{Microsoft,$BOOTLABEL}/Boot/bootmgfw.efi; do + [ -r $f ] && LOADER=$f + done + [ -n "$LOADER" ] || ogRaiseError $OG_ERR_NOTOS "$1 $2 ($OSVERSION, EFI)" || return $? + # Si existe el directorio Boot lo borramos + [ -d $MNTDIR/ogBoot ] && rm -rf $MNTDIR/ogBoot + DIRLOADER=$(realpath "${LOADER%/*}/..") + cp -r ${DIRLOADER}/Boot $MNTDIR/ogBoot + ;; +esac +} + + +#/** +# 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). +#*/ ## +function ogNvramDeleteEntry () { +local NUMENTRY n + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME [ Num_order_entry | Label_entry ] " \ + "$FUNCNAME 2" \ + "$FUNCNAME \"Windows Boot Manager\"" + return +fi + +# Error si no se recibe 1 parámetro. +[ $# -eq 1 ] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME [ Num_order_entry | Label_entry ]" || return $? + +# Si no es equipo UEFI salir con error +ogIsEfiActive || ogRaiseError $OG_ERR_NOTUEFI || return $? + +# Distingo si es número de orden o etiqueta +if [[ $1 =~ ^([0-9a-fA-F]+)$ ]]; then + NUMENTRY=$( efibootmgr |awk -v NUM="$(printf %04x 0x$1|tr '[:lower:]' '[:upper:]')" '{ if($1~NUM) print substr($1,5,4)}') +else + NUMENTRY=$(efibootmgr |awk -v LABEL="$1" '{ if(substr($0, index($0,$2))==LABEL) print substr($1,5,4)}') +fi + +[ "$NUMENTRY" == "" ] && return $(ogRaiseError $OG_ERR_NOTFOUND "NVRAM entry '$1'") + +for n in $NUMENTRY; do + efibootmgr -B -b $n &>/dev/null +done +} + + +#/** +# 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. +#*/ ## +function ogNvramGetCurrent () { + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME" \ + "$FUNCNAME" + return +fi + +# Si no es equipo UEFI salir con error +ogIsEfiActive || ogRaiseError $OG_ERR_NOTUEFI || return $? + +efibootmgr| awk -v bootentry=99999 '{if ($1~/BootCurrent/) bootentry=$2; if ($1~bootentry) printf "%s %s %s\n", gensub(/^0{1,3}/,"",1,substr($1,5,4))," ", substr($0, index($0,$2))}' +} + + +# 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. +#*/ ## +function ogNvramGetNext () { +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME" \ + "$FUNCNAME" + return +fi + +# Si no es equipo UEFI salir con error +ogIsEfiActive || ogRaiseError $OG_ERR_NOTUEFI || return $? + +efibootmgr|awk '{ if ($1 == "BootNext:") print $2}' +} + + +# 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. +#*/ ## +function ogNvramGetOrder () { +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME" \ + "$FUNCNAME" + return +fi + +# Si no es equipo UEFI salir con error +ogIsEfiActive || ogRaiseError $OG_ERR_NOTUEFI || return $? + +efibootmgr|awk '{ if ($1 == "BootOrder:") print $2}' +} + + +#/** +# ogNvramGetTimeout +#@brief Muestra el tiempo de espera del gestor de arranque (NVRAM) +#@return Timeout de la NVRAM +#@exception OG_ERR_NOTUEFI UEFI no activa. +#*/ ## +function ogNvramGetTimeout () { +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME" \ + "$FUNCNAME" + return +fi + +# Si no es equipo UEFI salir con error +ogIsEfiActive || ogRaiseError $OG_ERR_NOTUEFI || return $? + +efibootmgr|awk '{ if ($1 == "Timeout:") print substr($0, index($0,$2))}' +} + + +#/** +# 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. +#*/ ## +function ogGrubUefiConf () { +local EFIDIR BOOTLABEL GRUBEFI UUID DEVICE PREFIXSECONDSTAGE EFIGRUBDIR + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_part [ str_dir_grub ]" \ + "$FUNCNAME 1 2" \ + "$FUNCNAME 1 3 /boot/grubPARTITION" + return +fi + +# Error si no se reciben al menos 2 parámetros. +[ $# -ge 2 ] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME int_ndisk int_part [ str_dir_grub ]" || return $? + +# Directorio del grub en la partición de sistema +PREFIXSECONDSTAGE="$3" + +EFIDIR=$(ogMount $(ogGetEsp)) || ogRaiseError $OG_ERR_PARTITION "ESP" || return $? +BOOTLABEL=$(printf "Part-%02d-%02d" $1 $2) +EFIGRUBDIR="$EFIDIR/EFI/$BOOTLABEL/boot/grub" +# Comprobamos que existe directorio +[ -d "$EFIGRUBDIR" ] || mkdir -p "$EFIGRUBDIR" +# Parcheamos uuid y particion en grub.cfg +UUID=$(blkid -o value -s UUID $(ogDiskToDev $1 $2)) +DEVICE="hd$(expr $1 - 1 ),gpt$2" + +cat << EOT > $EFIGRUBDIR/grub.cfg +set root='$DEVICE' +set prefix=(\$root)'${PREFIXSECONDSTAGE}/boot/grub' +configfile \$prefix/grub.cfg +EOT + +# Provisional: confirmar si el segundo archivo se utiliza +cp $EFIGRUBDIR/grub.cfg "$EFIDIR/EFI/$BOOTLABEL/grub.cfg" +} + + +#/** +# 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. +#*/ ## +function ogNvramInactiveEntry () { +local NUMENTRY + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME [ Num_order_entry | Label_entry ] " \ + "$FUNCNAME 2" \ + "$FUNCNAME \"Windows Boot Manager\"" + return +fi + +# Error si no se recibe 1 parámetro. +[ $# -eq 1 ] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME [ Num_order_entry | Label_entry ]" || return $? + +# Si no es equipo UEFI salir con error +ogIsEfiActive || ogRaiseError $OG_ERR_NOTUEFI || return $? + +# Distingo si es número de orden o etiqueta +if [[ $1 =~ ^([0-9a-fA-F]+)$ ]]; then + NUMENTRY=$( efibootmgr |awk -v NUM="$(printf %04x 0x$1|tr '[:lower:]' '[:upper:]')" '{ if($1~NUM) print substr($1,5,4)}') +else + NUMENTRY=$(efibootmgr |awk -v LABEL="$1" '{ if(substr($0, index($0,$2))==LABEL) print substr($1,5,4)}') +fi + +[ "$NUMENTRY" == "" ] && return $(ogRaiseError $OG_ERR_NOTFOUND "NVRAM entry '$1'") + +efibootmgr -A -b $NUMENTRY &>/dev/null +} + + +#/** +# 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. +#*/ ## +function ogNvramList () { + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME" \ + "$FUNCNAME" + return +fi + +# Si no es equipo UEFI salir con error +ogIsEfiActive || ogRaiseError $OG_ERR_NOTUEFI || return $? + +efibootmgr |awk '{if($1~/Boot[[:digit:]]/) ; active="" ;if ($1~/*/) active="*"; if($1~/Boot[[:digit:]]/) printf "%4s %s %s %s\n", gensub(/^0{1,3}/,"",1,substr($1,5,4))," ", substr($0, index($0,$2)), active}' +} + + +#/** +# 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. +#*/ ## +function ogNvramPxeFirstEntry (){ +local NUMENTRY ORDER + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME" \ + "$FUNCNAME" + return +fi + +# Si no es equipo UEFI salir con error +ogIsEfiActive || ogRaiseError $OG_ERR_NOTUEFI || return $? + +NUMENTRY=$(printf %04X 0x$(efibootmgr|awk '/IP[vV]{0,1}4/ {print gensub(/^0{1,3}/,"",1,substr($1,5,4))}')) + +# Si la entrada es la primera nos salimos. +[[ $(ogNvramGetOrder) =~ ^$NUMENTRY ]] && return + +# Si la entrada ya existe la borramos. +ORDER="$NUMENTRY $(ogNvramGetOrder| sed -e s/$NUMENTRY//g -e s/,/' '/g)" + +ogNvramSetOrder $ORDER +} + + +#/** +# 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. +#*/ ## +function ogRestoreEfiBootLoader () { +# Variables locales +local MNTDIR EFIDIR BOOTLABEL OSVERSION LOADER f UUID DEVICE + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_part" \ + "$FUNCNAME 1 2" + return +fi + +# Error si no se reciben 2 arámetros. +[ $# == 2 ] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME int_ndisk int_part" || return $? + +# Comprobamos que exista partición de sistema y la ESP +MNTDIR=$(ogMount $1 $2) || ogRaiseError $OG_ERR_PARTITION "$DISK $PART" || return $? +EFIDIR=$(ogMount $(ogGetEsp)) +if [ "$EFIDIR" == "" ]; then + ogFormat $(ogGetEsp) FAT32 + EFIDIR=$(ogMount $(ogGetEsp)) || ogRaiseError $OG_ERR_PARTITION "ESP" || return $? +fi + +# Comprobamos que exista el cargador +#BOOTLABEL=$(printf "Part-%02d-%02d" $1 $2) +OSVERSION=$(ogGetOsVersion $1 $2) +case $OSVERSION in + *Windows\ 10*) + BOOTLABEL=$(printf "Part-%02d-%02d" $1 $2) + LOADER=$(ogGetPath $MNTDIR/ogBoot/bootmgfw.efi) + [ -n "$LOADER" ] || ogRaiseError $OG_ERR_NOTOS "$1 $2 ($OSVERSION, EFI)" || return $? + [ -r $EFIDIR/EFI/$BOOTLABEL ] && rm -rf $EFIDIR/EFI/$BOOTLABEL + mkdir -p $EFIDIR/EFI/$BOOTLABEL + cp -r "${LOADER%/*}" $EFIDIR/EFI/$BOOTLABEL/Boot + # Nombre OpenGnsys para cargador + cp $LOADER $EFIDIR/EFI/$BOOTLABEL/Boot/ogloader.efi + + # Si existe subcarpeta Microsoft en la partición EFI la renombramos + [ "$(ogGetPath $EFIDIR/EFI/Microsoft)" == "" ] || mv $EFIDIR/EFI/{Microsoft,Microsoft.backup.og} + ;; +esac +} + + +#/** +# 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) +#*/ ## +function ogRestoreUuidPartitions () { +local DISK PART IMGNAME INFOFILE DEVICE DATA GUID UUID IMGGUID +local EFIDEVICE EFIDATA EFIGUID EFIUUID EFIUUID IMGEFIGUID + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME REPO|CACHE str_imgname int_ndisk int_npart" \ + "$FUNCNAME REPO Windows 1 2" + return +fi +# Error si no se reciben 4 parámetros. +[ $# -eq 4 ] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME REPO|CACHE str_imgname int_ndisk int_npart" || return $? + +# Sólo se ejecuta si es UEFI +ogIsEfiActive || return + +# Parámetros de entrada +IMGNAME="$2" +INFOFILE="$OGIMG/.$IMGNAME.img.json" +[ "${1^^}" == "CACHE" ] && INFOFILE="$OGCAC$INFOFILE" +# TODO: que la función getPath soporte archivos ocultos +ls $INFOFILE &>/dev/null || ogRaiseError $OG_ERR_NOTFOUND "$INFOFILE" || return $? +DISK=$3 +PART=$4 + +DEVICE=$(ogDiskToDev $DISK) +read -e EFIDISK EFIPART <<<"$(ogGetEsp)" + +# Datos de la imagen +IMGGUID=$(jq .guid $INFOFILE|tr -d \") +IMGEFIGUID=$(jq .espguid $INFOFILE|tr -d \") + +# Datos actuales +DATA=$(sfdisk -J $DEVICE) +GUID=$(echo $DATA|jq ".partitiontable|.id"|tr -d \") + +if [ "$IMGGUID" != "$GUID" ]; then + echo sgdisk -U "$IMGGUID" "$DEVICE" + sgdisk -U "$IMGGUID" "$DEVICE" + partprobe +fi + +if [ $DISK -eq $EFIDISK ]; then + EFIDATA=$DATA + EFIDEVICE=$DEVICE +else + EFIDEVICE=$(ogDiskToDev $EFIDISK) || return $? + EFIDATA=$(sfdisk -J $EFIDEVICE) + EFIGUID=$(echo $EFIDATA|jq ".partitiontable|.id"|tr -d \") + if [ "$IMGEFIGUID" != "$EFIGUID" ]; then +echo sgdisk -U "$IMGEFIGUID" "$EFIDEVICE" + sgdisk -U "$IMGEFIGUID" "$EFIDEVICE" + partprobe + fi +fi +} + + +#/** +# 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. +#*/ ## +function ogNvramSetNext () { +local NUMENTRY + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME [ Num_order_entry | Label_entry ] " \ + "$FUNCNAME 2" \ + "$FUNCNAME \"Windows Boot Manager\"" + return +fi + +# Error si no se recibe 1 parámetro. +[ $# -eq 1 ] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME [ Num_order_entry | Label_entry ]" || return $? + +# Si no es equipo UEFI salir con error +ogIsEfiActive || ogRaiseError $OG_ERR_NOTUEFI || return $? + +# Distingo si es número de orden o etiqueta +if [[ $1 =~ ^([0-9a-fA-F]+)$ ]]; then + NUMENTRY=$( efibootmgr |awk -v NUM="$(printf %04x 0x$1|tr '[:lower:]' '[:upper:]')" '{ if($1~NUM) print substr($1,5,4)}') +else + NUMENTRY=$(efibootmgr | awk -v LABEL="$1" '$0 ~ LABEL { print substr($1,5,4) }') +fi + +[ "$NUMENTRY" == "" ] && return $(ogRaiseError $OG_ERR_NOTFOUND "NVRAM entry '$1'") + +efibootmgr -n $NUMENTRY &>/dev/null +} + +#/** +# 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). +#*/ ## +function ogNvramSetOrder () { +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME Num_order1 [ Num_order2 ] ... " \ + "$FUNCNAME 1 3" + return +fi +# +# Error si no se recibe al menos 1 parámetro. +[ $# -ge 1 ] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME Num_order1 [ Num_order2 ] ..." || return $? + +# Si no es equipo UEFI salir con error +ogIsEfiActive || ogRaiseError $OG_ERR_NOTUEFI || return $? + +# Comprobamos que sean números +[[ "$@" =~ ^([0-9a-fA-F ]+)$ ]] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME Num_order1 [ Num_order2 ] ..." || return $? + +# Entradas de la NVRAM actuales +NUMENTRYS=$(efibootmgr|awk '{ if ($1~/Boot[0-9a-fA-F]{4}/) printf "0%s ", substr($1,5,4)}') + +ORDER="" +for ARG in $@; do + # Si no existe la entrada me salgo + ARG=$(printf %04X 0x$ARG) + echo $NUMENTRYS | grep "$ARG" &>/dev/null || ogRaiseError $OG_ERR_NOTFOUND "NVRAM entry order \"$ARG\"" || return $? + ORDER=${ORDER},$ARG +done + +# Cambiamos el orden +efibootmgr -o ${ORDER#,} &>/dev/null +} + + +#/** +# 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. +#*/ ## +function ogNvramSetTimeout () { +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_Timeout (seg)" \ + "$FUNCNAME 2" + return +fi +# +# Si no es equipo UEFI salir con error +ogIsEfiActive || ogRaiseError $OG_ERR_NOTUEFI || return $? + +# Error si no se recibe 1 parámetro. +[ $# -eq 1 ] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME int_Timeout (seg)" || return $? + +# Comprobamos que sea un número +[[ "$1" =~ ^([0-9 ]+)*$ ]] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME int_Timeout (seg)" || return $? + +# Cambiamos el orden +efibootmgr -t $1 &>/dev/null +} + + +#/** +# 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. +#*/ ## +function ogUuidChange () { +local MNTDIR DEVICE UUID NEWUUID f + +# Si se solicita, mostrar ayuda. +if [ "$*" == "help" ]; then + ogHelp "$FUNCNAME" "$FUNCNAME int_ndisk int_part" \ + "$FUNCNAME 1 2" + return +fi + +# Error si no se reciben al menos 2 parámetros. +[ $# -eq 2 ] || ogRaiseError $OG_ERR_FORMAT "$FUNCNAME int_ndisk int_part" || return $? + +# Comprobamos que exista la partición +MNTDIR=$(ogMount $1 $2) || ogRaiseError $OG_ERR_NOTFOUND "Device $1 $2" || return $? +DEVICE=$(ogDiskToDev $1 $2) +UUID=$(blkid -o value -s UUID $DEVICE) +NEWUUID=$(cat /proc/sys/kernel/random/uuid) + +# Cambiamos UUID a la partición +ogUnmount $1 $2 +tune2fs $DEVICE -U $NEWUUID + +# Cambiamos UUID en la configuración (fstab y grub) +ogMount $1 $2 +for f in $MNTDIR/etc/fstab $MNTDIR/{,boot/}{{grubMBR,grubPARTITION}/boot/,}{grub{,2},{,efi/}EFI/*}/{menu.lst,grub.cfg}; do + [ -r $f ] && sed -i s/$UUID/$NEWUUID/g $f +done +} diff --git a/client/lib/engine/bin/UEFILib.py b/client/lib/engine/bin/UEFILib.py deleted file mode 100644 index a70b5a7..0000000 --- a/client/lib/engine/bin/UEFILib.py +++ /dev/null @@ -1,579 +0,0 @@ -import os.path -import re -import subprocess -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. -#*/ ## -#ogNvramActiveEntry ('2') -#ogNvramActiveEntry ('Windows Boot Manager') -def ogNvramActiveEntry (entry): - if not InventoryLib.ogIsEfiActive(): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTUEFI, '') - return - - numentries = [] - efibootmgr_out = subprocess.run (['efibootmgr'], capture_output=True, text=True).stdout - try: - foo = int (entry, 16) ## raises ValueError if entry doesn't look like hexadecimal - num = f'{foo:04x}'.upper() - for l in efibootmgr_out.splitlines(): - words = l.split() - if len(words) < 2: continue - if num in words[0]: - numentries.append (words[0][4:8]) - except ValueError: - for l in efibootmgr_out.splitlines(): - words = l.split (maxsplit=1) - if len(words) < 2: continue - if words[1] == entry: - numentries.append (words[0][4:8]) - - if not numentries: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'NVRAM entry "{entry}"') - return - - if 1 != len(numentries): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_GENERIC, f'more than one entry found') - return - - subprocess.run (['efibootmgr', '-a', '-b', numentries[0]], capture_output=True, text=True) - -#/** -# 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. -#*/ ## -#ogNvramAddEntry ('1', '2', True) -#ogNvramAddEntry ('grub', '/EFI/grub/grubx64.efi', True) -#ogNvramAddEntry ('Windows', '/EFI/Microsoft/Boot/bootmgfw.efi') -def ogNvramAddEntry (bootlbl, bootldr, nvram_set=False): - if not InventoryLib.ogIsEfiActive(): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTUEFI, '') - return - - esp = DiskLib.ogGetEsp() - if not esp: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, 'ESP') - return - efidisk, efipar = esp.split() - - try: - foo = int(bootlbl) + int(bootldr) ## raises ValueError if bootlbl/bootldr don't look like numbers - bootlabel = f'Part-{int(bootlbl):02d}-{int(bootldr):02d}' - bootloader = f'/EFI/{bootlabel}/Boot/ogloader.efi' - except ValueError: - bootlabel = bootlbl - bootloader = bootldr - - ogNvramDeleteEntry (bootlabel) - - dev = DiskLib.ogDiskToDev (efidisk) - subprocess.run (['efibootmgr', '-C', '-d', dev, '-p', efipar, '-L', bootlabel, '-l', bootloader]) - - if nvram_set: - efibootmgr_out = subprocess.run (['efibootmgr'], capture_output=True, text=True).stdout - for l in efibootmgr_out.splitlines(): - words = l.split (maxsplit=1) - if len(words) < 2: continue - if words[1] == bootlabel: - numentry = words[0][4:8] - order = ogNvramGetOrder() - ogNvramSetOrder (order + [numentry]) - - - -#/** -# 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 -#*/ ## -def ogCopyEfiBootLoader (disk, par): - mntdir = FileSystemLib.ogMount (disk, par) - if not mntdir: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, f'{disk} {par}') - return None - - 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: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, 'ESP') - return - - bootlabel = f'Part-{int(disk):02d}-{int(par):02d}' - osversion = InventoryLib.ogGetOsVersion (disk, par) - print (f'bootlabel ({bootlabel})') - print (f'osversion ({osversion})') - if 'Windows 1' in osversion: - loader = None - for i in f'{efidir}/EFI/Microsoft/Boot/bootmgfw.efi', f'{efidir}/EFI/{bootlabel}/Boot/bootmgfw.efi': - if os.path.exists (i): - loader = i - if not loader: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTOS, f'{disk} {par} ({osversion}, EFI)') - return None - - if (os.path.isdir (f'{mntdir}/ogBoot')): - shutil.rmtree (f'{mntdir}/ogBoot') - dirloader = os.path.realpath (os.path.dirname (loader) + '/..') - shutil.copytree (f'{dirloader}/Boot', f'{mntdir}/ogBoot') - - -#/** -# 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). -#*/ ## -#ogNvramDeleteEntry ('2') -#ogNvramDeleteEntry ('Windows Boot Manager') -def ogNvramDeleteEntry (entry): - if not InventoryLib.ogIsEfiActive(): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTUEFI, '') - return - - numentries = [] - efibootmgr_out = subprocess.run (['efibootmgr'], capture_output=True, text=True).stdout - try: - foo = int (entry, 16) ## raises ValueError if entry doesn't look like hexadecimal - num = f'{foo:04x}'.upper() - for l in efibootmgr_out.splitlines(): - words = l.split() - if len(words) < 2: continue - if num in words[0]: - numentries.append (words[0][4:8]) - except ValueError: - for l in efibootmgr_out.splitlines(): - words = l.split (maxsplit=1) - if len(words) < 2: continue - if words[1] == entry: - numentries.append (words[0][4:8]) - - if not numentries: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'NVRAM entry "{entry}"') - return - - if 1 != len(numentries): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_GENERIC, f'more than one entry found') - return - - subprocess.run (['efibootmgr', '-B', '-b', numentries[0]], capture_output=True, text=True) - - - -#/** -# 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. -#*/ ## -def ogNvramGetCurrent(): - if not InventoryLib.ogIsEfiActive(): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTUEFI, '') - return - - bootentry = '9999' - ret = None - efibootmgr_out = subprocess.run (['efibootmgr'], capture_output=True, text=True).stdout - for l in efibootmgr_out.splitlines(): - words = l.split (maxsplit=1) - if len(words) < 2: continue - if 'BootCurrent' in words[0]: - bootentry = words[1] - continue - if bootentry in words[0]: - num = words[0][4:8].strip ('0') or '0' - ret = f'{num} {words[1]}' - return ret - - -# 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. -#*/ ## -def ogNvramGetNext(): - if not InventoryLib.ogIsEfiActive(): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTUEFI, '') - return - - ret = None - efibootmgr_out = subprocess.run (['efibootmgr'], capture_output=True, text=True).stdout - for l in efibootmgr_out.splitlines(): - words = l.split (maxsplit=1) - if len(words) < 2: continue - if 'BootNext' in words[0]: - ret = words[1] - return ret - - -# ogNvramGetOrder -#@brief Muestra el orden de las entradas del gestor de arranque (NVRAM) -#@return Array, orden de las entradas -#@exception OG_ERR_NOTUEFI UEFI no activa. -#*/ ## -def ogNvramGetOrder(): - if not InventoryLib.ogIsEfiActive(): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTUEFI, '') - return - - ret = [] - efibootmgr_out = subprocess.run (['efibootmgr'], capture_output=True, text=True).stdout - for l in efibootmgr_out.splitlines(): - words = l.split() - if len(words) < 2: continue - if 'BootOrder:' == words[0]: - ret = words[1].split (',') - return ret - - -#/** -# ogNvramGetTimeout -#@brief Muestra el tiempo de espera del gestor de arranque (NVRAM) -#@return Timeout de la NVRAM -#@exception OG_ERR_NOTUEFI UEFI no activa. -#*/ ## -def ogNvramGetTimeout(): - if not InventoryLib.ogIsEfiActive(): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTUEFI, '') - return - - ret = None - efibootmgr_out = subprocess.run (['efibootmgr'], capture_output=True, text=True).stdout - for l in efibootmgr_out.splitlines(): - words = l.split (maxsplit=1) - if len(words) < 2: continue - if 'Timeout:' == words[0]: - ret = words[1] - return ret - - -#/** -# 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. -#*/ ## -#ogNvramInactiveEntry ('2') -#ogNvramInactiveEntry ('Windows Boot Manager') -def ogNvramInactiveEntry (entry): - if not InventoryLib.ogIsEfiActive(): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTUEFI, '') - return - - numentries = [] - efibootmgr_out = subprocess.run (['efibootmgr'], capture_output=True, text=True).stdout - try: - foo = int (entry, 16) ## raises ValueError if entry doesn't look like hexadecimal - num = f'{foo:04x}'.upper() - for l in efibootmgr_out.splitlines(): - words = l.split() - if len(words) < 2: continue - if num in words[0]: - numentries.append (words[0][4:8]) - except ValueError: - for l in efibootmgr_out.splitlines(): - words = l.split (maxsplit=1) - if len(words) < 2: continue - if words[1] == entry: - numentries.append (words[0][4:8]) - - if not numentries: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'NVRAM entry "{entry}"') - return - - if 1 != len(numentries): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_GENERIC, f'more than one entry found') - return - - subprocess.run (['efibootmgr', '-A', '-b', numentries[0]], capture_output=True, text=True) - - -#/** -# ogNvramList -#@brief Lista las entradas de la NVRAN (sólo equipos UEFI) -#@return Multiline string: entradas de la NVRAM con el formato: orden etiqueta [* (si está activa) ] -#@exception OG_ERR_NOTUEFI UEFI no activa. -#*/ ## -def ogNvramList(): - if not InventoryLib.ogIsEfiActive(): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTUEFI, '') - return - - ret = '' - efibootmgr_out = subprocess.run (['efibootmgr'], capture_output=True, text=True).stdout - for l in efibootmgr_out.splitlines(): - words = l.split (maxsplit=1) - if len(words) < 2: continue - if re.search ('Boot[0-9]', words[0]): - active = '*' if '*' in words[0] else '' - num = words[0][4:8].strip ('0') or '0' - ret += '{:>4s} {} {}\n'.format (num, words[1], active) - return ret - - -#/** -# 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. -#*/ ## -def ogNvramPxeFirstEntry(): - if not InventoryLib.ogIsEfiActive(): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTUEFI, '') - return - - num = '' - efibootmgr_out = subprocess.run (['efibootmgr'], capture_output=True, text=True).stdout - for l in efibootmgr_out.splitlines(): - if re.search ('IP[vV]{0,1}4', l): - num = l[4:8].strip ('0') or '0' - numentry = f'{int(num):04x}'.upper() - - o = ogNvramGetOrder() - if not o: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_GENERIC, f'ogNvramGetOrder returned an empty list') - return - - # Si la entrada es la primera nos salimos. - if numentry == o[0]: - return True - - # Si la entrada ya existe la borramos. - order = [numentry] + list (filter (lambda x: x if x!=numentry else [], o)) - ogNvramSetOrder (order) - - return True - - -#/** -# 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-{int(disk):02d}-{int(par):02d}' - loader = FileLib.ogGetPath (file=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 (file=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. -#*/ ## -#ogNvramSetNext ('2') -#ogNvramSetNext ('Windows Boot Manager') -def ogNvramSetNext (entry): - if not InventoryLib.ogIsEfiActive(): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTUEFI, '') - return - - numentries = [] - efibootmgr_out = subprocess.run (['efibootmgr'], capture_output=True, text=True).stdout - try: - foo = int (entry, 16) ## raises ValueError if entry doesn't look like hexadecimal - num = f'{foo:04x}'.upper() - for l in efibootmgr_out.splitlines(): - words = l.split() - if len(words) < 2: continue - if num in words[0]: - numentries.append (words[0][4:8]) - except ValueError: - for l in efibootmgr_out.splitlines(): - words = l.split (maxsplit=1) - if len(words) < 2: continue - if words[1] == entry: - numentries.append (words[0][4:8]) - - if not numentries: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'NVRAM entry "{entry}"') - return - - if 1 != len(numentries): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_GENERIC, f'more than one entry found') - return - - subprocess.run (['efibootmgr', '-n', numentries[0]], capture_output=True, text=True) - -#/** -# 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). -#*/ ## -#ogNvramSetOrder (['1', '3']) -def ogNvramSetOrder (order): - if not InventoryLib.ogIsEfiActive(): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTUEFI, '') - return - - try: - for i in order: - foo = int (i, 16) - except ValueError: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, 'ogNvramSetOrder ([array or hex values])') - return - - # Entradas de la NVRAM actuales - numentries = [] - efibootmgr_out = subprocess.run (['efibootmgr'], capture_output=True, text=True).stdout - for l in efibootmgr_out.splitlines(): - words = l.split() - if len(words) < 2: continue - if re.search ('Boot[0-9a-fA-F]{4}', words[0]): - numentries.append ('0' + words[0][4:8]) - - new_order = [] - for o in order: - h = f'{int(o,16):05x}'.upper() - if h not in numentries: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'NVRAM entry order "{h}"') - return - new_order.append (h) - - subprocess.run (['efibootmgr', '-o', ','.join (new_order)]) - - -#/** -# 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. -#*/ ## -#ogNvramSetTimeout ('2') -def ogNvramSetTimeout (t): - if not InventoryLib.ogIsEfiActive(): - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTUEFI, '') - return - - try: - num = int (t) ## raises ValueError if t doesn't look like a number - except ValueError: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, 'ogNvramSetTimeout (timeout)') - return - - subprocess.run (['efibootmgr', '-t', t]) - - -#/** -# 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. -#*/ ## diff --git a/client/lib/engine/bin/__init__.py b/client/lib/engine/bin/__init__.py deleted file mode 100755 index e69de29..0000000 diff --git a/client/lib/engine/bin/lang_ca_ES.py b/client/lib/engine/bin/lang_ca_ES.py deleted file mode 100755 index 81e48ca..0000000 --- a/client/lib/engine/bin/lang_ca_ES.py +++ /dev/null @@ -1,400 +0,0 @@ -#!/usr/bin/python3 - -# Fichero de idioma: catalá. -#@version 1.1.1 -#@author - - -# Mensajes de error. -MSG_ERR_GENERIC="Error imprevisto no definido" -MSG_ERR_FORMAT="Formato de ejecución incorrecto" -MSG_ERR_OUTOFLIMIT="Valor fuera de rango o no válido" -MSG_ERR_NOTFOUND="Fichero o dispositivo no encontrado" -MSG_ERR_PARTITION="Partición errónea o desconocida" -MSG_ERR_LOCKED="Recurso bloqueado por operación de uso exclusivo" -MSG_ERR_CACHE="Error en partición de caché local" -MSG_ERR_NOGPT="El disco indicado no contiene una particion GPT" -MSG_ERR_REPO="Error al montar el repositorio de imágenes" -MSG_ERR_NOMSDOS="El disco indicado no contiene una partición MSDOS" -MSG_ERR_FILESYS="Sistema de archivos desconocido o no se puede montar" -MSG_ERR_NOTOS="Sistema operativo no detectado o no se puede iniciar" -MSG_ERR_IMAGE="No se puede crear o restaurar una image de sistema" -MSG_ERR_IMAGEFILE="Archivo de imagen corrupto o de otra versión de partclone" -MSG_ERR_NOTEXEC="Programa o función no ejecutable" -MSG_ERR_NOTWRITE="No hay acceso de escritura" -MSG_ERR_NOTCACHE="No existe particion Cache en el cliente" -MSG_ERR_NOTUEFI="La interfaz UEFI no está activa" -MSG_ERR_NOTBIOS="La interfaz BIOS Legacy no está activa" -MSG_ERR_CACHESIZE="El espacio de la cache local o remota no es suficiente" -MSG_ERR_REDUCEFS="Error al reducir el sistema de archivos" -MSG_ERR_EXTENDFS="Error al expandir el sistema de archivos" -MSG_ERR_IMGSIZEPARTITION="Error al restaurar: Particion mas pequeña que la imagen" -MSG_ERR_UPDATECACHE="Error al realizar el comando updateCache" -MSG_ERR_UCASTSYNTAXT="Error en la generación de sintaxis de transferenica unicast" -MSG_ERR_UCASTSENDPARTITION="Error en envio UNICAST de una particion" -MSG_ERR_UCASTSENDFILE="Error en envio UNICAST de un fichero" -MSG_ERR_UCASTRECEIVERPARTITION="Error en la recepcion UNICAST de una particion" -MSG_ERR_UCASTRECEIVERFILE="Error en la recepcion UNICAST de un fichero" -MSG_ERR_MCASTSYNTAXT="Error en la generación de sintaxis de transferenica multicast" -MSG_ERR_MCASTSENDFILE="Error en envio MULTICAST de un fichero" -MSG_ERR_MCASTRECEIVERFILE="Error en la recepcion MULTICAST de un fichero" -MSG_ERR_MCASTSENDPARTITION="Error en envio MULTICAST de una particion" -MSG_ERR_MCASTRECEIVERPARTITION="Error en la recepcion MULTICAST de un fichero" -MSG_ERR_PROTOCOLJOINMASTER="Error en la conexion de una sesion UNICAST|MULTICAST con el MASTER" -MSG_ERR_DONTFORMAT="Error al formatear" -MSG_ERR_DONTMOUNT_IMAGE="Error al montar/reducir la imagen" -MSG_ERR_DONTUNMOUNT_IMAGE="Error al desmontar la imagen" -MSG_ERR_DONTSYNC_IMAGE="Imagen no sincronizable" -MSG_ERR_NOTDIFFERENT="No se detectan diferencias entre la imagen basica y la particion." -MSG_ERR_SYNCHRONIZING="Error al sincronizar, puede afectar la creacion|restauracion de la imagen" - -# Mensajes de avisos. -MSG_DONTUSE="NO USAR" -MSG_DONTMOUNT="Sistema de archivos no montado" -MSG_DONTUNMOUNT="El sistema de archivos no se puede desmontar o no está montado" -MSG_MOUNT="Sistema de archivos montado" -MSG_MOUNTREADONLY="Sistema de archivos montado solo de lectura" -MSG_OBSOLETE="EN DESUSO" - -# Mensajes complementarios para las ayudas. -MSG_64BIT="64 bits" -MSG_DISK="disc" -MSG_ERROR="Error" -MSG_EXAMPLE="Exemple" -MSG_FORMAT="Format" -MSG_FUNCTION="Funció" -MSG_HARDWAREINVENTORY="Inventario de maquinari de la màquina" -MSG_IMAGE="imatge" -MSG_INSTALLED="instal-lat" -MSG_NOCACHE="sense caché local" -MSG_NOEXTENDED="sense partició estensa" -MSG_PARTITION="partició" -MSG_PROTOCOL="protocol" -MSG_RESERVEDVALUE="Valor reservat" -MSG_SEE="Veure" -MSG_UNKNOWN="Desconegut" -MSG_WARNING="Avís" - -# Mensajes del proceso de arranque. -MSG_DETECTLVMRAID="Detectar metadispositivos LVM y RAID." -MSG_ERRBOOTMODE=f"{MSG_ERROR}: Modo de arranque desconocido." -MSG_LAUNCHCLIENT="Ejecutar cliente." -MSG_LOADAPI="Cargar funciones del motor de clonación." -MSG_LOADMODULES="Cargar módulos del kernel." -MSG_MAKELINKS="Crear enlaces simbólicos." -MSG_MOUNTREPO="Montar repositorio por %s en modo %s." -MSG_OFFLINEMODE="Modo de arranque sin conexión." -MSG_OTHERSERVICES="Iniciar servicios complementarios del cliente." -MSG_POWEROFFCONF="Definir parámetros de ahorro de energía." - -# Mensajes del menú por defecto. -MSG_BOOT="Iniciar" -MSG_DUPLEX="Dúplex" -MSG_HOSTNAME="Equipo" -MSG_IPADDR="Dirección IP" -MSG_MACADDR="Dirección MAC" -MSG_MENUTITLE="Menú de opciones" -MSG_POWEROFF="Apagar el equipo" -MSG_SPEED="Velocidad" - -# Mensajes de descripción breve de las funciones de la API. -MSG_HELP_ogAclFilter="Extrae las acl de los ficheros de la diferencial" -MSG_HELP_ogAddCmd="Añade comandos al fichero creado por la función ogInstalMiniSetup." -MSG_HELP_ogAddRegistryKey="Añade una nueva clave al registro de Windows." -MSG_HELP_ogAddRegistryValue="Añade un nuevo valor al registro de Windows." -MSG_HELP_ogAddToLaunchDaemon="" -MSG_HELP_ogBoot="Arranca un sistema operativo instalado." -MSG_HELP_ogBootLoaderDeleteEntry=MSG_DONTUSE -MSG_HELP_ogBootLoaderHidePartitions=MSG_DONTUSE -MSG_HELP_ogBootMbrGeneric="" -MSG_HELP_ogBootMbrXP="" -MSG_HELP_ogBurgDefaultEntry="Configura la entrada por defecto de Burg." -MSG_HELP_ogBurgDeleteEntry="Borra en el Burg del MBR las entradas para el inicio en una particion." -MSG_HELP_ogBurgHidePartitions="Configura el Burg del MBR para que oculte las particiones de windows que no se esten iniciando. Permite definir una partición que no se ocultará (ej: para datos)." -MSG_HELP_ogBurgInstallMbr="Instal·la el carregador d'arrencada BURG al MBR del primer disc dur" -MSG_HELP_ogBurgOgliveDefaultEntry="Configura la entrada de ogLive como la entrada por defecto de Burg." -MSG_HELP_ogCalculateChecksum="Calcula la suma de comprobación (checksum) de un fichero." -MSG_HELP_ogCalculateFullChecksum="" -MSG_HELP_ogChangeRepo="Cambia el repositorio para el recurso remoto images." -MSG_HELP_ogCheckFs="Comprueba la consistencia de un sistema de archivos." -MSG_HELP_ogCheckIpAddress="" -MSG_HELP_ogCheckProgram="" -MSG_HELP_ogCheckStringInGroup="" -MSG_HELP_ogCheckStringInReg="" -MSG_HELP_ogCheckSyncImage="Muestra el contenido de la imagen para comprobarla." -MSG_HELP_ogCleanLinuxDevices="" -MSG_HELP_ogCleanOs="Elimina los archivos que no son necesarios en el sistema operativo." -MSG_HELP_ogCompareChecksumFiles="Compara si coinciden las sumas de comprobación almacenadas de 2 ficheros." -MSG_HELP_ogConfigureFstab="" -MSG_HELP_ogConfigureOgagent="Configura el nuevo agente OGAgent para sistemas ooperativos." -MSG_HELP_ogCopyFile="Copia un fichero a otro almacenamiento." -MSG_HELP_ogCreateBootLoaderImage="" -MSG_HELP_ogCreateCache="Reserva espacio para la partición de caché al final del disco." -MSG_HELP_ogCreateDiskImage="Genera una imagen exacta de un disco completo." -MSG_HELP_ogCreateFileImage="Crea/Redimensiona el archivo de la imagen sincronizada" -MSG_HELP_ogCreateGptPartitions="" -MSG_HELP_ogCreateImage="Genera una imagen exacta de un sistema operativo instalado localmente." -MSG_HELP_ogCreateImageSyntax="" -MSG_HELP_ogCreateInfoImage="Crea informacion del contenido de la imagen" -MSG_HELP_ogCreateMbrImage="Genera una imagen del sector de arranque (MBR)." -MSG_HELP_ogCreatePartitions="Define la estructura de particiones de un disco." -MSG_HELP_ogCreatePartitionTable="Genera una tabla de particiones en caso de que no sea valida." -MSG_HELP_ogCreateTorrent="" -MSG_HELP_ogCopyEfiBootLoader="Copia el cargador de arranque desde la partición EFI a la de sistema." -MSG_HELP_ogDeleteCache="Elimina la partición de caché local." -MSG_HELP_ogDeleteFile="Borra un fichero de un espacio de almacenamiento." -MSG_HELP_ogDeletePartitionTable="Elimina la tabla de particiones del disco" -MSG_HELP_ogDeleteRegistryKey="Borra una clave vacía del registro de Windows." -MSG_HELP_ogDeleteRegistryValue="Borra un valor del registro de Windows." -MSG_HELP_ogDeleteTree="Borra un árbol de directorios de un espacio de almacenamiento." -MSG_HELP_ogDevToDisk="Devuelve el nº de orden de disco o de partición correspondiente al camino del fichero de dispositivo." -MSG_HELP_ogDiskToDev="Devuelve el camino del fichero de dispositivo correspondiente al nº de orden de disco o de partición." -MSG_HELP_ogDomainScript="" -MSG_HELP_ogEcho="" -MSG_HELP_ogExecAndLog="" -MSG_HELP_ogExtendFs="Extiende el tamaño de un sistema de archivo al máximo de su partición." -MSG_HELP_ogFindCache="Indica la partición reservada para caché local." -MSG_HELP_ogFixBootSector="" -MSG_HELP_ogFormatCache="Formatea (inicia) el sistema de caché local." -MSG_HELP_ogFormat="Formatea o reformatea un sistema de archivos." -MSG_HELP_ogFormatFs=MSG_HELP_ogFormat -MSG_HELP_ogGetArch="Devuelve el tipo de arquitectura del cliente." -MSG_HELP_ogGetCacheSize="Devuelve el tamaño de la partición de caché local." -MSG_HELP_ogGetCacheSpace="Devuelve el espacio máximo disponible que puede ser reservado para la partición de caché local." -MSG_HELP_ogGetCaller="" -MSG_HELP_ogGetDiskSize="Devuelve el tamaño del disco." -MSG_HELP_ogGetDiskType="Devuelve el mnemónico de tipo de disco." -MSG_HELP_ogGetFreeSize="" -MSG_HELP_ogGetFsSize="Devuelve el tamaño de un sistema de archivos." -MSG_HELP_ogGetFsType="Devuelve el mnemónico de tipo de sistema de archivos." -MSG_HELP_ogGetGroupDir="Devuelve el camino del directorio por defecto para el grupo del cliente." -MSG_HELP_ogGetGroupName="Devuelve el nombre del grupo al que pertenece el cliente." -MSG_HELP_ogGetHivePath="Devuelve el camino completo del fichero de una sección del registro de Windows." -MSG_HELP_ogGetHostname="Devuelve el nombre de la máquina local." -MSG_HELP_ogGetImageCompressor="Devuelve la herramienta de compresión de la imagen." -MSG_HELP_ogGetImageInfo="Muestra información sobre la imagen monolitica: clonacion:compresor:sistemaarchivos:tamañoKB." -MSG_HELP_ogGetImageProgram="Devuelve el programa usado para crear la imagen." -MSG_HELP_ogGetImageSize="Devuelve el tamaño de una imagen de sistema." -MSG_HELP_ogGetImageType="Devuelve el sistema de ficheros de la imagen." -MSG_HELP_ogGetIpAddress="Devuelve la dirección IP del cliente." -MSG_HELP_ogGetLastSector="Devuelve el último sector usable del disco o de una partición." -MSG_HELP_ogGetMacAddress="Devuelve la dirección Ethernet del cliente." -MSG_HELP_ogGetMountImageDir="Devuelve el directorio de montaje de una imagen." -MSG_HELP_ogGetMountPoint="Devuelve el directorio donde está montado un sistema de archivos local." -MSG_HELP_ogGetNetInterface="" -MSG_HELP_ogGetOsType="Devuelve el tipo de un sistema operativo instalado." -MSG_HELP_ogGetOsUuid="" -MSG_HELP_ogGetOsVersion="Devuelve el tipo y la versión de un sistema operativo instalado." -MSG_HELP_ogGetParentPath="Devuelve el camino completo del directorio padre de un fichero de sistema OpenGnsys." -MSG_HELP_ogGetPartitionActive="Indica cual es la partición marcada como activa en un disco." -MSG_HELP_ogGetPartitionId="Devuelve el identificador de tipo de una partición." -MSG_HELP_ogGetPartitionSize="Devuelve el tamaño de una partición." -MSG_HELP_ogGetPartitionsNumber="" -MSG_HELP_ogGetPartitionTableType="Devuelve el tipo de tabla de particiones del disco" -MSG_HELP_ogGetPartitionType="Devuelve el mnemónico de tipo de una partición." -MSG_HELP_ogGetPath="Devuelve el camino completo de un fichero de sistema OpenGnsys." -MSG_HELP_ogGetRegistryValue="Devuelve el dato de un valor del registro de Windows." -MSG_HELP_ogGetRepoIp="Devuelve la dirección IP del repositorio de datos." -MSG_HELP_ogGetSerialNumber="Devuelve el número de serie del cliente." -MSG_HELP_ogGetServerIp="Devuelve la dirección IP del servidor principal." -MSG_HELP_ogGetSizeParameters="Devuelve el tamaño de los datos de un sistema de ficheros, el espacio necesario para la imagen y si cabe en el repositorio elegido." -MSG_HELP_ogGetWindowsName="Devuelve el nombre del cliente guardado en el registro de Windows." -MSG_HELP_ogGrubAddOgLive="Incluye en el grub del MBR una entrada llamando al cliente de opengnsys." -MSG_HELP_ogGrubDefaultEntry="Configura la entrada por defecto de GRUB." -MSG_HELP_ogGrubDeleteEntry="Borra en el grub del MBR las entradas para el inicio en una particion." -MSG_HELP_ogGrubHidePartitions="Configura el grub del MBR para que oculte las particiones de windows que no se esten iniciando. Permite definir una partición que no se ocultará (ej: para datos)." -MSG_HELP_ogGrubInstallMbr="Instal·la el carregador d'arrencada GRUB al MBR del primer disc dur" -MSG_HELP_ogGrubInstallPartition="Instal·la el carregador d'arrencada BURG al BootSector" -MSG_HELP_ogGrubOgliveDefaultEntry="Configura la entrada de ogLive como la entrada por defecto de GRUB." -MSG_HELP_ogGrubSecurity="Configura usuario y clave para modificar las entradas del menu del Grub." -MSG_HELP_ogGrubUefiConf="Genera el fichero grub.cfg de la partición EFI." -MSG_HELP_ogHelp="Muestra mensajes de ayudas para las funciones." -MSG_HELP_ogHidePartition="Oculta una partición de Windows." -MSG_HELP_ogIdToType="Devuelve el mnemónico asociado al identificador de tipo de partición." -MSG_HELP_ogNvramActiveEntry="Configura a activa entrada del gestor de arranque (NVRAM)." -MSG_HELP_ogNvramAddEntry="Crea nueva entrada del gestor de arranque (NVRAM)." -MSG_HELP_ogNvramDeleteEntry="Borra entrada del gestor de arranque (NVRAM)." -MSG_HELP_ogNvramGetCurrent="Muestra la entrada del gestor de arranque (NVRAM) que ha iniciado el equipo." -MSG_HELP_ogNvramGetNext="Muestra la entrada del gestor de arranque (NVRAM) que se utilizará en el próximo arranque." -MSG_HELP_ogNvramGetOrder="Muestra el orden de las entradas del gestor de arranque (NVRAM)." -MSG_HELP_ogNvramGetTimeout="Muestra el tiempo de espera del gestor de arranque (NVRAM)." -MSG_HELP_ogNvramInactiveEntry="Configura a inactiva entrada del gestor de arranque (NVRAM)." -MSG_HELP_ogNvramList="Lista las entradas del gestor de arranque (NVRAN) marcando con un asterisco las activas" -MSG_HELP_ogNvramSetNext="Configura el próximo arranque con la entrada del gestor de arranque (NVRAM)." -MSG_HELP_ogNvramSetOrder="Configura el orden de las entradas del gestor de arranque (NVRAM)." -MSG_HELP_ogNvramSetTimeout="Configura el tiempo de espera del gestor de arranque (NVRAM)." -MSG_HELP_ogGetOsType="Devuelve el tipo de un sistema operativo instalado." -MSG_HELP_ogInstallFirstBoot="Crea un archivo que se ejecutará en el primer arranque de Windows." -MSG_HELP_ogInstallLaunchDaemon="Instala un archivo que se ejecutará en el arranque de macOS." -MSG_HELP_ogInstallLinuxClient=MSG_OBSOLETE -MSG_HELP_ogInstallMiniSetup="Instala un archivo que se ejecutará en el arranque de Windows." -MSG_HELP_ogInstallRunonce="Crea un archivo que se ejecutará en el inicio de un usuario administrador de Windows." -MSG_HELP_ogInstallWindowsClient=MSG_OBSOLETE -MSG_HELP_ogIsFormated="Comprueba si un sistema de archivos está formateado." -MSG_HELP_ogIsImageLocked="Comprueba si una imagen está bloqueada por una operación de uso exclusivo." -MSG_HELP_ogIsLocked="Comprueba si una partición o su disco están bloqueados por una operación de uso exclusivo." -MSG_HELP_ogIsDiskLocked="Comprueba si un disco está bloqueado por una operación de uso exclusivo." -MSG_HELP_ogIsMounted="Comprueba si un sistema de archivos está montado." -MSG_HELP_ogIsNewerFile="Comprueba si un fichero es más nuevo (se ha modificado después) que otro." -MSG_HELP_ogIsPartitionLocked=MSG_HELP_ogIsLocked -MSG_HELP_ogIsRepoLocked="" -MSG_HELP_ogIsSyncImage="Comprueba si la imagen es sincronizable." -MSG_HELP_ogIsVirtualMachine="" -MSG_HELP_ogIsWritable="Comprueba si un sistema de archivos está montado con permiso de escritura." -MSG_HELP_ogLinuxBootParameters="Devuelve los parámetros de arranque de un sistema operativo Linux instalado." -MSG_HELP_ogListHardwareInfo="Lista el inventario de dispositivos del cliente." -MSG_HELP_ogListLogicalPartitions="" -MSG_HELP_ogListPartitions="Lista la estructura de particiones de un disco." -MSG_HELP_ogListPrimaryPartitions="" -MSG_HELP_ogListRegistryKeys="Lista los nombres de las subclaves incluidas en una clave del registro de Windows." -MSG_HELP_ogListRegistryValues="Lista los nombres de los valores incluidos en una clave del registro de Windows." -MSG_HELP_ogListSoftware="Lista el inventario de programas instalados en un sistema operativo." -MSG_HELP_ogLock="Bloquea una partición para operación de uso exclusivo." -MSG_HELP_ogLockDisk="Bloquea un disco para operación de uso exclusivo." -MSG_HELP_ogLockImage="Bloquea una imagen para operación de uso exclusivo." -MSG_HELP_ogLockPartition=MSG_HELP_ogLock -MSG_HELP_ogMakeChecksumFile="Almacena la suma de comprobación de un fichero." -MSG_HELP_ogMakeDir="Crea un directorio para OpenGnsys." -MSG_HELP_ogMakeGroupDir="Crea el directorio de grupo (aula) en un repositorio." -MSG_HELP_ogMcastReceiverFile="" -MSG_HELP_ogMcastReceiverPartition="" -MSG_HELP_ogMcastRequest="" -MSG_HELP_ogMcastSendFile="" -MSG_HELP_ogMcastSendPartition="" -MSG_HELP_ogMcastSyntax="" -MSG_HELP_ogMountCache="Monta el sistema de archivos dedicado a caché local." -MSG_HELP_ogMountCdrom="Monta dispositivo óptico por defecto." -MSG_HELP_ogMountImage="Monta una imagen sincronizable" -MSG_HELP_ogMount="Monta un sistema de archivos y devuelve el punto de montaje." -MSG_HELP_ogMountFs=MSG_HELP_ogMount -MSG_HELP_ogNvramActiveEntry="Configura a activa entrada del gestor de arranque (NVRAM)." -MSG_HELP_ogNvramAddEntry="Crea nueva entrada del gestor de arranque (NVRAM)." -MSG_HELP_ogNvramDeleteEntry="Borra entrada del gestor de arranque (NVRAM)." -MSG_HELP_ogNvramGetCurrent="Muestra la entrada del gestor de arranque (NVRAM) que ha iniciado el equipo." -MSG_HELP_ogNvramGetNext="Muestra la entrada del gestor de arranque (NVRAM) que se utilizará en el próximo arranque." -MSG_HELP_ogNvramGetOrder="Muestra el orden de las entradas del gestor de arranque (NVRAM)." -MSG_HELP_ogNvramGetTimeout="Muestra el tiempo de espera del gestor de arranque (NVRAM)." -MSG_HELP_ogNvramInactiveEntry="Configura a inactiva entrada del gestor de arranque (NVRAM)." -MSG_HELP_ogNvramList="Lista las entradas del gestor de arranque (NVRAN) marcando con un asterisco las activas" -MSG_HELP_ogNvramPxeFirstEntry="Configura la tarjeta de red como primer arranque en la NVRAM." -MSG_HELP_ogNvramSetNext="Configura el próximo arranque con la entrada del gestor de arranque (NVRAM)." -MSG_HELP_ogNvramSetOrder="Configura el orden de las entradas del gestor de arranque (NVRAM)." -MSG_HELP_ogNvramSetTimeout="Configura el tiempo de espera del gestor de arranque (NVRAM)." -MSG_HELP_ogRaiseError="Muestra y registra mensajes de error y devuelve el código correspondiente." -MSG_HELP_ogReduceFs="Reduce el tamaño del sistema de archivos al mínimo ocupado por sus datos." -MSG_HELP_ogReduceImage="Reduce el tamaño de la imagen" -MSG_HELP_ogRefindDeleteEntry="Borra en rEFInd las entradas para el inicio en una particion." -MSG_HELP_ogRefindDefaultEntry="Configura la entrada por defecto de rEFInd." -MSG_HELP_ogRefindOgliveDefaultEntry="Configura la entrada de ogLive como la entrada por defecto de rEFInd." -MSG_HELP_ogRefindSetTheme="Asigna un tema al rEFInd." -MSG_HELP_ogRefindSetTimeOut="Define el tiempo (segundos) que se muestran las opciones de inicio de rEFInd." -MSG_HELP_ogRefindSetResolution="Define la resolución que usuará el thema del gestor de arranque rEFInd." -MSG_HELP_ogRefindInstall="Instala y configura el gestor rEFInd en la particion EFI" -MSG_HELP_ogRestoreAclImage="" -MSG_HELP_ogRestoreBootLoaderImage="" -MSG_HELP_ogRestoreDiskImage="Restaura una imagen de un disco completo." -MSG_HELP_ogRestoreEfiBootLoader="Copia el cargador de arranque de la partición de sistema a la partición EFI." -MSG_HELP_ogRestoreImage="Restaura una imagen de sistema operativo." -MSG_HELP_ogRestoreInfoImage="Restablece informacion del sistema: acl y enlaces simbolicos" -MSG_HELP_ogRestoreMbrImage="Restaura una imagen del sector de arranque (MBR)." -MSG_HELP_ogRestoreUuidPartitions="Restaura los uuid de las particiones y la tabla de particiones." -MSG_HELP_ogSaveImageInfo="Crea un fichero con la información de la imagen." -MSG_HELP_ogSetLinuxName="" -MSG_HELP_ogSetPartitionActive="Establece el número de partición activa de un disco." -MSG_HELP_ogSetPartitionId="Modifica el tipo de una partición física usando el mnemónico del tipo." -MSG_HELP_ogSetPartitionSize="Establece el tamaño de una partición." -MSG_HELP_ogSetPartitionType="Modifica el identificador de tipo de una partición física." -MSG_HELP_ogSetRegistryValue="Asigna un dato a un valor del registro de Windows." -MSG_HELP_ogSetWindowsName="Asigna el nombre del cliente en el registro de Windows." -MSG_HELP_ogSetWinlogonUser="Asigna el nombre de usuario por defecto para el gestor de entrada de Windows." -MSG_HELP_ogSyncCreate="Sincroniza los datos de la particion a la imagen" -MSG_HELP_ogSyncRestore="Sincroniza los datos de la imagen a la particion" -MSG_HELP_ogTorrentStart="" -MSG_HELP_ogTypeToId="Devuelve el identificador asociado al mnemónico de tipo de partición." -MSG_HELP_ogUcastReceiverPartition="" -MSG_HELP_ogUcastSendFile="" -MSG_HELP_ogUcastSendPartition="" -MSG_HELP_ogUcastSyntax="" -MSG_HELP_ogUnhidePartition="Hace visible una partición de Windows." -MSG_HELP_ogUninstallLinuxClient="Desinstala el cliente OpenGnSys en un sistema operativo Linux." -MSG_HELP_ogUninstallWindowsClient="Desinstala el cliente OpenGnSys en un sistema operativo Windows." -MSG_HELP_ogUnlock="Desbloquea una partición tras finalizar una operación de uso exclusivo." -MSG_HELP_ogUnlockDisk="Desbloquea un disco tras finalizar una operación de uso exclusivo." -MSG_HELP_ogUnlockImage="Desbloquea una imagen tras finalizar una operación de uso exclusivo." -MSG_HELP_ogUnlockPartition=MSG_HELP_ogUnlock -MSG_HELP_ogUnmountAll="Desmonta todos los sistemas de archivos." -MSG_HELP_ogUnmountCache="Desmonta el sistema de archivos de caché local." -MSG_HELP_ogUnmount="Desmonta un sistema de archivos." -MSG_HELP_ogUnmountImage="Desmonta la imagen" -MSG_HELP_ogUnmountFs=MSG_HELP_ogUnmount -MSG_HELP_ogUnsetDirtyBit="" -MSG_HELP_ogUpdateCacheIsNecesary="Comprueba si es necesario actualizar una archivo en la cache local." -MSG_HELP_ogUpdatePartitionTable="Actualiza informacion tabla particiones del disco" -MSG_HELP_ogUuidChange="Reemplaza el UUID de un sistema de ficheros." -MSG_HELP_ogWaitSyncImage="" -MSG_HELP_ogWindowsBootParameters="" -MSG_HELP_ogWindowsRegisterPartition="" - -# Scripts -MSG_HELP_configureOs="Post-configura de arranque del sistema" -MSG_HELP_createBaseImage="Genera imagen basica de la particion" -MSG_HELP_createDiffImage="Genera imagen diferencial de la particion respecto a la imagen basica" -MSG_HELP_installOfflineMode="Prepara el equipo cliente para el modo offline." -MSG_HELP_partclone2sync="Convierte imagen de partclone en imagen sincronizable." -MSG_HELP_restoreBaseImage="Restaura una imagen basica en una particion" -MSG_HELP_restoreDiffImage="Restaura una imagen diferencial en una particion" -MSG_HELP_updateCache="Realiza la actualizacion de la cache" - -# Mensajes de descripción breve de la interfaz. -MSG_INTERFACE_START="[START Interface] Ejecutar comando: " -MSG_INTERFACE_END="[END Interface] Comando terminado con este código: " - -# Mensajes de scripts. -MSG_SCRIPTS_START=" INICIO scripts : " -MSG_SCRIPTS_END=" FIN scripts: " -MSG_SCRIPTS_TASK_END="Fin de la tarea" - -MSG_SCRIPTS_TASK_SLEEP="Esperando para iniciar" -MSG_SCRIPTS_TASK_START="Iniciando" -MSG_SCRIPTS_TASK_ERR="Error" - -# Script createImage. -MSG_SCRIPTS_FILE_RENAME=" Renombrar fichero-imagen previo: " -MSG_SCRIPTS_CREATE_SIZE=" Calcular espacio (KB) requerido para almacenarlo y el disponible: " - -# Script updateCache. -MSG_SCRIPTS_UPDATECACHE_DOUPDATE="comprovar si es necessari actualitzar el fitxer imatge" -MSG_SCRIPTS_UPDATECACHE_CHECKSIZECACHE="Comprobar que el tamaño de la cache es mayor que el fichero a descargar." -# Script updateCache: para las imágenes sincronizadas tipo dir. -MSG_SCRIPTS_UPDATECACHE_CHECKSIZEDIR="Calculamos el tamaño de la imagen." -MSG_SCRIPTS_UPDATECACHE_CHECKSIZEIMG="Comprobamos si hay que la imagen del repositorio es mayor que la de la cache." -MSG_SCRIPTS_UPDATECACHE_IFNOTCACHEDO="Comprobar el espacio libre de la cache y actuar según engine.cfg" - -MSG_SCRIPTS_UPDATECACHE_CHECKMCASTSESSION="Comprobando sesion multicast: ServidorMcast:PuertoDatos" - -# interface sustituye temporalmente al scritp restore -MSG_SCRIPTS_CHECK_ENGINE="Analizar proceso a realizar según engine.cfg" -MSG_SCRIPTS_MULTICAST_PRECHECK_PORT="Determinar puerto principal y auxiliar multicast." -MSG_SCRIPTS_MULTICAST_CHECK_PORT="Comprobar puertos de sesion y datos" -MSG_SCRIPTS_MULTICAST_REQUEST_PORT="Solicitar la apertura: " -MSG_SCRIPTS_OS_CONFIGURE="Iniciar la configuracion del sistema restaurado" - -# TIME MESSAGES -MSG_SCRIPTS_TIME_TOTAL="tiempo total del proceso" -MSG_SCRIPTS_TIME_PARTIAL="tiempo parcial del subproceso" - -# HTTPLOG -MSG_HTTPLOG_NOUSE="No apague este ordenador por favor" - -# Mensajes sincronizadas -MSG_SYNC_RESIZE="Redimensiona la imagen al tamaño necesario" -MSG_SYNC_RESTORE="Trae el listado ficheros y baja la imagen" -MSG_SYNC_DELETE="Diferencial: Borra archivos antiguos" -MSG_SYNC_SLEEP="Espera que se monte/reduzca la imagen" -# Mensajes sincronizadas complementarios a errores -MSG_SYNC_DIFFERENTFS="El sistema de ficheros de destino no coincide con el de la imagen" -MSG_SYNC_EXTENSION="Las extensiones de la imagenes deben ser img o diff" -MSG_SYNC_NOCHECK="La imagen esta montada por otro proceso, no podemos comprobarla" - -MSG_RESTORE="Restaura la imagen en" - diff --git a/client/lib/engine/bin/lang_en_GB.py b/client/lib/engine/bin/lang_en_GB.py deleted file mode 100755 index fbc9eee..0000000 --- a/client/lib/engine/bin/lang_en_GB.py +++ /dev/null @@ -1,387 +0,0 @@ -#!/usr/bin/python3 - -# English language file. -#@version 1.1.0 -#@author Jose Miguel Hernandez - Universidad de Salamanca -#@date 2018-03-01 - -# Error messages. -MSG_ERR_GENERIC="Undefined unknown error" -MSG_ERR_FORMAT="Wrong execution format" -MSG_ERR_OUTOFLIMIT="Out of range or invalid value" -MSG_ERR_NOTFOUND="File or device not found" -MSG_ERR_PARTITION="Unknown or wrong partition" -MSG_ERR_LOCKED="Resource locked by exclusive use operation" -MSG_ERR_CACHE="Local cache error" -MSG_ERR_NOGPT="Current disk does not include GPT partition" -MSG_ERR_REPO="Failed when mounting images repository" -MSG_ERR_NOMSDOS="Current disk does not include MSDOS partition" -MSG_ERR_FILESYS="Unknown or unmountable file system" -MSG_ERR_NOTOS="Cannot detect or boot OS" -MSG_ERR_IMAGE="Cannot create or restore a system image" -MSG_ERR_IMAGEFILE="Image file corrupt or of other partclone version" -MSG_ERR_NOTEXEC="Non executable program or function" -MSG_ERR_NOTWRITE="Write access denied" -MSG_ERR_NOTCACHE="No client cache partition" -MSG_ERR_NOTUEFI="UEFI isn't active" -MSG_ERR_NOTBIOS="BIOS legacy isn't active" -MSG_ERR_CACHESIZE="Not enough space in local or remote cache" -MSG_ERR_REDUCEFS="Error when reducing file system" -MSG_ERR_EXTENDFS="Error when expanding file system" -MSG_ERR_IMGSIZEPARTITION="Backup error: Partition smaller than image" -MSG_ERR_UPDATECACHE="Error when running `updateCache´ command" -MSG_ERR_UCASTSYNTAXT="Error when generating Unicast transfer syntax" -MSG_ERR_UCASTSENDPARTITION="Error when sending a Unicast partition" -MSG_ERR_UCASTSENDFILE="Error when sending a Unicast file" -MSG_ERR_UCASTRECEIVERPARTITION="Error when receiving an Unicast partition" -MSG_ERR_UCASTRECEIVERFILE="Error when receiving an Unicast file" -MSG_ERR_MCASTSYNTAXT="Error when generating Multicast transfer syntax" -MSG_ERR_MCASTSENDFILE="Error when sending Multicast file" -MSG_ERR_MCASTRECEIVERFILE="Error when receiving Multicast file" -MSG_ERR_MCASTSENDPARTITION="Error when sending Multicast partition" -MSG_ERR_MCASTRECEIVERPARTITION="Error when receiving Multicast partition " -MSG_ERR_PROTOCOLJOINMASTER="Error when connecting Unicast/Multicast session to Master" -MSG_ERR_DONTFORMAT="Formatting Error" -MSG_ERR_DONTMOUNT_IMAGE="Error when mounting/reducing image" -MSG_ERR_DONTUNMOUNT_IMAGE="Error when unmounting image" -MSG_ERR_DONTSYNC_IMAGE="Unsynchronizable image" -MSG_ERR_NOTDIFFERENT="Basic image identical to partition" -MSG_ERR_SYNCHRONIZING="Synchronizing error, it may affect image creation/restoration process" - -# Warning messages. -MSG_DONTUSE="DO NOT USE" -MSG_DONTMOUNT="Unmounted file system" -MSG_DONTUNMOUNT="Cannot unmount file system or it isn't mounted" -MSG_MOUNT="File system already mounted" -MSG_MOUNTREADONLY="Read-only file system mounted" -MSG_OBSOLETE="OBSOLETE" - -# Auxiliary help messages. -MSG_64BIT="64-bit" -MSG_DISK="Disk" -MSG_ERROR="Error" -MSG_EXAMPLE="Example" -MSG_FORMAT="Format" -MSG_FUNCTION="Function" -MSG_HARDWAREINVENTORY="Hardware inventory" -MSG_IMAGE="Image" -MSG_INSTALLED="Installed" -MSG_NOCACHE="No local cache" -MSG_NOEXTENDED="No extended partition" -MSG_PARTITION="Partition" -MSG_PROTOCOL="Protocol" -MSG_RESERVEDVALUE="Reserved value" -MSG_SEE="See" -MSG_UNKNOWN="Unknown" -MSG_WARNING="Warning" - -# Boot process messages. -MSG_DETECTLVMRAID="Detecting LVM and RAID meta-devices." -MSG_ERRBOOTMODE=f"{MSG_ERROR}: Unknown boot mode." -MSG_LAUNCHCLIENT="Launching client browser." -MSG_LOADAPI="Loading cloning-engine functions." -MSG_LOADMODULES="Loading kernel modules." -MSG_MAKELINKS="Creating symbolic links." -MSG_MOUNTREPO="Mounting repository using %s by %s mode." -MSG_OFFLINEMODE="Off-line boot mode." -MSG_OTHERSERVICES="Starting client complementary services." -MSG_POWEROFFCONF="Defining power-saving parameters." - -# Default menu messages. -MSG_BOOT="Boot" -MSG_DUPLEX="Duplex" -MSG_HOSTNAME="Hostname" -MSG_IPADDR="IP Address" -MSG_MACADDR="MAC Address" -MSG_MENUTITLE="Options menu" -MSG_POWEROFF="Shutdown computer" -MSG_SPEED="Speed" - -# API functions messages. -MSG_HELP_ogAclFilter="Draws ACL files from differential image." -MSG_HELP_ogAddCmd="Adds commands to file created by ogInstalMiniSetup." -MSG_HELP_ogAddRegistryKey="Adds new Windows registry key." -MSG_HELP_ogAddRegistryValue="Adds new Windows registry value." -MSG_HELP_ogAddToLaunchDaemon="" -MSG_HELP_ogBoot="Boots installed OS." -MSG_HELP_ogBootLoaderDeleteEntry=MSG_DONTUSE -MSG_HELP_ogBootLoaderHidePartitions=MSG_DONTUSE -MSG_HELP_ogBootMbrGeneric="" -MSG_HELP_ogBootMbrXP="" -MSG_HELP_ogBurgDefaultEntry="Sets default Burg entry." -MSG_HELP_ogBurgDeleteEntry="Deletes partition start-entries from MBR BURG." -MSG_HELP_ogBurgHidePartitions="Sets MBR Burg to hide non starting windows partitions. Allows you to select a partition that will not be hidden (e.g. for data)." -MSG_HELP_ogBurgInstallMbr="Installs BURG boot-loader on 1st HD MBR." -MSG_HELP_ogBurgOgliveDefaultEntry="Sets ogLive input as default Burg input." -MSG_HELP_ogCalculateChecksum="Calculates file checksum." -MSG_HELP_ogCalculateFullChecksum="Calculates file full checksum" -MSG_HELP_ogChangeRepo="Changes repository for remote resource: images." -MSG_HELP_ogCheckFs="Checks file system consistence." -MSG_HELP_ogCheckIpAddress="" -MSG_HELP_ogCheckProgram="" -MSG_HELP_ogCheckStringInGroup="" -MSG_HELP_ogCheckStringInReg="" -MSG_HELP_ogCheckSyncImage="Displays image contents to check it." -MSG_HELP_ogCleanLinuxDevices="" -MSG_HELP_ogCleanOs="Deletes OS unnecessary files." -MSG_HELP_ogCompareChecksumFiles="Compares if the checksums match." -MSG_HELP_ogConfigureFstab="" -MSG_HELP_ogConfigureOgagent="Sets OS new agent: OGAgent." -MSG_HELP_ogCopyFile="Copies file to another storage unit ." -MSG_HELP_ogCreateBootLoaderImage="" -MSG_HELP_ogCreateCache="Saves space for cache partition at the end of disk." -MSG_HELP_ogCreateDiskImage="Creates exact image from local disk." -MSG_HELP_ogCreateFileImage="Creates/Resizes synchronized image file." -MSG_HELP_ogCreateGptPartitions="" -MSG_HELP_ogCreateImage="Creates exact image from local installed OS." -MSG_HELP_ogCreateImageSyntax="" -MSG_HELP_ogCreateInfoImage="Creates image content information." -MSG_HELP_ogCreateMbrImage="Creates MBR image." -MSG_HELP_ogCreatePartitions="Creates disk partition table." -MSG_HELP_ogCreatePartitionTable="Creates partition table, if necessary." -MSG_HELP_ogCreateTorrent="" -MSG_HELP_ogCopyEfiBootLoader="Copy the boot loader from the EFI partition to system partition." -MSG_HELP_ogDeleteCache="Deletes local cache partition." -MSG_HELP_ogDeleteFile="Deletes file from storage." -MSG_HELP_ogDeletePartitionTable="Deletes disk table partition" -MSG_HELP_ogDeleteRegistryKey="Deletes empty Windows registry key." -MSG_HELP_ogDeleteRegistryValue="Deletes Windows registry value." -MSG_HELP_ogDeleteTree="Deletes directory tree." -MSG_HELP_ogDevToDisk="Returns disk or partition ordinal number for device file path." -MSG_HELP_ogDiskToDev="Returns device file path for disk or partition ordinal number." -MSG_HELP_ogDomainScript="" -MSG_HELP_ogEcho="Displays and log messages." -MSG_HELP_ogExecAndLog="Runs and logs command" -MSG_HELP_ogExtendFs="Expands file system size to partition maximum." -MSG_HELP_ogFindCache="Shows local cache reserved partition." -MSG_HELP_ogFixBootSector="" -MSG_HELP_ogFormatCache="Formats (clears) local cache." -MSG_HELP_ogFormat="Formats file system." -MSG_HELP_ogFormatFs=MSG_HELP_ogFormat -MSG_HELP_ogGetArch="Returns client architecture." -MSG_HELP_ogGetCacheSize="Returns local cache partition size." -MSG_HELP_ogGetCacheSpace="Returns maximum available space that can be reserved for local cache partition." -MSG_HELP_ogGetCaller="Returns program or function which is calling to current one" -MSG_HELP_ogGetDiskSize="Returns disk size." -MSG_HELP_ogGetDiskType="Returns disk type." -MSG_HELP_ogGetFreeSize="" -MSG_HELP_ogGetFsSize="Returns file system size." -MSG_HELP_ogGetFsType="Returns file system type." -MSG_HELP_ogGetGroupDir="Returns default directory path for client group." -MSG_HELP_ogGetGroupName="Returns client group name." -MSG_HELP_ogGetHivePath="Returns full path of file from Windows registry section." -MSG_HELP_ogGetHostname="Returns local hostname." -MSG_HELP_ogGetImageCompressor="Returns image compression tool." -MSG_HELP_ogGetImageInfo="Displays monolithic image information: cloning; compressor; file system; size(KB)." -MSG_HELP_ogGetImageProgram="Returns used program to create image." -MSG_HELP_ogGetImageSize="Returns system image size." -MSG_HELP_ogGetImageType="Returns image file system." -MSG_HELP_ogGetIpAddress="Returns client IP." -MSG_HELP_ogGetLastSector="Returns last available sector from disk or partition." -MSG_HELP_ogGetMacAddress="Returns client Ethernet address." -MSG_HELP_ogGetMountImageDir="Returns mounting directory of image." -MSG_HELP_ogGetMountPoint="Returns directory of local file system mount point." -MSG_HELP_ogGetNetInterface="" -MSG_HELP_ogGetOsType="Returns installed OS type." -MSG_HELP_ogGetOsUuid="Returns OS UUID" -MSG_HELP_ogGetOsVersion="Returns OS version." -MSG_HELP_ogGetParentPath="Returns full path of OpenGnsys system file parent directory." -MSG_HELP_ogGetPartitionActive="Returns disk active partition." -MSG_HELP_ogGetPartitionId="Returns partition type ID." -MSG_HELP_ogGetPartitionSize="Returns partition size." -MSG_HELP_ogGetPartitionsNumber="Returns disk partitions number." -MSG_HELP_ogGetPartitionTableType="Returns disk partition table type." -MSG_HELP_ogGetPartitionType="Returns partition type." -MSG_HELP_ogGetPath="Returns full path of OpenGnsys system file." -MSG_HELP_ogGetRegistryValue="Returns data from Windows registry value." -MSG_HELP_ogGetRepoIp="Returns OpenGnsys Repository IP address ." -MSG_HELP_ogGetSerialNumber="Returns host serial number." -MSG_HELP_ogGetServerIp="Returns main OpenGnsys Server IP address." -MSG_HELP_ogGetSizeParameters="Returns file system data size, required space for image and if it fits in the chosen repository." -MSG_HELP_ogGetWindowsName="Returns saved client name on Windows registry." -MSG_HELP_ogGrubAddOgLive="Adds MBR grub an entry calling Opengnsys client." -MSG_HELP_ogGrubDefaultEntry="Sets GRUB default entry." -MSG_HELP_ogGrubDeleteEntry="Deletes partition start entries on MBR grub." -MSG_HELP_ogGrubHidePartitions="Sets MBR grub to hide non starting Windows partitions. Allows you to select a partition that will not be hidden (e.g. for data)." -MSG_HELP_ogGrubInstallMbr="Installs GRUB boot loader on 1st HD MBR" -MSG_HELP_ogGrubInstallPartition="Installs GRUB boot loader on BootSector" -MSG_HELP_ogGrubOgliveDefaultEntry="Sets ogLive entry as default GRUB entry." -MSG_HELP_ogGrubSecurity="Configures user and password for change the menu entries of grub." -MSG_HELP_ogGrubUefiConf="Generates the grub.cfg file of the EFI partition." -MSG_HELP_ogHelp="Shows functions help messages." -MSG_HELP_ogHidePartition="Hides Windows partition." -MSG_HELP_ogIdToType="Returns partition type identifier." -MSG_HELP_ogInstallFirstBoot="Creates file to run on first Windows boot." -MSG_HELP_ogInstallLaunchDaemon="Installs file to run on MACos boot." -MSG_HELP_ogInstallLinuxClient=MSG_OBSOLETE -MSG_HELP_ogInstallMiniSetup="Installs file to run on Windows boot." -MSG_HELP_ogInstallRunonce="Creates file to run on admin-user Windows boot." -MSG_HELP_ogInstallWindowsClient=MSG_OBSOLETE -MSG_HELP_ogIsFormated="Checks file system if formatted." -MSG_HELP_ogIsImageLocked="Checks image if blocked by exclusive use operation." -MSG_HELP_ogIsLocked="Checks partition or disk if blocked by exclusive use operation." -MSG_HELP_ogIsDiskLocked="Checks disk if blocked by exclusive use operation." -MSG_HELP_ogIsMounted="Checks file system if mounted." -MSG_HELP_ogIsNewerFile="Checks if one file is newer (or has been modified later) than another one." -MSG_HELP_ogIsPartitionLocked=MSG_HELP_ogIsLocked -MSG_HELP_ogIsRepoLocked="" -MSG_HELP_ogIsSyncImage="Checks image if synchronizable." -MSG_HELP_ogIsVirtualMachine="Checks if client is a virtual machine" -MSG_HELP_ogIsWritable="Checks if mounted file system has write permissions." -MSG_HELP_ogLinuxBootParameters="Returns installed Linux boot parameters." -MSG_HELP_ogListHardwareInfo="Lists the client hardware inventory." -MSG_HELP_ogListLogicalPartitions="Lists disk logic partitions." -MSG_HELP_ogListPartitions="Lists disk partitions table." -MSG_HELP_ogListPrimaryPartitions="Lists disk primary partitions" -MSG_HELP_ogListRegistryKeys="Lists sub-keys names included on a Windows registry key." -MSG_HELP_ogListRegistryValues="Lists value names included on a Windows registry key." -MSG_HELP_ogListSoftware="Lists OS installed programs inventory." -MSG_HELP_ogLock="Blocks partition for exclusive use operation." -MSG_HELP_ogLockDisk="Blocks disk for exclusive use operation." -MSG_HELP_ogLockImage="Blocks image for exclusive use operation." -MSG_HELP_ogLockPartition=MSG_HELP_ogLock -MSG_HELP_ogMakeChecksumFile="Stores file checksum." -MSG_HELP_ogMakeDir="Makes OpenGnsys directory." -MSG_HELP_ogMakeGroupDir="Makes group (lab) directory on repository." -MSG_HELP_ogMcastReceiverFile="" -MSG_HELP_ogMcastReceiverPartition="" -MSG_HELP_ogMcastRequest="" -MSG_HELP_ogMcastSendFile="" -MSG_HELP_ogMcastSendPartition="" -MSG_HELP_ogMcastSyntax="" -MSG_HELP_ogMountCache="Mounts cache file system." -MSG_HELP_ogMountCdrom="Mounts default optical drive." -MSG_HELP_ogMountImage="Mounts synchronizable image" -MSG_HELP_ogMount="Mounts file system and returns mount point." -MSG_HELP_ogMountFs=MSG_HELP_ogMount -MSG_HELP_ogNvramActiveEntry="Sets active a bootloader (NVRAM) entry." -MSG_HELP_ogNvramAddEntry="Creates new entry in bootloader (NVRAM)." -MSG_HELP_ogNvramDeleteEntry="Deletes a bootloader (NVRAM) entry." -MSG_HELP_ogNvramGetCurrent="Displays the bootloader (NVRAM) entry that was started by the computer." -MSG_HELP_ogNvramGetNext="Displays the bootloader (NVRAM) entry for the boot next." -MSG_HELP_ogNvramGetOrder="Displays the bootloader (NVRAM) entries order." -MSG_HELP_ogNvramGetTimeout="Displays the bootloader (NVRAM) timeout." -MSG_HELP_ogNvramInactiveEntry="Sets inactive bootloader (NVRAM) entry." -MSG_HELP_ogNvramList="Lists bootloader (NVRAM) entries, by staring actives ones." -MSG_HELP_ogNvramPxeFirstEntry="Set the network as the NVRAM first boot." -MSG_HELP_ogNvramSetNext="Set the bootloader (NVRAM) entry for the boot next." -MSG_HELP_ogNvramSetOrder="Sets the bootloader (NVRAM) entries order." -MSG_HELP_ogNvramSetTimeout="Sets the bootloader (NVRAM) timeout." -MSG_HELP_ogRaiseError="Displays and registers error messages and returns code." -MSG_HELP_ogReduceFs="Reduces file system size to minimum." -MSG_HELP_ogReduceImage="Reduces image size." -MSG_HELP_ogRefindDeleteEntry="Deletes the menu entry of a partition in rEFInd." -MSG_HELP_ogRefindDefaultEntry="Configures default menu entry in rEFInd." -MSG_HELP_ogRefindOgliveDefaultEntry="Configures ogLive menu entry as default menu entry in rEFInd." -MSG_HELP_ogRefindSetTheme="Configures rEFInd's theme." -MSG_HELP_ogRefindSetTimeOut="Defines the time that rEFInd shows the menu." -MSG_HELP_ogRefindSetResolution="Defines the resolucion of rEFInd's theme." -MSG_HELP_ogRefindInstall="Installs and configures rEFInd boot loader in ESP." -MSG_HELP_ogRestoreAclImage="Restores Windows ACL (Inf. must be on /tmp)." -MSG_HELP_ogRestoreBootLoaderImage="" -MSG_HELP_ogRestoreDiskImage="Restores disk image." -MSG_HELP_ogRestoreEfiBootLoader="Copy the boot loader from the system partition to the EFI partition." -MSG_HELP_ogRestoreImage="Restore OS image." -MSG_HELP_ogRestoreInfoImage="Restores system information: ACL and symbolic links" -MSG_HELP_ogRestoreMbrImage="Restores boot sector image (MBR)." -MSG_HELP_ogRestoreUuidPartitions="Restores UUID of partitions and partition table." -MSG_HELP_ogSaveImageInfo="Creates the image information file." -MSG_HELP_ogSetLinuxName="" -MSG_HELP_ogSetPartitionActive="Sets active partition number of disk." -MSG_HELP_ogSetPartitionId="Changes partition ID using mnemonic." -MSG_HELP_ogSetPartitionSize="Sets partition size." -MSG_HELP_ogSetPartitionType="Changes partition type ID." -MSG_HELP_ogSetRegistryValue="Assigns data to a Windows registry values." -MSG_HELP_ogSetWindowsName="Assigns client name to Windows registry." -MSG_HELP_ogSetWinlogonUser="Assigns Windows default user name to Windows input manager." -MSG_HELP_ogSyncCreate="Synchronizes partition data to image" -MSG_HELP_ogSyncRestore="Synchronize image data to partition" -MSG_HELP_ogTorrentStart="" -MSG_HELP_ogTypeToId="Returns the ID of partition type mnemonic." -MSG_HELP_ogUcastReceiverPartition="" -MSG_HELP_ogUcastSendFile="" -MSG_HELP_ogUcastSendPartition="" -MSG_HELP_ogUcastSyntax="" -MSG_HELP_ogUnhidePartition="Unhides Windows partition." -MSG_HELP_ogUninstallLinuxClient="Uninstalls old OpenGnSys agent from Linux OS." -MSG_HELP_ogUninstallWindowsClient="Uninstalls oldOpenGnSys agent from Windows OS." -MSG_HELP_ogUnlock="Unlocks partition after exclusive use operation." -MSG_HELP_ogUnlockDisk="Unlocks disk after exclusive use operation." -MSG_HELP_ogUnlockImage="Unlocks image after exclusive use operation." -MSG_HELP_ogUnlockPartition=MSG_HELP_ogUnlock -MSG_HELP_ogUnmountAll="Unmounts all file systems." -MSG_HELP_ogUnmountCache="Unmounts cache file system." -MSG_HELP_ogUnmountImage="Unmounts image" -MSG_HELP_ogUnmount="Unmounts file system." -MSG_HELP_ogUnmountFs=MSG_HELP_ogUnmount -MSG_HELP_ogUnsetDirtyBit="" -MSG_HELP_ogUpdateCacheIsNecesary="Checks if necessary file update in local cache." -MSG_HELP_ogUpdatePartitionTable="Updates disk partition table info " -MSG_HELP_ogUuidChange="Replaces the filesystem UUID" -MSG_HELP_ogWaitSyncImage="" -MSG_HELP_ogWindowsBootParameters="" -MSG_HELP_ogWindowsRegisterPartition="" - -# Scripts -MSG_HELP_configureOs="Post-configure system boot" -MSG_HELP_createBaseImage="Create partition basic image" -MSG_HELP_createDiffImage="Create partition differential image from basic image" -MSG_HELP_installOfflineMode="Prepare client for off-line mode." -MSG_HELP_partclone2sync="Turn part-clone image into synchronizable image." -MSG_HELP_restoreBaseImage="Restore basic image into partition" -MSG_HELP_restoreDiffImage="Restore differential image into partition" -MSG_HELP_updateCache="Update cache" - -# INTERFACE functions messages. -MSG_INTERFACE_START="[START Interface] Run command: " -MSG_INTERFACE_END="[END Interface] Command finished with this code: " - -# SCRIPTS messages. -MSG_SCRIPTS_START=" START scripts: " -MSG_SCRIPTS_END=" END scripts: " -MSG_SCRIPTS_TASK_END="End of task" - -MSG_SCRIPTS_TASK_SLEEP="Waiting to start" -MSG_SCRIPTS_TASK_START="Starting" -MSG_SCRIPTS_TASK_ERR="Error" - -# createImage script -MSG_SCRIPTS_FILE_RENAME="Rename previous image-file: " -MSG_SCRIPTS_CREATE_SIZE="Check required and available storing space(KB): " - -# updateCache script -MSG_SCRIPTS_UPDATECACHE_DOUPDATE="Check if it is necessary to update image file" -MSG_SCRIPTS_UPDATECACHE_CHECKSIZECACHE="Check if Cache size is bigger than image file size." -# Script updateCache: for dir synchronized images . -MSG_SCRIPTS_UPDATECACHE_CHECKSIZEDIR="Calculate image size." -MSG_SCRIPTS_UPDATECACHE_CHECKSIZEIMG="Check if repository image file size is bigger than Cache size." -MSG_SCRIPTS_UPDATECACHE_IFNOTCACHEDO="Check free Cache and apply engine.cfg" - -MSG_SCRIPTS_UPDATECACHE_CHECKMCASTSESSION="Checking Multicast Session McastServer:DataPort" - -# interface temporarily replaces restore script -MSG_SCRIPTS_CHECK_ENGINE="Analyze process to carry out according to engine.cfg" -MSG_SCRIPTS_MULTICAST_PRECHECK_PORT="Check main and auxiliary Multicast port." -MSG_SCRIPTS_MULTICAST_CHECK_PORT="Check session and data ports" -MSG_SCRIPTS_MULTICAST_REQUEST_PORT="Request Multicast port opening: " -MSG_SCRIPTS_OS_CONFIGURE="Start restored system setting" - -# TIME MESSAGES -MSG_SCRIPTS_TIME_TOTAL="Total process time" -MSG_SCRIPTS_TIME_PARTIAL="Partial sub-process time" - -# HTTPLOG -MSG_HTTPLOG_NOUSE="PLEASE DO NOT TURN OFF THIS COMPUTER" - -# Messages for synchronized images (complementary to errors) -MSG_SYNC_RESIZE="Resize image to necessary size" -MSG_SYNC_RESTORE="Get files list and download image" -MSG_SYNC_DELETE="Differential: Delete old files" -MSG_SYNC_SLEEP="Wait for mounting/reducing image" -# Messages for synchronized images (complementary to errors) -MSG_SYNC_DIFFERENTFS="Destination file system does not match image" -MSG_SYNC_EXTENSION="Image extension must be img or diff" -MSG_SYNC_NOCHECK="Image mounted by another process. Cannot verify it" - -MSG_RESTORE="Restore image on " - diff --git a/client/lib/engine/bin/lang_es_ES.py b/client/lib/engine/bin/lang_es_ES.py deleted file mode 100755 index 1687e99..0000000 --- a/client/lib/engine/bin/lang_es_ES.py +++ /dev/null @@ -1,387 +0,0 @@ -#!/usr/bin/python3 - -# Fichero de idioma: español. -#@version 1.1.1 -#@author - - -# Mensajes de error. -MSG_ERR_GENERIC="Error imprevisto no definido" -MSG_ERR_FORMAT="Formato de ejecución incorrecto" -MSG_ERR_OUTOFLIMIT="Valor fuera de rango o no válido" -MSG_ERR_NOTFOUND="Fichero o dispositivo no encontrado" -MSG_ERR_PARTITION="Partición errónea o desconocida" -MSG_ERR_LOCKED="Recurso bloqueado por operación de uso exclusivo" -MSG_ERR_CACHE="Error en partición de caché local" -MSG_ERR_NOGPT="El disco indicado no contiene una partición GPT" -MSG_ERR_REPO="Error al montar el repositorio de imágenes" -MSG_ERR_NOMSDOS="El disco indicado no contiene una partición MSDOS" -MSG_ERR_FILESYS="Sistema de archivos desconocido o no se puede montar" -MSG_ERR_NOTOS="Sistema operativo no detectado o no se puede iniciar" -MSG_ERR_IMAGE="No se puede crear o restaurar una image de sistema" -MSG_ERR_IMAGEFILE="Archivo de imagen corrupto o de otra versión de partclone" -MSG_ERR_NOTEXEC="Programa o función no ejecutable" -MSG_ERR_NOTWRITE="No hay acceso de escritura" -MSG_ERR_NOTCACHE="No existe partición caché en el cliente" -MSG_ERR_NOTUEFI="La interfaz UEFI no está activa" -MSG_ERR_NOTBIOS="La interfaz BIOS Legacy no está activa" -MSG_ERR_CACHESIZE="El espacio de la caché local o remota no es suficiente" -MSG_ERR_REDUCEFS="Error al reducir el sistema de archivos" -MSG_ERR_EXTENDFS="Error al expandir el sistema de archivos" -MSG_ERR_IMGSIZEPARTITION="Error al restaurar: Partición mas pequeña que la imagen" -MSG_ERR_UPDATECACHE="Error al realizar el comando updateCache" -MSG_ERR_UCASTSYNTAXT="Error en la generación de sintaxis de transferenica Unicast" -MSG_ERR_UCASTSENDPARTITION="Error en envío Unicast de una partición" -MSG_ERR_UCASTSENDFILE="Error en envío Unicast de un fichero" -MSG_ERR_UCASTRECEIVERPARTITION="Error en la recepción Unicast de una partición" -MSG_ERR_UCASTRECEIVERFILE="Error en la recepción Unicast de un fichero" -MSG_ERR_MCASTSYNTAXT="Error en la generación de sintaxis de transferenica Multicast" -MSG_ERR_MCASTSENDFILE="Error en envío Multicast de un fichero" -MSG_ERR_MCASTRECEIVERFILE="Error en la recepción Multicast de un fichero" -MSG_ERR_MCASTSENDPARTITION="Error en envío Multicast de una partición" -MSG_ERR_MCASTRECEIVERPARTITION="Error en la recepción Multicast de un fichero" -MSG_ERR_PROTOCOLJOINMASTER="Error en la conexión de una sesión Unicast|Multicast con el Master" -MSG_ERR_DONTFORMAT="Error al formatear" -MSG_ERR_DONTMOUNT_IMAGE="Error al montar/reducir la imagen" -MSG_ERR_DONTUNMOUNT_IMAGE="Error al desmontar la imagen" -MSG_ERR_DONTSYNC_IMAGE="Imagen no sincronizable" -MSG_ERR_NOTDIFFERENT="No se detectan diferencias entre la imagen básica y la partición" -MSG_ERR_SYNCHRONIZING="Error al sincronizar, puede afectar la creacion|restauracion de la imagen" - -# Mensajes de avisos. -MSG_DONTMOUNT="Sistema de archivos no montado" -MSG_DONTUSE="NO USAR" -MSG_DONTUNMOUNT="El sistema de archivos no se puede desmontar o no está montado" -MSG_MOUNT="Sistema de archivos montado" -MSG_MOUNTREADONLY="Sistema de archivos montado solo de lectura" -MSG_OBSOLETE="EN DESUSO" - -# Mensajes complementarios para las ayudas. -MSG_64BIT="64 bits" -MSG_DISK="disco" -MSG_ERROR="Error" -MSG_EXAMPLE="Ejemplo" -MSG_FORMAT="Formato" -MSG_FUNCTION="Función" -MSG_HARDWAREINVENTORY="Inventario de hardware de la máquina" -MSG_IMAGE="imagen" -MSG_INSTALLED="instalado" -MSG_NOCACHE="sin caché local" -MSG_NOEXTENDED="sin partición extendida" -MSG_PARTITION="partición" -MSG_PROTOCOL="protocolo" -MSG_RESERVEDVALUE="Valor reservado" -MSG_SEE="Ver" -MSG_UNKNOWN="Desconocido" -MSG_WARNING="Aviso" - -# Mensajes del proceso de arranque. -MSG_DETECTLVMRAID="Detectar metadispositivos LVM y RAID." -MSG_ERRBOOTMODE=f"{MSG_ERROR}: Modo de arranque desconocido." -MSG_LAUNCHCLIENT="Ejecutar cliente." -MSG_LOADAPI="Cargar funciones del motor de clonación." -MSG_LOADMODULES="Cargar módulos del kernel." -MSG_MAKELINKS="Crear enlaces simbólicos." -MSG_MOUNTREPO="Montar repositorio por %s en modo %s." -MSG_OFFLINEMODE="Modo de arranque sin conexión." -MSG_OTHERSERVICES="Iniciar servicios complementarios del cliente." -MSG_POWEROFFCONF="Definir parámetros de ahorro de energía." - -# Mensajes del menú por defecto. -MSG_BOOT="Iniciar" -MSG_DUPLEX="Dúplex" -MSG_HOSTNAME="Equipo" -MSG_IPADDR="Dirección IP" -MSG_MACADDR="Dirección MAC" -MSG_MENUTITLE="Menú de opciones" -MSG_POWEROFF="Apagar el equipo" -MSG_SPEED="Velocidad" - -# Mensajes de descripción breve de las funciones de la API. -MSG_HELP_ogAclFilter="Extrae las acl de los ficheros de la diferencial" -MSG_HELP_ogAddCmd="Añade comandos al fichero creado por la función ogInstalMiniSetup." -MSG_HELP_ogAddRegistryKey="Añade una nueva clave al registro de Windows." -MSG_HELP_ogAddRegistryValue="Añade un nuevo valor al registro de Windows." -MSG_HELP_ogAddToLaunchDaemon="" -MSG_HELP_ogBoot="Arranca un sistema operativo instalado." -MSG_HELP_ogBootLoaderDeleteEntry=MSG_DONTUSE -MSG_HELP_ogBootLoaderHidePartitions=MSG_DONTUSE -MSG_HELP_ogBootMbrGeneric="" -MSG_HELP_ogBootMbrXP="" -MSG_HELP_ogBurgDefaultEntry="Configura la entrada por defecto de Burg." -MSG_HELP_ogBurgDeleteEntry="Borra en el Burg del MBR las entradas para el inicio en una particion." -MSG_HELP_ogBurgHidePartitions="Configura el Burg del MBR para que oculte las particiones de windows que no se esten iniciando. Permite definir una partición que no se ocultará (ej: para datos)." -MSG_HELP_ogBurgInstallMbr="Instala el gestor de arranque BURG en el MBR del primer disco duro" -MSG_HELP_ogBurgOgliveDefaultEntry="Configura la entrada de ogLive como la entrada por defecto de Burg." -MSG_HELP_ogCalculateChecksum="Calcula la suma de comprobación (checksum) de un fichero." -MSG_HELP_ogCalculateFullChecksum="Calcula la suma de comprobación completa de un fichero." -MSG_HELP_ogChangeRepo="Cambia el repositorio para el recurso remoto images." -MSG_HELP_ogCheckFs="Comprueba la consistencia de un sistema de archivos." -MSG_HELP_ogCheckIpAddress="" -MSG_HELP_ogCheckProgram="" -MSG_HELP_ogCheckStringInGroup="" -MSG_HELP_ogCheckStringInReg="" -MSG_HELP_ogCheckSyncImage="Muestra el contenido de la imagen para comprobarla." -MSG_HELP_ogCleanLinuxDevices="" -MSG_HELP_ogCleanOs="Elimina los archivos que no son necesarios en el sistema operativo." -MSG_HELP_ogCompareChecksumFiles="Compara si coinciden las sumas de comprobación almacenadas de 2 ficheros." -MSG_HELP_ogConfigureFstab="" -MSG_HELP_ogConfigureOgagent="Configura el nuevo agente OGAgent para sistemas operativos." -MSG_HELP_ogCopyFile="Copia un fichero a otro almacenamiento." -MSG_HELP_ogCreateBootLoaderImage="" -MSG_HELP_ogCreateCache="Reserva espacio para la partición de caché al final del disco." -MSG_HELP_ogCreateDiskImage="Genera una imagen exacta de un disco completo." -MSG_HELP_ogCreateFileImage="Crea/redimensiona el archivo de la imagen sincronizada" -MSG_HELP_ogCreateGptPartitions="" -MSG_HELP_ogCreateImage="Genera una imagen exacta de un sistema operativo instalado localmente." -MSG_HELP_ogCreateImageSyntax="" -MSG_HELP_ogCreateInfoImage="Crea información del contenido de la imagen" -MSG_HELP_ogCreateMbrImage="Genera una imagen del sector de arranque (MBR)." -MSG_HELP_ogCreatePartitions="Define la estructura de particiones de un disco." -MSG_HELP_ogCreatePartitionTable="Genera una tabla de particiones en caso de que no sea valida." -MSG_HELP_ogCreateTorrent="" -MSG_HELP_ogCopyEfiBootLoader="Copia el cargador de arranque desde la partición EFI a la de sistema." -MSG_HELP_ogDeleteCache="Elimina la partición de caché local." -MSG_HELP_ogDeleteFile="Borra un fichero de un espacio de almacenamiento." -MSG_HELP_ogDeletePartitionTable="Elimina la tabla de particiones del disco" -MSG_HELP_ogDeleteRegistryKey="Borra una clave vacía del registro de Windows." -MSG_HELP_ogDeleteRegistryValue="Borra un valor del registro de Windows." -MSG_HELP_ogDeleteTree="Borra un árbol de directorios de un espacio de almacenamiento." -MSG_HELP_ogDevToDisk="Devuelve el nº de orden de disco o de partición correspondiente al camino del fichero de dispositivo." -MSG_HELP_ogDiskToDev="Devuelve el camino del fichero de dispositivo correspondiente al nº de orden de disco o de partición." -MSG_HELP_ogDomainScript="" -MSG_HELP_ogEcho="Muestra un mensaje en pantalla y permite registrarlo en fichero de log" -MSG_HELP_ogExecAndLog="Ejecuta un comando y registra su salida en fichero de log" -MSG_HELP_ogExtendFs="Extiende el tamaño de un sistema de archivo al máximo de su partición." -MSG_HELP_ogFindCache="Indica la partición reservada para caché local." -MSG_HELP_ogFixBootSector="" -MSG_HELP_ogFormatCache="Formatea (inicia) el sistema de caché local." -MSG_HELP_ogFormat="Formatea o reformatea un sistema de archivos." -MSG_HELP_ogFormatFs=MSG_HELP_ogFormat -MSG_HELP_ogGetArch="Devuelve el tipo de arquitectura del cliente." -MSG_HELP_ogGetCacheSize="Devuelve el tamaño de la partición de caché local." -MSG_HELP_ogGetCacheSpace="Devuelve el espacio máximo disponible que puede ser reservado para la partición de caché local." -MSG_HELP_ogGetCaller="Devuelve el programa o función que llama al actual" -MSG_HELP_ogGetDiskSize="Devuelve el tamaño del disco." -MSG_HELP_ogGetDiskType="Devuelve el mnemónico de tipo de disco." -MSG_HELP_ogGetFreeSize="" -MSG_HELP_ogGetFsSize="Devuelve el tamaño de un sistema de archivos." -MSG_HELP_ogGetFsType="Devuelve el mnemónico de tipo de sistema de archivos." -MSG_HELP_ogGetGroupDir="Devuelve el camino del directorio por defecto para el grupo del cliente." -MSG_HELP_ogGetGroupName="Devuelve el nombre del grupo al que pertenece el cliente." -MSG_HELP_ogGetHivePath="Devuelve el camino completo del fichero de una sección del registro de Windows." -MSG_HELP_ogGetHostname="Devuelve el nombre de la máquina local." -MSG_HELP_ogGetImageCompressor="Devuelve la herramienta de compresión de la imagen." -MSG_HELP_ogGetImageInfo="Muestra información sobre la imagen monolitica: clonacion:compresor:sistemaarchivos:tamañoKB." -MSG_HELP_ogGetImageProgram="Devuelve el programa usado para crear la imagen." -MSG_HELP_ogGetImageSize="Devuelve el tamaño de una imagen de sistema." -MSG_HELP_ogGetImageType="Devuelve el sistema de ficheros de la imagen." -MSG_HELP_ogGetIpAddress="Devuelve la dirección IP del cliente." -MSG_HELP_ogGetLastSector="Devuelve el último sector usable del disco o de una partición." -MSG_HELP_ogGetMacAddress="Devuelve la dirección Ethernet del cliente." -MSG_HELP_ogGetMountImageDir="Devuelve el directorio de montaje de una imagen." -MSG_HELP_ogGetMountPoint="Devuelve el directorio donde está montado un sistema de archivos local." -MSG_HELP_ogGetNetInterface="" -MSG_HELP_ogGetOsType="Devuelve el tipo de un sistema operativo instalado." -MSG_HELP_ogGetOsUuid="Devuelve el UUID de un sistema operativo" -MSG_HELP_ogGetOsVersion="Devuelve el tipo y la versión de un sistema operativo instalado." -MSG_HELP_ogGetParentPath="Devuelve el camino completo del directorio padre de un fichero de sistema OpenGnsys." -MSG_HELP_ogGetPartitionActive="Indica cual es la partición marcada como activa en un disco." -MSG_HELP_ogGetPartitionId="Devuelve el identificador de tipo de una partición." -MSG_HELP_ogGetPartitionSize="Devuelve el tamaño de una partición." -MSG_HELP_ogGetPartitionsNumber="Devuelve el número de particiones de un disco" -MSG_HELP_ogGetPartitionTableType="Devuelve el tipo de tabla de particiones del disco" -MSG_HELP_ogGetPartitionType="Devuelve el mnemónico de tipo de una partición." -MSG_HELP_ogGetPath="Devuelve el camino completo de un fichero de sistema OpenGnsys." -MSG_HELP_ogGetRegistryValue="Devuelve el dato de un valor del registro de Windows." -MSG_HELP_ogGetRepoIp="Devuelve la dirección IP del repositorio de datos." -MSG_HELP_ogGetSerialNumber="Devuelve el número de serie del equipo" -MSG_HELP_ogGetServerIp="Devuelve la dirección IP del servidor principal." -MSG_HELP_ogGetSizeParameters="Devuelve el tamaño de los datos de un sistema de ficheros, el espacio necesario para la imagen y si cabe en el repositorio elegido." -MSG_HELP_ogGetWindowsName="Devuelve el nombre del cliente guardado en el registro de Windows." -MSG_HELP_ogGrubAddOgLive="Incluye en el grub del MBR una entrada llamando al cliente de opengnsys." -MSG_HELP_ogGrubDefaultEntry="Configura la entrada por defecto de GRUB." -MSG_HELP_ogGrubDeleteEntry="Borra en el grub del MBR las entradas para el inicio en una particion." -MSG_HELP_ogGrubHidePartitions="Configura el grub del MBR para que oculte las particiones de windows que no se esten iniciando. Permite definir una partición que no se ocultará (ej: para datos)." -MSG_HELP_ogGrubInstallMbr="Instala el gestor de arranque GRUB en el MBR del primer disco duro" -MSG_HELP_ogGrubInstallPartition="Instala el gestor de arranque GRUB en el BootSector" -MSG_HELP_ogGrubOgliveDefaultEntry="Configura la entrada de ogLive como la entrada por defecto de GRUB." -MSG_HELP_ogGrubSecurity="Configura usuario y clave para modificar las entradas del menu del Grub." -MSG_HELP_ogGrubUefiConf="Genera el fichero grub.cfg de la partición EFI." -MSG_HELP_ogHelp="Muestra mensajes de ayudas para las funciones." -MSG_HELP_ogHidePartition="Oculta una partición de Windows." -MSG_HELP_ogIdToType="Devuelve el mnemónico asociado al identificador de tipo de partición." -MSG_HELP_ogInstallFirstBoot="Crea un archivo que se ejecutará en el primer arranque de Windows." -MSG_HELP_ogInstallLaunchDaemon="Instala un archivo que se ejecutará en el arranque de macOS." -MSG_HELP_ogInstallLinuxClient=MSG_OBSOLETE -MSG_HELP_ogInstallMiniSetup="Instala un archivo que se ejecutará en el arranque de Windows." -MSG_HELP_ogInstallRunonce="Crea archivo que se ejecutará en el inicio de un usuario administrador de Windows." -MSG_HELP_ogInstallWindowsClient=MSG_OBSOLETE -MSG_HELP_ogIsFormated="Comprueba si un sistema de archivos está formateado." -MSG_HELP_ogIsImageLocked="Comprueba si una imagen está bloqueada por una operación de uso exclusivo." -MSG_HELP_ogIsLocked="Comprueba si una partición o su disco están bloqueados por una operación de uso exclusivo." -MSG_HELP_ogIsDiskLocked="Comprueba si un disco está bloqueado por una operación de uso exclusivo." -MSG_HELP_ogIsMounted="Comprueba si un sistema de archivos está montado." -MSG_HELP_ogIsNewerFile="Comprueba si un fichero es más nuevo (se ha modificado después) que otro." -MSG_HELP_ogIsPartitionLocked=MSG_HELP_ogIsLocked -MSG_HELP_ogIsRepoLocked="" -MSG_HELP_ogIsSyncImage="Comprueba si la imagen es sincronizable." -MSG_HELP_ogIsVirtualMachine="Comprueba si el cliente es una máquina virtual" -MSG_HELP_ogIsWritable="Comprueba si un sistema de archivos está montado con permiso de escritura." -MSG_HELP_ogLinuxBootParameters="Devuelve los parámetros de arranque de un sistema operativo Linux instalado." -MSG_HELP_ogListHardwareInfo="Lista el inventario de dispositivos del cliente." -MSG_HELP_ogListLogicalPartitions="Lista las particiones lógicas de un disco" -MSG_HELP_ogListPartitions="Lista la estructura de particiones de un disco." -MSG_HELP_ogListPrimaryPartitions="Lista las particiones primarias de un disco" -MSG_HELP_ogListRegistryKeys="Lista los nombres de las subclaves incluidas en una clave del registro de Windows." -MSG_HELP_ogListRegistryValues="Lista los nombres de los valores incluidos en una clave del registro de Windows." -MSG_HELP_ogListSoftware="Lista el inventario de programas instalados en un sistema operativo." -MSG_HELP_ogLock="Bloquea una partición para operación de uso exclusivo." -MSG_HELP_ogLockDisk="Bloquea un disco para operación de uso exclusivo." -MSG_HELP_ogLockImage="Bloquea una imagen para operación de uso exclusivo." -MSG_HELP_ogLockPartition=MSG_HELP_ogLock -MSG_HELP_ogMakeChecksumFile="Almacena la suma de comprobación de un fichero." -MSG_HELP_ogMakeDir="Crea un directorio para OpenGnsys." -MSG_HELP_ogMakeGroupDir="Crea el directorio de grupo (aula) en un repositorio." -MSG_HELP_ogMcastReceiverFile="" -MSG_HELP_ogMcastReceiverPartition="" -MSG_HELP_ogMcastRequest="" -MSG_HELP_ogMcastSendFile="" -MSG_HELP_ogMcastSendPartition="" -MSG_HELP_ogMcastSyntax="" -MSG_HELP_ogMountCache="Monta el sistema de archivos dedicado a caché local." -MSG_HELP_ogMountCdrom="Monta dispositivo óptico por defecto." -MSG_HELP_ogMountImage="Monta una imagen sincronizable" -MSG_HELP_ogMount="Monta un sistema de archivos y devuelve el punto de montaje." -MSG_HELP_ogMountFs=MSG_HELP_ogMount -MSG_HELP_ogNvramActiveEntry="Configura a activa entrada del gestor de arranque (NVRAM)." -MSG_HELP_ogNvramAddEntry="Crea nueva entrada del gestor de arranque (NVRAM)." -MSG_HELP_ogNvramDeleteEntry="Borra entrada del gestor de arranque (NVRAM)." -MSG_HELP_ogNvramGetCurrent="Muestra la entrada del gestor de arranque (NVRAM) que ha iniciado el equipo." -MSG_HELP_ogNvramGetNext="Muestra la entrada del gestor de arranque (NVRAM) que se utilizará en el próximo arranque." -MSG_HELP_ogNvramGetOrder="Muestra el orden de las entradas del gestor de arranque (NVRAM)." -MSG_HELP_ogNvramGetTimeout="Muestra el tiempo de espera del gestor de arranque (NVRAM)." -MSG_HELP_ogNvramInactiveEntry="Configura a inactiva entrada del gestor de arranque (NVRAM)." -MSG_HELP_ogNvramList="Lista las entradas del gestor de arranque (NVRAN) marcando con un asterisco las activas" -MSG_HELP_ogNvramPxeFirstEntry="Configura la tarjeta de red como primer arranque en la NVRAM." -MSG_HELP_ogNvramSetNext="Configura el próximo arranque con la entrada del gestor de arranque (NVRAM)." -MSG_HELP_ogNvramSetOrder="Configura el orden de las entradas del gestor de arranque (NVRAM)." -MSG_HELP_ogNvramSetTimeout="Configura el tiempo de espera del gestor de arranque (NVRAM)." -MSG_HELP_ogRaiseError="Muestra y registra mensajes de error y devuelve el código correspondiente." -MSG_HELP_ogReduceFs="Reduce el tamaño del sistema de archivos al mínimo ocupado por sus datos." -MSG_HELP_ogReduceImage="Reduce el tamaño de la imagen" -MSG_HELP_ogRefindDeleteEntry="Borra en rEFInd las entradas para el inicio en una particion." -MSG_HELP_ogRefindDefaultEntry="Configura la entrada por defecto de rEFInd." -MSG_HELP_ogRefindOgliveDefaultEntry="Configura la entrada de ogLive como la entrada por defecto de rEFInd." -MSG_HELP_ogRefindSetTheme="Asigna un tema al rEFInd." -MSG_HELP_ogRefindSetTimeOut="Define el tiempo (segundos) que se muestran las opciones de inicio de rEFInd." -MSG_HELP_ogRefindSetResolution="Define la resolución que usuará el thema del gestor de arranque rEFInd." -MSG_HELP_ogRefindInstall="Instala y configura el gestor rEFInd en la particion EFI" -MSG_HELP_ogRestoreAclImage="Restaura las ACL de Windows (La informacion debe estar copiada en /tmp)." -MSG_HELP_ogRestoreBootLoaderImage="" -MSG_HELP_ogRestoreDiskImage="Restaura una imagen de un disco completo." -MSG_HELP_ogRestoreEfiBootLoader="Copia el cargador de arranque de la partición de sistema a la partición EFI." -MSG_HELP_ogRestoreImage="Restaura una imagen de sistema operativo." -MSG_HELP_ogRestoreInfoImage="Restablece información del sistema: ACL y enlaces simbolicos" -MSG_HELP_ogRestoreMbrImage="Restaura una imagen del sector de arranque (MBR)." -MSG_HELP_ogRestoreUuidPartitions="Restaura los uuid de las particiones y la tabla de particiones." -MSG_HELP_ogSaveImageInfo="Crea un fichero con la información de la imagen." -MSG_HELP_ogSetLinuxName="" -MSG_HELP_ogSetPartitionActive="Establece el número de partición activa de un disco." -MSG_HELP_ogSetPartitionId="Modifica el tipo de una partición física usando el mnemónico del tipo." -MSG_HELP_ogSetPartitionSize="Establece el tamaño de una partición." -MSG_HELP_ogSetPartitionType="Modifica el identificador de tipo de una partición física." -MSG_HELP_ogSetRegistryValue="Asigna un dato a un valor del registro de Windows." -MSG_HELP_ogSetWindowsName="Asigna el nombre del cliente en el registro de Windows." -MSG_HELP_ogSetWinlogonUser="Asigna el nombre de usuario por defecto para el gestor de entrada de Windows." -MSG_HELP_ogSyncCreate="Sincroniza los datos de la partición a la imagen" -MSG_HELP_ogSyncRestore="Sincroniza los datos de la imagen a la partición" -MSG_HELP_ogTorrentStart="" -MSG_HELP_ogTypeToId="Devuelve el identificador asociado al mnemónico de tipo de partición." -MSG_HELP_ogUcastReceiverPartition="" -MSG_HELP_ogUcastSendFile="" -MSG_HELP_ogUcastSendPartition="" -MSG_HELP_ogUcastSyntax="" -MSG_HELP_ogUnhidePartition="Hace visible una partición de Windows." -MSG_HELP_ogUninstallLinuxClient="Desinstala el antiguo cliente OpenGnSys en un sistema operativo Linux." -MSG_HELP_ogUninstallWindowsClient="Desinstala el antiguo cliente OpenGnSys en un sistema operativo Windows." -MSG_HELP_ogUnlock="Desbloquea una partición tras finalizar una operación de uso exclusivo." -MSG_HELP_ogUnlockDisk="Desbloquea un disco tras finalizar una operación de uso exclusivo." -MSG_HELP_ogUnlockImage="Desbloquea una imagen tras finalizar una operación de uso exclusivo." -MSG_HELP_ogUnlockPartition=MSG_HELP_ogUnlock -MSG_HELP_ogUnmountAll="Desmonta todos los sistemas de archivos." -MSG_HELP_ogUnmountCache="Desmonta el sistema de archivos de caché local." -MSG_HELP_ogUnmount="Desmonta un sistema de archivos." -MSG_HELP_ogUnmountImage="Desmonta la imagen." -MSG_HELP_ogUnmountFs=MSG_HELP_ogUnmount -MSG_HELP_ogUnsetDirtyBit="" -MSG_HELP_ogUpdateCacheIsNecesary="Comprueba si es necesario actualizar una archivo en la cache local." -MSG_HELP_ogUpdatePartitionTable="Actualiza información de la tabla de particiones del disco." -MSG_HELP_ogUuidChange="Reemplaza el UUID de un sistema de ficheros." -MSG_HELP_ogWaitSyncImage="" -MSG_HELP_ogWindowsBootParameters="" -MSG_HELP_ogWindowsRegisterPartition="" - -# Scripts -MSG_HELP_configureOs="Post-configura de arranque del sistema" -MSG_HELP_createBaseImage="Genera imagen básica de la partición" -MSG_HELP_createDiffImage="Genera imagen diferencial de la partición respecto a la imagen básica" -MSG_HELP_installOfflineMode="Prepara el equipo cliente para el modo offline." -MSG_HELP_partclone2sync="Convierte imagen de partclone en imagen sincronizable." -MSG_HELP_restoreBaseImage="Restaura una imagen básica en una partición" -MSG_HELP_restoreDiffImage="Restaura una imagen diferencial en una partición" -MSG_HELP_updateCache="Realiza la actualización de la caché" - -# Mensajes de descripción breve de la interfaz. -MSG_INTERFACE_START="[START Interface] Ejecutar comando: " -MSG_INTERFACE_END="[END Interface] Comando terminado con este código: " - -# Mensajes de scripts. -MSG_SCRIPTS_START=" INICIO scripts: " -MSG_SCRIPTS_END=" FIN scripts: " -MSG_SCRIPTS_TASK_END="Fin de la tarea" - -MSG_SCRIPTS_TASK_SLEEP="Esperando para iniciar" -MSG_SCRIPTS_TASK_START="Iniciando" -MSG_SCRIPTS_TASK_ERR="Error" - -# Script createImage. -MSG_SCRIPTS_FILE_RENAME=" Renombrar fichero-imagen previo: " -MSG_SCRIPTS_CREATE_SIZE=" Calcular espacio (KB) requerido para almacenarlo y el disponible: " - -# Script updateCache. -MSG_SCRIPTS_UPDATECACHE_DOUPDATE="Comprobar si es necesario actualizar el fichero imagen " -MSG_SCRIPTS_UPDATECACHE_CHECKSIZECACHE="Comprobar que el tamaño de la caché es mayor que el fichero a descargar." -# Script updateCache: para las imágenes sincronizadas tipo dir. -MSG_SCRIPTS_UPDATECACHE_CHECKSIZEDIR="Calcular el tamaño de la imagen." -MSG_SCRIPTS_UPDATECACHE_CHECKSIZEIMG="Comprobar si la imagen del repositorio es mayor que la de la caché." -MSG_SCRIPTS_UPDATECACHE_IFNOTCACHEDO="Comprobar el espacio libre de la caché y actuar según engine.cfg" - -MSG_SCRIPTS_UPDATECACHE_CHECKMCASTSESSION="Comprobando sesión Multicast: ServidorMcast:PuertoDatos" - -# interface sustituye temporalmente al scritp restore -MSG_SCRIPTS_CHECK_ENGINE="Analizar proceso a realizar según engine.cfg" -MSG_SCRIPTS_MULTICAST_PRECHECK_PORT="Determinar puerto principal y auxiliar Multicast." -MSG_SCRIPTS_MULTICAST_CHECK_PORT="Comprobar puertos de sesión y datos" -MSG_SCRIPTS_MULTICAST_REQUEST_PORT="Solicitar la apertura: " -MSG_SCRIPTS_OS_CONFIGURE="Iniciar la configuración del sistema restaurado" - -# TIME MESSAGES -MSG_SCRIPTS_TIME_TOTAL="tiempo total del proceso" -MSG_SCRIPTS_TIME_PARTIAL="tiempo parcial del subproceso" - -# HTTPLOG -MSG_HTTPLOG_NOUSE="No apague este ordenador por favor" - -# Mensajes sincronizadas -MSG_SYNC_RESIZE="Redimensiona la imagen al tamaño necesario" -MSG_SYNC_RESTORE="Trae el listado ficheros y baja la imagen" -MSG_SYNC_DELETE="Diferencial: Borra archivos antiguos" -MSG_SYNC_SLEEP="Espera que se monte/reduzca la imagen" -# Mensajes sincronizadas complementarios a errores -MSG_SYNC_DIFFERENTFS="El sistema de ficheros de destino no coincide con el de la imagen" -MSG_SYNC_EXTENSION="Las extensiones de la imagenes deben ser img o diff" -MSG_SYNC_NOCHECK="La imagen esta montada por otro proceso, no podemos comprobarla" - -MSG_RESTORE="Restaura la imagen en" - diff --git a/client/lib/engine/bin/ogGlobals.py b/client/lib/engine/bin/ogGlobals.py deleted file mode 100755 index cbce1ff..0000000 --- a/client/lib/engine/bin/ogGlobals.py +++ /dev/null @@ -1,112 +0,0 @@ -#!/usr/bin/python3 - -import sys -import os.path -import locale -import importlib.util - -def load_lang (name): - global lang - if name in sys.modules: - return True - elif (spec := importlib.util.find_spec (name)) is not None: - lang = importlib.util.module_from_spec (spec) - sys.modules[name] = lang - spec.loader.exec_module (lang) - return True - else: - #print(f"can't find the {name!r} module") - return False - -l = locale.getlocale()[0] -if not l: print (f"couldn't set locale") -if not l or not load_lang (f'lang_{l}'): - if not load_lang ('lang_en_GB'): - raise ModuleNotFoundError (f"can't find the default language module", name=name) - -TZ='Europe/Madrid' - - -## engine.cfg -OGLOGSESSION='/tmp/session.log' -OGLOGCOMMAND='/tmp/command.log' -#OGWINCHKDISK=True #Hacer chkdisk tras la clonacion -ACTIONCACHEFULL='NONE' #Que hacer cuando la cache no tenga espacio libre. [ NONE | FORMAT ] ] -RESTOREPROTOCOLNOTCACHE=None #Que protocolo de restauracion usar en el caso de que no exista cache o no exista espacio sufiente. [NONE | UNICAST | MULTICAST].NONE retorna error -IMGPROG='partclone' -IMGCOMP='lzop' -IMGEXT='img' -IMGREDUCE=True -#OGWINREDUCE=True #Al enviar particion reducir el sistema de archivos previamente. -MCASTERRORSESSION=120 #timeout (segundos) para abortar la sesion de multicast si no contacta con el servidor de multicast. Valor asignado a 0, utiliza los valores por defecto de udp-cast -MCASTWAIT=30 # timeout (segundos) para abortar la la transferencia si se interrumpe. Valor asignado a 0, utiliza los valores por defecto de udp-cast -#CREATESPEED=100000*4 # Factor para calcular el time-out al crear la imagen. 100000k -> 4s -#FACTORSYNC=120 # Factor de compresion para las imagenes (windos en ext4). -#BACKUP=False # Realizar copia de seguridad antes de crear la imagen. -#IMGFS='EXT4' # Sistema de archivo de la imagenes sincronizadas. EXT4 o BTRFS -#OGSLEEP=20 # Tiempo de sleep antes de realizar el reboot -NODEBUGFUNCTIONS=['ogCreateImageSyntax', 'ogGetHivePath', 'ogGetOsType', 'ogRestoreImageSyntax', 'ogUnmountAll', 'ogUnmountCache'] # Funciones que no deben mostrar salida de avisos si son llamadas por otras funciones. -#DEFAULTSPEED='' -## /engine.cfg - - -## loadenviron.sh -OPENGNSYS = '/opt/opengnsys' -OGBIN = os.path.join (OPENGNSYS, 'bin') -OGETC = os.path.join (OPENGNSYS, 'etc') -OGLIB = os.path.join (OPENGNSYS, 'lib') -OGAPI = os.path.join (OGLIB, 'engine', 'bin') -OGSCRIPTS = os.path.join (OPENGNSYS, 'scripts') -OGIMG = os.path.join (OPENGNSYS, 'images') -OGCAC = os.path.join (OPENGNSYS, 'cache') -OGLOG = os.path.join (OPENGNSYS, 'log') -OGLOGFILE = f'{OGLOG}/192.168.42.42' ## TODO import NetLib; OGLOGFILE = f'$OGLOG/{NetLib.ogGetIpAddress()}.log' -DEBUG = 'yes' -## /loadenviron.sh - -# Declaración de códigos de error. -OG_ERR_FORMAT=1 # Formato de ejecución incorrecto. -OG_ERR_NOTFOUND=2 # Fichero o dispositivo no encontrado. -OG_ERR_PARTITION=3 # Error en partición de disco. -OG_ERR_LOCKED=4 # Partición o fichero bloqueado. -OG_ERR_IMAGE=5 # Error al crear o restaurar una imagen. -OG_ERR_NOTOS=6 # Sin sistema operativo. -OG_ERR_NOTEXEC=7 # Programa o función no ejecutable. -# Códigos 8-13 reservados por ogAdmClient.h -OG_ERR_NOTWRITE=14 # No hay acceso de escritura -OG_ERR_NOTCACHE=15 # No hay particion cache en cliente -OG_ERR_CACHESIZE=16 # No hay espacio en la cache para almacenar fichero-imagen -OG_ERR_REDUCEFS=17 # Error al reducir sistema archivos -OG_ERR_EXTENDFS=18 # Error al expandir el sistema de archivos -OG_ERR_OUTOFLIMIT=19 # Valor fuera de rango o no válido. -OG_ERR_FILESYS=20 # Sistema de archivos desconocido o no se puede montar -OG_ERR_CACHE=21 # Error en partición de caché local -OG_ERR_NOGPT=22 # El disco indicado no contiene una particion GPT -OG_ERR_REPO=23 # Error al montar el repositorio de imagenes -OG_ERR_NOMSDOS=24 # El disco indicado no contienen una particion MSDOS - -OG_ERR_IMGSIZEPARTITION=30 # Error al restaurar partición más pequeña que la imagen -OG_ERR_UPDATECACHE=31 # Error al realizar el comando updateCache -OG_ERR_DONTFORMAT=32 # Error al formatear -OG_ERR_IMAGEFILE=33 # Archivo de imagen corrupto o de otra versión de $IMGPROG -OG_ERR_GENERIC=40 # Error imprevisto no definido -OG_ERR_UCASTSYNTAXT=50 # Error en la generación de sintaxis de transferenica UNICAST -OG_ERR_UCASTSENDPARTITION=51 # Error en envío UNICAST de partición -OG_ERR_UCASTSENDFILE=52 # Error en envío UNICAST de un fichero -OG_ERR_UCASTRECEIVERPARTITION=53 # Error en la recepcion UNICAST de una particion -OG_ERR_UCASTRECEIVERFILE=54 # Error en la recepcion UNICAST de un fichero -OG_ERR_MCASTSYNTAXT=55 # Error en la generacion de sintaxis de transferenica Multicast. -OG_ERR_MCASTSENDFILE=56 # Error en envio MULTICAST de un fichero -OG_ERR_MCASTRECEIVERFILE=57 # Error en la recepcion MULTICAST de un fichero -OG_ERR_MCASTSENDPARTITION=58 # Error en envio MULTICAST de una particion -OG_ERR_MCASTRECEIVERPARTITION=59 # Error en la recepcion MULTICAST de una particion -OG_ERR_PROTOCOLJOINMASTER=60 # Error en la conexion de una sesion UNICAST|MULTICAST con el MASTER - -OG_ERR_DONTMOUNT_IMAGE=70 # Error al montar una imagen sincronizada. -OG_ERR_DONTSYNC_IMAGE=71 # Imagen no sincronizable (es monolitica) -OG_ERR_DONTUNMOUNT_IMAGE=72 # Error al desmontar la imagen -OG_ERR_NOTDIFFERENT=73 # No se detectan diferencias entre la imagen basica y la particion. -OG_ERR_SYNCHRONIZING=74 # Error al sincronizar, puede afectar la creacion/restauracion de la imagen - -OG_ERR_NOTUEFI=80 # La interfaz UEFI no está activa -OG_ERR_NOTBIOS=81 # La interfaz BIOS legacy no está activa diff --git a/debian/control b/debian/control index 799c0e7..61875ca 100644 --- a/debian/control +++ b/debian/control @@ -11,6 +11,6 @@ Section: admin Priority: optional Architecture: all Depends: - samba, python3 (>=3.4) | python (>= 3.4), ${misc:Depends}, ${shlibs:Depends} + samba, ucf, python3 (>=3.4) | python (>= 3.4), ${misc:Depends}, ${shlibs:Depends} Description: OpenGnsys client files This package provides the basic filesystem for clients. diff --git a/debian/ogclient.postinst b/debian/ogclient.postinst new file mode 100644 index 0000000..7745d5f --- /dev/null +++ b/debian/ogclient.postinst @@ -0,0 +1,55 @@ +#!/bin/sh + +#. /usr/share/debconf/confmodule + +set -e +case "$1" in + configure) + # Create a temporary file with the modified configuration + SMB_CONF="/etc/samba/smb-ogclient.conf" + OLD_FILE="/etc/samba/smb.conf" + NEW_FILE=$(mktemp) + + # Ensure the template file exists + if [ ! -f "$SMB_CONF" ]; then + echo "Config file missing!" + exit 1 + fi + + # Check if our share section already exists + if grep -q "include = /etc/samba/smb-ogclient.conf" "$OLD_FILE"; then + # Section already exists, do nothing + rm -f "$NEW_FILE" + else + # Copy the original file + cp -a "$OLD_FILE" "$NEW_FILE" + + # Append our configuration + echo "include = /etc/samba/smb-ogclient.conf" >> "$NEW_FILE" + + # Use ucf to handle the file update + ucf --debconf-ok "$NEW_FILE" "$OLD_FILE" + + # Clean up + rm -f "$NEW_FILE" + + # Reload Samba + if command -v systemctl >/dev/null 2>&1; then + systemctl reload smbd.service + else + service smbd reload || true + fi + fi + ;; + abort-upgrade|abort-remove|abort-deconfigure) + ;; + + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +#DEBHELPER# + +exit 0 diff --git a/debian/ogclient.postrm b/debian/ogclient.postrm new file mode 100644 index 0000000..50b7439 --- /dev/null +++ b/debian/ogclient.postrm @@ -0,0 +1,28 @@ +#!/bin/sh -e + +#. /usr/share/debconf/confmodule + +set -e + +if [ "$1" = "remove" ] || [ "$1" = "purge" ]; then + # Create a temporary file with the configuration without our share + OLD_FILE="/etc/samba/smb.conf" + NEW_FILE=$(mktemp) + + # Remove our share section from the file + grep -v "include = /etc/samba/smb-ogclient.conf" "$OLD_FILE" > "$NEW_FILE" + + # Use ucf to update the file + ucf --debconf-ok "$NEW_FILE" "$OLD_FILE" + ucf --purge "$OLD_FILE" + + # Clean up + rm -f "$NEW_FILE" + + # Reload Samba + if command -v systemctl >/dev/null 2>&1; then + systemctl reload smbd.service + else + service smbd reload || true + fi +fi diff --git a/debian/rules b/debian/rules index b1ff31b..5738225 100755 --- a/debian/rules +++ b/debian/rules @@ -23,7 +23,7 @@ install: build mkdir -p debian/ogclient/opt/opengnsys/ogclient_log debian/ogclient/etc/samba cp -a client debian/ogclient/opt/opengnsys/ogclient mkdir -p debian/ogclient/opt/opengnsys/ogclient/images debian/ogclient/opt/opengnsys/ogclient/cache debian/ogclient/opt/opengnsys/ogclient/log - install --owner root --group root --mode 0644 etc/samba/smb-client.conf debian/ogclient/etc/samba/ + install --owner root --group root --mode 0644 etc/samba/smb-ogclient.conf debian/ogclient/etc/samba/ find debian/ogclient -name '*.swp' -exec rm -f '{}' ';' binary-arch: build install # emptyness @@ -40,7 +40,7 @@ binary-indep: build install dh_fixperms dh_installdeb ## ignore Qt*.so.4 errors - dh_shlibdeps --exclude debian/ogclient/opt/opengnsys/ogclient/bin/browser --exclude debian/ogclient/opt/opengnsys/ogclient/bin/grub-probe1.99_i686 + #dh_shlibdeps dh_gencontrol dh_md5sums dh_builddeb diff --git a/etc/samba/smb-client.conf b/etc/samba/smb-ogclient.conf similarity index 100% rename from etc/samba/smb-client.conf rename to etc/samba/smb-ogclient.conf