]> git.ipfire.org Git - thirdparty/systemd.git/blob - test/create-sys-script.py
tools/hwdb-update: allow downloads to fail
[thirdparty/systemd.git] / test / create-sys-script.py
1 #!/usr/bin/env python3
2 # SPDX-License-Identifier: LGPL-2.1+
3
4 OUTFILE_HEADER = """#!/usr/bin/env python3
5 # SPDX-License-Identifier: LGPL-2.1+
6 #
7 # create-sys-script.py
8 #
9 # (C) 2017 Canonical Ltd.
10 # Author: Dan Streetman <dan.streetman@canonical.com>
11 #
12 # systemd is free software; you can redistribute it and/or modify it
13 # under the terms of the GNU Lesser General Public License as published by
14 # the Free Software Foundation; either version 2.1 of the License, or
15 # (at your option) any later version.
16 #
17 # systemd is distributed in the hope that it will be useful, but
18 # WITHOUT ANY WARRANTY; without even the implied warranty of
19 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 # Lesser General Public License for more details.
21 #
22 # You should have received a copy of the GNU Lesser General Public License
23 # along with systemd; If not, see <http://www.gnu.org/licenses/>.
24 #
25 """
26
27 # Use this only to (re-)create the test/sys-script.py script,
28 # after adding or modifying anything in the test/sys/ directory
29
30
31 import os, sys
32 import stat
33 import tempfile
34 import filecmp
35 import subprocess
36
37 OUTFILE_MODE = 0o775
38
39 OUTFILE_FUNCS = r"""
40 import os, sys
41 import shutil
42
43 def d(path, mode):
44 os.mkdir(path, mode)
45
46 def l(path, src):
47 os.symlink(src, path)
48
49 def f(path, mode, contents):
50 with open(path, "wb") as f:
51 f.write(contents)
52 os.chmod(path, mode)
53 """
54
55 OUTFILE_MAIN = """
56 if len(sys.argv) < 2:
57 exit("Usage: {} <target dir>".format(sys.argv[0]))
58
59 if not os.path.isdir(sys.argv[1]):
60 exit("Target dir {} not found".format(sys.argv[1]))
61
62 os.chdir(sys.argv[1])
63
64 if os.path.exists('sys'):
65 shutil.rmtree('sys')
66 """
67
68
69 def handle_dir(outfile, path):
70 m = os.lstat(path).st_mode & 0o777
71 outfile.write(f"d('{path}', {m:#o})\n")
72
73
74 def handle_link(outfile, path):
75 src = os.readlink(path)
76 outfile.write(f"l('{path}', '{src}')\n")
77
78
79 def escape_single_quotes(b):
80 # remove the b'' wrapping each line repr
81 r = repr(b)[2:-1]
82 # python escapes all ' only if there are ' and " in the string
83 if '"' not in r:
84 r = r.replace("'", r"\'")
85 # return line with all ' escaped
86 return r
87
88
89 def handle_file(outfile, path):
90 m = os.lstat(path).st_mode & 0o777
91 with open(path, "rb") as f:
92 b = f.read()
93 if b.count(b"\n") > 1:
94 r = "\n".join( escape_single_quotes(l) for l in b.split(b"\n") )
95 r = f"b'''{r}'''"
96 else:
97 r = repr(b)
98 outfile.write(f"f('{path}', {m:#o}, {r})\n")
99
100
101 def process_sysdir(outfile):
102 for (dirpath, dirnames, filenames) in os.walk('sys'):
103 handle_dir(outfile, dirpath)
104 for d in dirnames:
105 path = os.path.join(dirpath, d)
106 if stat.S_ISLNK(os.lstat(path).st_mode):
107 handle_link(outfile, path)
108 for f in filenames:
109 path = os.path.join(dirpath, f)
110 mode = os.lstat(path).st_mode
111 if stat.S_ISLNK(mode):
112 handle_link(outfile, path)
113 elif stat.S_ISREG(mode):
114 handle_file(outfile, path)
115
116
117 def verify_dir(tmpd, path_a):
118 path_b = os.path.join(tmpd, path_a)
119 mode_a = os.lstat(path_a).st_mode
120 mode_b = os.lstat(path_b).st_mode
121 if not stat.S_ISDIR(mode_b):
122 raise Exception("Not directory")
123 if (mode_a & 0o777) != (mode_b & 0o777):
124 raise Exception("Permissions mismatch")
125
126
127 def verify_link(tmpd, path_a):
128 path_b = os.path.join(tmpd, path_a)
129 if not stat.S_ISLNK(os.lstat(path_b).st_mode):
130 raise Exception("Not symlink")
131 if os.readlink(path_a) != os.readlink(path_b):
132 raise Exception("Symlink dest mismatch")
133
134
135 def verify_file(tmpd, path_a):
136 path_b = os.path.join(tmpd, path_a)
137 mode_a = os.lstat(path_a).st_mode
138 mode_b = os.lstat(path_b).st_mode
139 if not stat.S_ISREG(mode_b):
140 raise Exception("Not file")
141 if (mode_a & 0o777) != (mode_b & 0o777):
142 raise Exception("Permissions mismatch")
143 if not filecmp.cmp(path_a, path_b, shallow=False):
144 raise Exception("File contents mismatch")
145
146
147 def verify_script(tmpd):
148 any = False
149 for (dirpath, dirnames, filenames) in os.walk("sys"):
150 any = True
151 try:
152 path = dirpath
153 verify_dir(tmpd, path)
154 for d in dirnames:
155 path = os.path.join(dirpath, d)
156 if stat.S_ISLNK(os.lstat(path).st_mode):
157 verify_link(tmpd, path)
158 for f in filenames:
159 path = os.path.join(dirpath, f)
160 mode = os.lstat(path).st_mode
161 if stat.S_ISLNK(mode):
162 verify_link(tmpd, path)
163 elif stat.S_ISREG(mode):
164 verify_file(tmpd, path)
165 except Exception:
166 print(f'FAIL on "{path}"', file=sys.stderr)
167 raise
168 if not any:
169 exit('Nothing found!')
170
171 if __name__ == "__main__":
172 if len(sys.argv) < 2:
173 exit('Usage: create-sys-script.py /path/to/test/')
174
175 outfile = os.path.abspath(os.path.dirname(sys.argv[0]) + '/sys-script.py')
176 print(f'Creating {outfile} using contents of {sys.argv[1]}/sys')
177
178 os.chdir(sys.argv[1])
179
180 with open(outfile, "w") as f:
181 os.chmod(outfile, OUTFILE_MODE)
182 f.write(OUTFILE_HEADER.replace(os.path.basename(sys.argv[0]),
183 os.path.basename(outfile)))
184 f.write(OUTFILE_FUNCS)
185 f.write(OUTFILE_MAIN)
186 process_sysdir(f)
187
188 with tempfile.TemporaryDirectory() as tmpd:
189 print(f'Recreating sys/ using {outfile} at {tmpd}')
190 subprocess.check_call([outfile, tmpd])
191 verify_script(tmpd)
192
193 print(f'Verification successful, {outfile} is correct')