blob: 11ed185de071b66fc279717ed972132983da93e4 [file] [log] [blame]
Jörg Thalheim3e67e5c2017-05-01 02:26:56 +02001#!/usr/bin/env python3
Yu Watanabedb9ecf02020-11-09 13:23:58 +09002# SPDX-License-Identifier: LGPL-2.1-or-later
Dan Streetmand001ac22017-02-10 15:27:18 -05003
Jörg Thalheim3e67e5c2017-05-01 02:26:56 +02004OUTFILE_HEADER = """#!/usr/bin/env python3
Yu Watanabedb9ecf02020-11-09 13:23:58 +09005# SPDX-License-Identifier: LGPL-2.1-or-later
Dan Streetmand001ac22017-02-10 15:27:18 -05006#
7# create-sys-script.py
8#
Lennart Poettering810adae2018-06-12 17:15:23 +02009# © 2017 Canonical Ltd.
Dan Streetmand001ac22017-02-10 15:27:18 -050010# Author: Dan Streetman <dan.streetman@canonical.com>
Dan Streetmand001ac22017-02-10 15:27:18 -050011"""
12
13# Use this only to (re-)create the test/sys-script.py script,
14# after adding or modifying anything in the test/sys/ directory
15
16
Zbigniew Jędrzejewski-Szmek227ef9b2017-09-29 12:27:21 +020017import os, sys
18import stat
19import tempfile
20import filecmp
21import subprocess
Dan Streetmand001ac22017-02-10 15:27:18 -050022
Dan Streetmand001ac22017-02-10 15:27:18 -050023OUTFILE_MODE = 0o775
24
25OUTFILE_FUNCS = r"""
26import os, sys
Zbigniew Jędrzejewski-Szmek0bca7952017-09-29 12:28:25 +020027import shutil
Dan Streetmand001ac22017-02-10 15:27:18 -050028
29def d(path, mode):
30 os.mkdir(path, mode)
31
32def l(path, src):
33 os.symlink(src, path)
34
35def f(path, mode, contents):
36 with open(path, "wb") as f:
37 f.write(contents)
38 os.chmod(path, mode)
Dan Streetmand001ac22017-02-10 15:27:18 -050039"""
40
41OUTFILE_MAIN = """
42if len(sys.argv) < 2:
43 exit("Usage: {} <target dir>".format(sys.argv[0]))
44
45if not os.path.isdir(sys.argv[1]):
46 exit("Target dir {} not found".format(sys.argv[1]))
47
48os.chdir(sys.argv[1])
49
Zbigniew Jędrzejewski-Szmek0bca7952017-09-29 12:28:25 +020050if os.path.exists('sys'):
51 shutil.rmtree('sys')
Dan Streetmand001ac22017-02-10 15:27:18 -050052"""
53
54
55def handle_dir(outfile, path):
56 m = os.lstat(path).st_mode & 0o777
Zbigniew Jędrzejewski-Szmek227ef9b2017-09-29 12:27:21 +020057 outfile.write(f"d('{path}', {m:#o})\n")
Dan Streetmand001ac22017-02-10 15:27:18 -050058
59
60def handle_link(outfile, path):
61 src = os.readlink(path)
Zbigniew Jędrzejewski-Szmek227ef9b2017-09-29 12:27:21 +020062 outfile.write(f"l('{path}', '{src}')\n")
Dan Streetmand001ac22017-02-10 15:27:18 -050063
64
65def escape_single_quotes(b):
66 # remove the b'' wrapping each line repr
67 r = repr(b)[2:-1]
68 # python escapes all ' only if there are ' and " in the string
69 if '"' not in r:
70 r = r.replace("'", r"\'")
71 # return line with all ' escaped
72 return r
73
74
75def handle_file(outfile, path):
76 m = os.lstat(path).st_mode & 0o777
77 with open(path, "rb") as f:
78 b = f.read()
79 if b.count(b"\n") > 1:
Zbigniew Jędrzejewski-Szmek227ef9b2017-09-29 12:27:21 +020080 r = "\n".join( escape_single_quotes(l) for l in b.split(b"\n") )
81 r = f"b'''{r}'''"
Dan Streetmand001ac22017-02-10 15:27:18 -050082 else:
83 r = repr(b)
Zbigniew Jędrzejewski-Szmek227ef9b2017-09-29 12:27:21 +020084 outfile.write(f"f('{path}', {m:#o}, {r})\n")
Dan Streetmand001ac22017-02-10 15:27:18 -050085
86
87def process_sysdir(outfile):
Zbigniew Jędrzejewski-Szmek227ef9b2017-09-29 12:27:21 +020088 for (dirpath, dirnames, filenames) in os.walk('sys'):
Dan Streetmand001ac22017-02-10 15:27:18 -050089 handle_dir(outfile, dirpath)
90 for d in dirnames:
91 path = os.path.join(dirpath, d)
92 if stat.S_ISLNK(os.lstat(path).st_mode):
93 handle_link(outfile, path)
94 for f in filenames:
95 path = os.path.join(dirpath, f)
96 mode = os.lstat(path).st_mode
97 if stat.S_ISLNK(mode):
98 handle_link(outfile, path)
99 elif stat.S_ISREG(mode):
100 handle_file(outfile, path)
101
102
103def verify_dir(tmpd, path_a):
104 path_b = os.path.join(tmpd, path_a)
105 mode_a = os.lstat(path_a).st_mode
106 mode_b = os.lstat(path_b).st_mode
107 if not stat.S_ISDIR(mode_b):
108 raise Exception("Not directory")
109 if (mode_a & 0o777) != (mode_b & 0o777):
110 raise Exception("Permissions mismatch")
111
112
113def verify_link(tmpd, path_a):
114 path_b = os.path.join(tmpd, path_a)
115 if not stat.S_ISLNK(os.lstat(path_b).st_mode):
116 raise Exception("Not symlink")
117 if os.readlink(path_a) != os.readlink(path_b):
118 raise Exception("Symlink dest mismatch")
119
120
121def verify_file(tmpd, path_a):
122 path_b = os.path.join(tmpd, path_a)
123 mode_a = os.lstat(path_a).st_mode
124 mode_b = os.lstat(path_b).st_mode
125 if not stat.S_ISREG(mode_b):
126 raise Exception("Not file")
127 if (mode_a & 0o777) != (mode_b & 0o777):
128 raise Exception("Permissions mismatch")
129 if not filecmp.cmp(path_a, path_b, shallow=False):
130 raise Exception("File contents mismatch")
131
132
133def verify_script(tmpd):
Zbigniew Jędrzejewski-Szmek227ef9b2017-09-29 12:27:21 +0200134 any = False
Dan Streetmand001ac22017-02-10 15:27:18 -0500135 for (dirpath, dirnames, filenames) in os.walk("sys"):
Zbigniew Jędrzejewski-Szmek227ef9b2017-09-29 12:27:21 +0200136 any = True
Dan Streetmand001ac22017-02-10 15:27:18 -0500137 try:
138 path = dirpath
139 verify_dir(tmpd, path)
140 for d in dirnames:
141 path = os.path.join(dirpath, d)
142 if stat.S_ISLNK(os.lstat(path).st_mode):
143 verify_link(tmpd, path)
144 for f in filenames:
145 path = os.path.join(dirpath, f)
146 mode = os.lstat(path).st_mode
147 if stat.S_ISLNK(mode):
148 verify_link(tmpd, path)
149 elif stat.S_ISREG(mode):
150 verify_file(tmpd, path)
151 except Exception:
Zbigniew Jędrzejewski-Szmek227ef9b2017-09-29 12:27:21 +0200152 print(f'FAIL on "{path}"', file=sys.stderr)
Dan Streetmand001ac22017-02-10 15:27:18 -0500153 raise
Zbigniew Jędrzejewski-Szmek227ef9b2017-09-29 12:27:21 +0200154 if not any:
155 exit('Nothing found!')
Dan Streetmand001ac22017-02-10 15:27:18 -0500156
157if __name__ == "__main__":
Zbigniew Jędrzejewski-Szmek227ef9b2017-09-29 12:27:21 +0200158 if len(sys.argv) < 2:
159 exit('Usage: create-sys-script.py /path/to/test/')
Dan Streetmand001ac22017-02-10 15:27:18 -0500160
Zbigniew Jędrzejewski-Szmek227ef9b2017-09-29 12:27:21 +0200161 outfile = os.path.abspath(os.path.dirname(sys.argv[0]) + '/sys-script.py')
162 print(f'Creating {outfile} using contents of {sys.argv[1]}/sys')
Dan Streetmand001ac22017-02-10 15:27:18 -0500163
Zbigniew Jędrzejewski-Szmek227ef9b2017-09-29 12:27:21 +0200164 os.chdir(sys.argv[1])
Dan Streetmand001ac22017-02-10 15:27:18 -0500165
Zbigniew Jędrzejewski-Szmek227ef9b2017-09-29 12:27:21 +0200166 with open(outfile, "w") as f:
167 os.chmod(outfile, OUTFILE_MODE)
168 f.write(OUTFILE_HEADER.replace(os.path.basename(sys.argv[0]),
169 os.path.basename(outfile)))
Dan Streetmand001ac22017-02-10 15:27:18 -0500170 f.write(OUTFILE_FUNCS)
171 f.write(OUTFILE_MAIN)
172 process_sysdir(f)
173
174 with tempfile.TemporaryDirectory() as tmpd:
Zbigniew Jędrzejewski-Szmek227ef9b2017-09-29 12:27:21 +0200175 print(f'Recreating sys/ using {outfile} at {tmpd}')
176 subprocess.check_call([outfile, tmpd])
Dan Streetmand001ac22017-02-10 15:27:18 -0500177 verify_script(tmpd)
178
Zbigniew Jędrzejewski-Szmek227ef9b2017-09-29 12:27:21 +0200179 print(f'Verification successful, {outfile} is correct')