]> git.ipfire.org Git - thirdparty/systemd.git/blob - test/create-sys-script.py
Merge pull request #5131 from keszybz/environment-generators
[thirdparty/systemd.git] / test / create-sys-script.py
1 #!/usr/bin/python3
2
3 OUTFILE_HEADER = """#!/usr/bin/python3
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
29 import os, sys, stat, tempfile, filecmp
30
31
32 OUTFILE = "sys-script.py"
33 OUTFILE_MODE = 0o775
34
35 OUTFILE_FUNCS = r"""
36 import os, sys
37
38 def d(path, mode):
39 os.mkdir(path, mode)
40
41 def l(path, src):
42 os.symlink(src, path)
43
44 def f(path, mode, contents):
45 with open(path, "wb") as f:
46 f.write(contents)
47 os.chmod(path, mode)
48
49 """
50
51 OUTFILE_MAIN = """
52 if len(sys.argv) < 2:
53 exit("Usage: {} <target dir>".format(sys.argv[0]))
54
55 if not os.path.isdir(sys.argv[1]):
56 exit("Target dir {} not found".format(sys.argv[1]))
57
58 os.chdir(sys.argv[1])
59
60 """
61
62
63 def handle_dir(outfile, path):
64 m = os.lstat(path).st_mode & 0o777
65 outfile.write("d('{}', {:#o})\n".format(path, m))
66
67
68 def handle_link(outfile, path):
69 src = os.readlink(path)
70 outfile.write("l('{}', '{}')\n".format(path, src))
71
72
73 def escape_single_quotes(b):
74 # remove the b'' wrapping each line repr
75 r = repr(b)[2:-1]
76 # python escapes all ' only if there are ' and " in the string
77 if '"' not in r:
78 r = r.replace("'", r"\'")
79 # return line with all ' escaped
80 return r
81
82
83 def handle_file(outfile, path):
84 m = os.lstat(path).st_mode & 0o777
85 with open(path, "rb") as f:
86 b = f.read()
87 if b.count(b"\n") > 1:
88 r = "\n".join([ escape_single_quotes(l) for l in b.split(b"\n") ])
89 r = "b'''{r}'''".format(r=r)
90 else:
91 r = repr(b)
92 outfile.write("f('{}', {:#o}, {})\n".format(path, m, r))
93
94
95 def process_sysdir(outfile):
96 for (dirpath, dirnames, filenames) in os.walk("sys"):
97 handle_dir(outfile, dirpath)
98 for d in dirnames:
99 path = os.path.join(dirpath, d)
100 if stat.S_ISLNK(os.lstat(path).st_mode):
101 handle_link(outfile, path)
102 for f in filenames:
103 path = os.path.join(dirpath, f)
104 mode = os.lstat(path).st_mode
105 if stat.S_ISLNK(mode):
106 handle_link(outfile, path)
107 elif stat.S_ISREG(mode):
108 handle_file(outfile, path)
109
110
111 def verify_dir(tmpd, path_a):
112 path_b = os.path.join(tmpd, path_a)
113 mode_a = os.lstat(path_a).st_mode
114 mode_b = os.lstat(path_b).st_mode
115 if not stat.S_ISDIR(mode_b):
116 raise Exception("Not directory")
117 if (mode_a & 0o777) != (mode_b & 0o777):
118 raise Exception("Permissions mismatch")
119
120
121 def verify_link(tmpd, path_a):
122 path_b = os.path.join(tmpd, path_a)
123 if not stat.S_ISLNK(os.lstat(path_b).st_mode):
124 raise Exception("Not symlink")
125 if os.readlink(path_a) != os.readlink(path_b):
126 raise Exception("Symlink dest mismatch")
127
128
129 def verify_file(tmpd, path_a):
130 path_b = os.path.join(tmpd, path_a)
131 mode_a = os.lstat(path_a).st_mode
132 mode_b = os.lstat(path_b).st_mode
133 if not stat.S_ISREG(mode_b):
134 raise Exception("Not file")
135 if (mode_a & 0o777) != (mode_b & 0o777):
136 raise Exception("Permissions mismatch")
137 if not filecmp.cmp(path_a, path_b, shallow=False):
138 raise Exception("File contents mismatch")
139
140
141 def verify_script(tmpd):
142 for (dirpath, dirnames, filenames) in os.walk("sys"):
143 try:
144 path = dirpath
145 verify_dir(tmpd, path)
146 for d in dirnames:
147 path = os.path.join(dirpath, d)
148 if stat.S_ISLNK(os.lstat(path).st_mode):
149 verify_link(tmpd, path)
150 for f in filenames:
151 path = os.path.join(dirpath, f)
152 mode = os.lstat(path).st_mode
153 if stat.S_ISLNK(mode):
154 verify_link(tmpd, path)
155 elif stat.S_ISREG(mode):
156 verify_file(tmpd, path)
157 except Exception:
158 print("FAIL on '{}'".format(path), file=sys.stderr)
159 raise
160
161
162 if __name__ == "__main__":
163 # Always operate in the dir where this script is
164 os.chdir(os.path.dirname(sys.argv[0]))
165
166 if not os.path.isdir("sys"):
167 exit("No sys/ directory; please create before running this")
168
169 print("Creating {} using contents of sys/".format(OUTFILE))
170
171 with open(OUTFILE, "w") as f:
172 os.chmod(OUTFILE, OUTFILE_MODE)
173 f.write(OUTFILE_HEADER.replace(os.path.basename(sys.argv[0]), OUTFILE))
174 f.write(OUTFILE_FUNCS)
175 f.write(OUTFILE_MAIN)
176 process_sysdir(f)
177
178 with tempfile.TemporaryDirectory() as tmpd:
179 print("Recreating sys/ using {} at {}".format(OUTFILE, tmpd))
180 os.system("./{script} {tmpd}".format(script=OUTFILE, tmpd=tmpd))
181 verify_script(tmpd)
182
183 print("Verification successful, {} is correct".format(OUTFILE))