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