]> git.ipfire.org Git - thirdparty/systemd.git/blame - test/create-sys-script.py
core: use id unit when retrieving unit file state (#8038)
[thirdparty/systemd.git] / test / create-sys-script.py
CommitLineData
3e67e5c9 1#!/usr/bin/env python3
35df7443 2# SPDX-License-Identifier: LGPL-2.1+
d001ac2c 3
3e67e5c9 4OUTFILE_HEADER = """#!/usr/bin/env python3
35df7443 5# SPDX-License-Identifier: LGPL-2.1+
d001ac2c
DS
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
227ef9bc
ZJS
31import os, sys
32import stat
33import tempfile
34import filecmp
35import subprocess
d001ac2c 36
d001ac2c
DS
37OUTFILE_MODE = 0o775
38
39OUTFILE_FUNCS = r"""
40import os, sys
0bca7954 41import shutil
d001ac2c
DS
42
43def d(path, mode):
44 os.mkdir(path, mode)
45
46def l(path, src):
47 os.symlink(src, path)
48
49def f(path, mode, contents):
50 with open(path, "wb") as f:
51 f.write(contents)
52 os.chmod(path, mode)
d001ac2c
DS
53"""
54
55OUTFILE_MAIN = """
56if len(sys.argv) < 2:
57 exit("Usage: {} <target dir>".format(sys.argv[0]))
58
59if not os.path.isdir(sys.argv[1]):
60 exit("Target dir {} not found".format(sys.argv[1]))
61
62os.chdir(sys.argv[1])
63
0bca7954
ZJS
64if os.path.exists('sys'):
65 shutil.rmtree('sys')
d001ac2c
DS
66"""
67
68
69def handle_dir(outfile, path):
70 m = os.lstat(path).st_mode & 0o777
227ef9bc 71 outfile.write(f"d('{path}', {m:#o})\n")
d001ac2c
DS
72
73
74def handle_link(outfile, path):
75 src = os.readlink(path)
227ef9bc 76 outfile.write(f"l('{path}', '{src}')\n")
d001ac2c
DS
77
78
79def 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
89def 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:
227ef9bc
ZJS
94 r = "\n".join( escape_single_quotes(l) for l in b.split(b"\n") )
95 r = f"b'''{r}'''"
d001ac2c
DS
96 else:
97 r = repr(b)
227ef9bc 98 outfile.write(f"f('{path}', {m:#o}, {r})\n")
d001ac2c
DS
99
100
101def process_sysdir(outfile):
227ef9bc 102 for (dirpath, dirnames, filenames) in os.walk('sys'):
d001ac2c
DS
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
117def 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
127def 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
135def 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
147def verify_script(tmpd):
227ef9bc 148 any = False
d001ac2c 149 for (dirpath, dirnames, filenames) in os.walk("sys"):
227ef9bc 150 any = True
d001ac2c
DS
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:
227ef9bc 166 print(f'FAIL on "{path}"', file=sys.stderr)
d001ac2c 167 raise
227ef9bc
ZJS
168 if not any:
169 exit('Nothing found!')
d001ac2c
DS
170
171if __name__ == "__main__":
227ef9bc
ZJS
172 if len(sys.argv) < 2:
173 exit('Usage: create-sys-script.py /path/to/test/')
d001ac2c 174
227ef9bc
ZJS
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')
d001ac2c 177
227ef9bc 178 os.chdir(sys.argv[1])
d001ac2c 179
227ef9bc
ZJS
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)))
d001ac2c
DS
184 f.write(OUTFILE_FUNCS)
185 f.write(OUTFILE_MAIN)
186 process_sysdir(f)
187
188 with tempfile.TemporaryDirectory() as tmpd:
227ef9bc
ZJS
189 print(f'Recreating sys/ using {outfile} at {tmpd}')
190 subprocess.check_call([outfile, tmpd])
d001ac2c
DS
191 verify_script(tmpd)
192
227ef9bc 193 print(f'Verification successful, {outfile} is correct')