Skip to content

Commit ee84211

Browse files
committed
replace gen_init_cpio with PyCPIO
Signed-off-by: Zen <[email protected]>
1 parent 875ea10 commit ee84211

File tree

6 files changed

+26
-828
lines changed

6 files changed

+26
-828
lines changed

setup.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,9 @@
88
description="A simple initramfs generator",
99
author="desultory",
1010
package_data={
11-
"ugrd": ["*/*.toml",
12-
"include/gen_init_cpio.c"]
11+
"ugrd": ["*/*.toml"]
1312
},
14-
install_requires=['zenlib>=1.0.0'],
13+
install_requires=['zenlib>=1.1.1', 'pycpio>=0.5.0'],
1514
entry_points={
1615
"console_scripts": [
1716
"ugrd = ugrd.main:main"

ugrd/base/base.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
__author__ = 'desultory'
2-
__version__ = '1.4.0'
2+
__version__ = '2.0.0'
3+
4+
from importlib.metadata import version
35

46

57
def do_switch_root(self) -> str:
@@ -8,13 +10,13 @@ def do_switch_root(self) -> str:
810
Checks if the root mount is mounted, if not, starts a bash shell
911
"""
1012
mount_dest = self.config_dict['mounts']['root']['destination'] if not self.config_dict.get('switch_root_target') else self.config_dict['switch_root_target']
11-
out = [f"echo 'Checking root mount: {mount_dest}'"]
12-
out += [f"if grep -q ' {mount_dest} ' /proc/mounts ; then"]
13-
out += [f" exec switch_root {mount_dest} /sbin/init"]
14-
out += ["else"]
15-
out += [" echo 'Root mount not found, restarting'"]
16-
out += [" exec /init"]
17-
out += ["fi"]
18-
13+
out = [f"echo 'Checking root mount: {mount_dest}'",
14+
"if grep -q ' {mount_dest} ' /proc/mounts ; then",
15+
f' echo "Completed UGRD v{version("ugrd")}."',
16+
f" exec switch_root {mount_dest} /sbin/init",
17+
"else",
18+
" echo 'Root mount not found, restarting'",
19+
" exec /init",
20+
"fi"]
1921
return out
2022

ugrd/base/cpio.py

Lines changed: 10 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -1,135 +1,21 @@
11
__author__ = 'desultory'
2-
__version__ = '1.2.1'
2+
__version__ = '2.0.0'
33

44

5-
from subprocess import run, CompletedProcess
6-
from pathlib import Path
5+
from pycpio import PyCPIO
76

87

9-
def build_gen_init_cpio(self, cpio_path: Path) -> CompletedProcess:
10-
"""
11-
Builds the gen_init_cpio source file if it exists
12-
"""
13-
if not str(cpio_path).endswith('.c'):
14-
source_file = cpio_path.with_suffix('.c')
15-
else:
16-
source_file = cpio_path
17-
cpio_path = cpio_path.with_suffix('')
8+
def make_cpio(self) -> None:
9+
cpio = PyCPIO(logger=self.logger)
10+
cpio.append_recursive(self.build_dir, relative=True)
1811

19-
if source_file.exists():
20-
self.logger.info("Building gen_init_cpio at: %s" % source_file)
21-
return self._run(['gcc', '-o', str(cpio_path), str(source_file)])
22-
else:
23-
raise FileNotFoundError("gen_init_cpio source file not found at: %s" % source_file)
24-
25-
26-
def pack_cpio(self) -> None:
27-
"""
28-
Packs the CPIO file using gen_init_cpio
29-
"""
30-
cpio_path = Path(__file__).parent.parent / 'include' / 'gen_init_cpio'
31-
32-
if not cpio_path.exists():
33-
build_gen_init_cpio(self, cpio_path)
34-
35-
self.logger.debug("Using gen_init_cpio at: %s" % cpio_path)
36-
37-
packing_list = str(self.out_dir / self.config_dict['cpio_list_name'])
38-
self.logger.info("Creating CPIO file from packing list: %s" % packing_list)
12+
if self.config_dict['mknod_cpio']:
13+
for node in self.config_dict['nodes'].values():
14+
self.logger.debug("Adding CPIO node: %s" % node)
15+
cpio.add_chardev(name=node['path'], mode=node['mode'], major=node['major'], minor=node['minor'])
3916

4017
out_cpio = self.out_dir / self.config_dict['out_file']
4118
if out_cpio.exists():
4219
self._rotate_old(out_cpio)
4320

44-
with open(out_cpio, 'wb') as cpio_file:
45-
cmd = run([str(cpio_path), packing_list], stdout=cpio_file)
46-
if cmd.returncode != 0:
47-
raise RuntimeError("gen_init_cpio failed with error: %s" % cmd.stderr.decode())
48-
49-
self.logger.info("CPIO file created at: %s" % out_cpio)
50-
51-
try:
52-
self._chown(out_cpio)
53-
except PermissionError:
54-
self.logger.warning("Unable to change the owner of the CPIO file: %s" % out_cpio)
55-
56-
57-
def generate_cpio_mknods(self) -> list:
58-
"""
59-
Generate all of the node entries for the CPIO from self.config_dict['nodes']
60-
"""
61-
node_list = []
62-
63-
for node in self.config_dict["nodes"].values():
64-
self.logger.debug("Adding CPIO node: %s" % node)
65-
node_list.append(f"nod {node['path']} {str(oct(node['mode'] & 0o777))[2:]} 0 0 c {node['major']} {node['minor']}")
66-
67-
self.logger.debug("CPIO node list: %s" % node_list)
68-
return node_list
69-
70-
71-
def make_cpio_list(self) -> None:
72-
"""
73-
Generates a CPIO list file for gen_init_cpio.
74-
75-
All folders and files in self.build_dir are included.
76-
The file uid and gid will be set to 0 within the cpio.
77-
Device node information will be included if nodes are in the path,
78-
if cpio_nodes is set to true, nodes will be created in the cpio only.
79-
80-
The cpio packing list is written to self.out_dir/cpio.list
81-
"""
82-
from os import walk, minor, major
83-
from pathlib import Path
84-
85-
directory_list = []
86-
file_list = []
87-
symlink_list = []
88-
node_list = []
89-
90-
for root_dir, dirs, files in walk(self.build_dir):
91-
current_dir = Path(root_dir)
92-
relative_dir = current_dir.relative_to(self.build_dir)
93-
94-
if relative_dir == Path("."):
95-
self.logger.log(5, "Skipping root directory")
96-
else:
97-
directory_perms = str(oct(current_dir.stat().st_mode & 0o777))[2:]
98-
directory_list.append(f"dir /{str(relative_dir)} {str(directory_perms)} 0 0")
99-
100-
for file in files:
101-
file_dest = relative_dir / file
102-
file_source = current_dir / file
103-
if file_source.is_symlink():
104-
symlink_list.append(f"slink /{file_dest} {file_source.resolve()} 777 0 0")
105-
elif file_source.is_char_device():
106-
node_major = major(file_source.stat().st_rdev)
107-
node_minor = minor(file_source.stat().st_rdev)
108-
node_perms = str(oct(file_source.stat().st_mode & 0o777))[2:]
109-
node_list.append(f"nod /{file_dest} {node_perms} 0 0 c {node_major} {node_minor}")
110-
elif file_source.is_block_device():
111-
raise NotImplementedError("Block devices are not supported")
112-
else:
113-
file_perms = str(oct(file_source.stat().st_mode & 0o777))[2:]
114-
file_entry = f"file /{file_dest} {file_source} {file_perms} 0 0"
115-
file_list.append(file_entry)
116-
117-
if self.config_dict['mknod_cpio']:
118-
for node in generate_cpio_mknods(self):
119-
if node not in node_list:
120-
node_list.append(node)
121-
else:
122-
self.logger.warning("Duplicate node entry: %s" % node)
123-
124-
self.logger.log(5, "CPIO directory list: %s" % directory_list)
125-
self.logger.log(5, "CPIO file list: %s" % file_list)
126-
self.logger.log(5, "CPIO symlink list: %s" % symlink_list)
127-
self.logger.log(5, "CPIO node list: %s" % node_list)
128-
129-
packing_list = directory_list + file_list + symlink_list + node_list
130-
131-
cpio_list_path = self.out_dir / self.config_dict['cpio_list_name']
132-
if cpio_list_path.exists():
133-
self._rotate_old(cpio_list_path)
134-
135-
self._write(cpio_list_path, packing_list, in_build_dir=False)
21+
cpio.write_cpio_file(out_cpio)

ugrd/base/cpio.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ cpio_list_name = "cpio.list"
33
mknod_cpio = true
44

55
[imports.pack]
6-
"ugrd.base.cpio" = [ "make_cpio_list", "pack_cpio" ]
6+
"ugrd.base.cpio" = [ "make_cpio" ]
77

88
[custom_parameters]
99
out_file = "str" # The name of the cpio file to create.

0 commit comments

Comments
 (0)