1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
import glob
import pathlib
import logging
import json
from dataclasses import dataclass
from typing import Optional, List, Dict, Any, Iterator, TYPE_CHECKING
from ..exceptions import SysCallError
from ..general import SysCommand
from ..output import log
if TYPE_CHECKING:
from .btrfs import BtrfsSubvolumeInfo
@dataclass
class MapperDev:
mappername :str
@property
def name(self):
return self.mappername
@property
def path(self):
return f"/dev/mapper/{self.mappername}"
@property
def partition(self):
from .helpers import uevent, get_parent_of_partition
from .partition import Partition
from .blockdevice import BlockDevice
for mapper in glob.glob('/dev/mapper/*'):
path_obj = pathlib.Path(mapper)
if path_obj.name == self.mappername and pathlib.Path(mapper).is_symlink():
dm_device = (pathlib.Path("/dev/mapper/") / path_obj.readlink()).resolve()
for slave in glob.glob(f"/sys/class/block/{dm_device.name}/slaves/*"):
partition_belonging_to_dmcrypt_device = pathlib.Path(slave).name
try:
uevent_data = SysCommand(f"blkid -o export /dev/{partition_belonging_to_dmcrypt_device}").decode()
except SysCallError as error:
log(f"Could not get information on device /dev/{partition_belonging_to_dmcrypt_device}: {error}", level=logging.ERROR, fg="red")
information = uevent(uevent_data)
block_device = BlockDevice(get_parent_of_partition('/dev/' / pathlib.Path(information['DEVNAME'])))
return Partition(information['DEVNAME'], block_device=block_device)
raise ValueError(f"Could not convert {self.mappername} to a real dm-crypt device")
@property
def mountpoint(self) -> Optional[pathlib.Path]:
try:
data = json.loads(SysCommand(f"findmnt --json -R {self.path}").decode())
for filesystem in data['filesystems']:
return pathlib.Path(filesystem.get('target'))
except SysCallError as error:
# Not mounted anywhere most likely
log(f"Could not locate mount information for {self.path}: {error}", level=logging.WARNING, fg="yellow")
pass
return None
@property
def mountpoints(self) -> List[Dict[str, Any]]:
return [obj['target'] for obj in self.mount_information]
@property
def mount_information(self) -> List[Dict[str, Any]]:
from .helpers import find_mountpoint
return [{**obj, 'target' : pathlib.Path(obj.get('target', '/dev/null'))} for obj in find_mountpoint(self.path)]
@property
def filesystem(self) -> Optional[str]:
from .helpers import get_filesystem_type
return get_filesystem_type(self.path)
@property
def subvolumes(self) -> Iterator['BtrfsSubvolumeInfo']:
from .btrfs import subvolume_info_from_path
for mountpoint in self.mount_information:
if target := mountpoint.get('target'):
if subvolume := subvolume_info_from_path(pathlib.Path(target)):
yield subvolume
|