ogclone-engine/client/lib/engine/bin/FileSystemLib.py

967 lines
32 KiB
Python

import subprocess
import sys
import os.path
import ogGlobals
import SystemLib
import DiskLib
import CacheLib
import FileSystemLib
def ogCheckFs(int_ndisk, int_nfilesys):
if len(sys.argv) != 3:
SystemLib.ogRaiseError(
"session",
ogGlobals.OG_ERR_FORMAT,
"Not enough arguments"
)
return
# Obtener partición.
PART = DiskLib.ogDiskToDev(int_ndisk, int_nfilesys)
if not PART:
return
TYPE = ogGetFsType(int_ndisk, int_nfilesys)
if TYPE == "EXT[234]" or TYPE == "CACHE":
PROG = "e2fsck"
PARAMS = "-y"
CODES = [1, 2]
elif TYPE == "BTRFS":
PROG = "btrfsck"
CODES = [1]
elif TYPE == "REISERFS":
PROG = "fsck.reiserfs"
PARAMS = "<<<\"Yes\""
CODES = [1, 2]
elif TYPE == "REISER4":
PROG = "fsck.reiser4"
PARAMS = "-ay"
elif TYPE == "JFS":
PROG = "fsck.jfs"
CODES = [1, 2]
elif TYPE == "XFS":
PROG = "xfs_repair"
elif TYPE == "F2FS":
PROG = "fsck.f2fs"
elif TYPE == "NTFS":
PROG = "ntfsfix"
elif TYPE == "EXFAT":
PROG = "fsck.exfat"
elif TYPE == "FAT32":
PROG = "dosfsck"
PARAMS = "-a"
CODES = [1]
elif TYPE == "FAT16":
PROG = "dosfsck"
PARAMS = "-a"
CODES = [1]
elif TYPE == "FAT12":
PROG = "dosfsck"
PARAMS = "-a"
CODES = [1]
elif TYPE == "HFS":
PROG = "fsck.hfs"
PARAMS = "-f"
elif TYPE == "HFSPLUS":
PROG = "fsck.hfs"
PARAMS = "-f"
elif TYPE == "UFS":
PROG = "fsck.ufs"
elif TYPE == "ZFS":
PROG = "fsck.zfs"
else:
SystemLib.ogRaiseError(
"session",
ogGlobals.OG_ERR_PARTITION,
f"{int_ndisk}, {int_nfilesys}"
)
return
# Error si el sistema de archivos esta montado o bloqueado.
ogUnmount(int_ndisk, int_nfilesys)
if ogIsMounted(int_ndisk, int_nfilesys):
SystemLib.ogRaiseError(
"session",
ogGlobals.OG_ERR_PARTITION,
f"{int_ndisk} {int_nfilesys}"
)
return
if ogIsLocked(int_ndisk, int_nfilesys):
SystemLib.ogRaiseError(
"session",
ogGlobals.OG_ERR_LOCKED,
f"{int_ndisk} {int_nfilesys}"
)
return
# Comprobar en modo uso exclusivo.
ogLock(int_ndisk, int_nfilesys)
try:
result = subprocess.run([PROG, PARAMS, PART], capture_output=True)
ERRCODE = result.returncode
except FileNotFoundError:
SystemLib.ogRaiseError(
"session",
ogGlobals.OG_ERR_NOTEXEC,
PROG
)
ERRCODE = ogGlobals.OG_ERR_NOTEXEC
except:
SystemLib.ogRaiseError(
"session",
ogGlobals.OG_ERR_PARTITION,
f"{int_ndisk} {int_nfilesys}"
)
ERRCODE = ogGlobals.OG_ERR_PARTITION
ogUnlock(int_ndisk, int_nfilesys)
return ERRCODE
def ogExtendFs():
# Error si no se reciben 2 parámetros.
if len(sys.argv) != 3:
SystemLib.ogRaiseError(
"session",
ogGlobals.OG_ERR_FORMAT,
f"Not enough arguments"
)
return
# Obtener partición.
PART = DiskLib.ogDiskToDev(int(sys.argv[1]), int(sys.argv[2]))
if not PART:
return
# Redimensionar al tamaño máximo según el tipo de partición.
TYPE = ogGetFsType(int(sys.argv[1]), int(sys.argv[2]))
if TYPE == "EXT[234]":
PROG = "resize2fs"
PARAMS = "-f"
elif TYPE == "BTRFS":
PROG = "btrfs"
PARAMS = "filesystem resize max"
DOMOUNT = True # Debe estar montado.
elif TYPE == "REISERFS" or TYPE == "REISER4":
PROG = "resize_reiserfs"
PARAMS = "-f"
elif TYPE == "F2FS" or TYPE == "JFS" or TYPE == "NILFS2" or TYPE == "XFS" or TYPE == "EXFAT" or TYPE == "FAT32" or TYPE == "FAT16" or TYPE == "HFS" or TYPE == "HFSPLUS" or TYPE == "UFS":
return # No se reduce (por el momento).
elif TYPE == "NTFS":
PROG = "ntfsresize"
PARAMS = "<<<\"y\" -f"
else:
SystemLib.ogRaiseError(
"session",
ogGlobals.OG_ERR_PARTITION,
f"{int(sys.argv[1])} {int(sys.argv[2])} {TYPE}"
)
return
# Salida normal si no se va a aplicar la operación.
if not PROG:
return
# Error si el sistema de archivos no se queda en el estado de montaje adecuado.
if DOMOUNT:
PART = ogMount(int(sys.argv[1]), int(sys.argv[2]))
if not PART:
return
else:
ogUnmount(int(sys.argv[1]), int(sys.argv[2]))
if ogIsMounted(int(sys.argv[1]), int(sys.argv[2])):
SystemLib.ogRaiseError(
"session",
ogGlobals.OG_ERR_PARTITION,
f"{int(sys.argv[1])} {int(sys.argv[2])}"
)
return
# Error si el sistema de archivos está bloqueado.
if ogIsLocked(int(sys.argv[1]), int(sys.argv[2])):
SystemLib.ogRaiseError(
"session",
ogGlobals.OG_ERR_LOCKED,
f"{int(sys.argv[1])} {int(sys.argv[2])}"
)
return
# Redimensionar en modo uso exclusivo.
ogLock(int(sys.argv[1]), int(sys.argv[2]))
try:
subprocess.run([PROG, PARAMS, PART], capture_output=True)
ERRCODE = 0
except FileNotFoundError:
SystemLib.ogRaiseError(
"session",
ogGlobals.OG_ERR_NOTEXEC,
PROG
)
ERRCODE = ogGlobals.OG_ERR_NOTEXEC
except:
SystemLib.ogRaiseError(
"session",
ogGlobals.OG_ERR_PARTITION,
f"{int(sys.argv[1])} {int(sys.argv[2])}"
)
ERRCODE = ogGlobals.OG_ERR_PARTITION
ogUnlock(int(sys.argv[1]), int(sys.argv[2]))
return ERRCODE
#/**
# 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)
#/**
# 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, type=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 type:
type = ogGetFsType (disk, par)
if not type:
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 type not in data:
SystemLib.ogRaiseError (
[],
ogGlobals.OG_ERR_PARTITION,
f"{disk} {par} {type}"
)
return
d = data[type]
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, PART])
else:
errcode = subprocess.run ([prog, params, PART], input=input, text=True)
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)
print (f'nati: ogIsPartitionLocked: DISK ({DISK}) PART ({PART})')
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)
print (f'nati: ogIsPartitionLocked: LOCKDISK ({LOCKDISK}) LOCKPART ({LOCKPART}) rc ({rc})')
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('/', '-')}"
open(LOCKFILE, 'w').close()
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])
def ogMountFirstFs(int_ndisk):
# Obtener número de particiones del disco.
NPARTS = DiskLib.ogGetPartitionsNumber(int_ndisk)
for PART in range(1, NPARTS + 1):
MNTDIR = ogMount(int_ndisk, PART)
if MNTDIR:
return MNTDIR
SystemLib.ogRaiseError(
"session",
ogGlobals.OG_ERR_NOTFOUND,
f"{int_ndisk}"
)
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):
print (f'nati: ogMountFs: is locked disk ({disk}) par ({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
MNTDIR = subprocess.run(["mount", "-l", "-t", "iso9660", DEV], capture_output=True, text=True)
MNTDIR = MNTDIR.stdout.strip().split(" ")[2]
if not MNTDIR:
MNTDIR = DEV.replace("/dev", "/mnt")
os.makedirs(MNTDIR, exist_ok=True)
try:
subprocess.run(["mount", "-t", "iso9660", DEV, MNTDIR], check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
except subprocess.CalledProcessError:
SystemLib.ogRaiseError (
[],
ogGlobals.OG_ERR_PARTITION,
"cdrom"
)
return
return MNTDIR
def ogReduceFs(int_ndisk, int_nfilesys):
# Error si no se reciben 2 parámetros.
if len(sys.argv) != 3:
SystemLib.ogRaiseError (
[],
ogGlobals.OG_ERR_FORMAT,
"Not enough arguments"
)
return
# Obtener partición.
PART = DiskLib.ogDiskToDev(int_ndisk, int_nfilesys)
if not PART:
return
# Redimensionar según el tipo de partición.
TYPE = ogGetFsType(int_ndisk, int_nfilesys)
if TYPE == "EXT4":
ogUnmount(int_ndisk, int_nfilesys)
subprocess.run(["resize2fs", "-fpM", PART], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
elif TYPE == "BTRFS":
MNTDIR = ogMount(int_ndisk, int_nfilesys)
SIZE = subprocess.run(["btrfs", "filesystem", "show", MNTDIR], capture_output=True, text=True)
SIZE = SIZE.stdout.strip().split(" ")[6]
SIZE = int(float(SIZE) * 1.1 + 1)
subprocess.run(["btrfs", "filesystem", "resize", str(SIZE), MNTDIR], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
elif TYPE in ["REISERFS", "REISER4"]:
MNTDIR = ogMount(int_ndisk, int_nfilesys)
SIZE = int(subprocess.run(["df", "-k", MNTDIR], capture_output=True, text=True).stdout.strip().split("\n")[1].split()[2])
SIZE = SIZE * 110 // 100
ogUnmount(int_ndisk, int_nfilesys)
subprocess.run(["resize_reiserfs", "-s" + str(SIZE) + "K", PART], input="y\n", stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
elif TYPE == "NTFS":
ogUnmount(int_ndisk, int_nfilesys)
MAXSIZE, SIZE = subprocess.run(["ntfsresize", "-fi", PART], capture_output=True, text=True)
MAXSIZE = MAXSIZE.strip().split(" ")[3]
SIZE = SIZE.strip().split(" ")[4]
SIZE = int(float(SIZE) * 1.1 / 1024 + 1) * 1024
RETVAL = 1
while RETVAL != 0 and SIZE + EXTRASIZE < MAXSIZE:
EXTRASIZE = subprocess.run(["ntfsresize", "-fns", str(SIZE), PART], capture_output=True, text=True)
EXTRASIZE = int(EXTRASIZE.stdout.strip()) if EXTRASIZE.stdout.strip() else 0
RETVAL = EXTRASIZE != 0
SIZE += EXTRASIZE
if SIZE < MAXSIZE:
subprocess.run(["ntfsresize", "-fs", str(SIZE), PART], input="y\n", stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
elif TYPE in ["FAT32", "FAT16"]:
# No se reduce (por el momento).
pass
elif TYPE == "HFS" or TYPE == "HFSPLUS":
# No se reduce (por el momento).
pass
elif TYPE == "UFS":
# No se reduce (por el momento).
pass
else:
SystemLib.ogRaiseError (
[],
ogGlobals.OG_ERR_PARTITION,
f"{int_ndisk}, {int_nfilesys}"
)
# Devuelve tamaño del sistema de ficheros.
return ogGetFsSize(int_ndisk, int_nfilesys)
#/**
# 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('/', '-')}"
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(int_ndisk):
if len(sys.argv) != 3:
SystemLib.ogRaiseError (
[],
ogGlobals.OG_ERR_FORMAT,
"Not enough arguments"
)
return
# Obtener partición y punto de montaje.
DISK = DiskLib.ogDiskToDev(int_ndisk)
for PART in range(1, DiskLib.ogGetPartitionsNumber(int_ndisk) + 1):
if ogGetFsType(int_ndisk, PART) != "CACHE":
ogUnmount(int_ndisk, PART)
def ogUnsetDirtyBit(int_ndisk, int_nfilesys):
# Error si no se reciben 2 parámetros.
if len(sys.argv) != 3:
SystemLib.ogRaiseError (
[],
ogGlobals.OG_ERR_FORMAT,
"Not enough arguments"
)
return
# Obtener partición y punto de montaje.
PART = DiskLib.ogDiskToDev(int_ndisk, int_nfilesys)
if not PART:
return
# Realizar acciones específicas según el tipo de sistema de archivos.
TYPE = ogGetFsType(int_ndisk, int_nfilesys)
if TYPE == "NTFS":
ogUnmount(int_ndisk, int_nfilesys)
subprocess.run(["ntfsfix", "-d", PART], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
else:
pass # Add more specific actions for other file systems if needed.
#/**
# 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