mirror of
https://github.com/systemd/systemd.git
synced 2024-11-01 17:51:22 +03:00
11a1589223
Files which are installed as-is (any .service and other unit files, .conf files, .policy files, etc), are left as is. My assumption is that SPDX identifiers are not yet that well known, so it's better to retain the extended header to avoid any doubt. I also kept any copyright lines. We can probably remove them, but it'd nice to obtain explicit acks from all involved authors before doing that.
180 lines
4.9 KiB
Python
Executable File
180 lines
4.9 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
# SPDX-License-Identifier: LGPL-2.1+
|
|
|
|
OUTFILE_HEADER = """#!/usr/bin/env python3
|
|
# SPDX-License-Identifier: LGPL-2.1+
|
|
#
|
|
# create-sys-script.py
|
|
#
|
|
# (C) 2017 Canonical Ltd.
|
|
# Author: Dan Streetman <dan.streetman@canonical.com>
|
|
"""
|
|
|
|
# Use this only to (re-)create the test/sys-script.py script,
|
|
# after adding or modifying anything in the test/sys/ directory
|
|
|
|
|
|
import os, sys
|
|
import stat
|
|
import tempfile
|
|
import filecmp
|
|
import subprocess
|
|
|
|
OUTFILE_MODE = 0o775
|
|
|
|
OUTFILE_FUNCS = r"""
|
|
import os, sys
|
|
import shutil
|
|
|
|
def d(path, mode):
|
|
os.mkdir(path, mode)
|
|
|
|
def l(path, src):
|
|
os.symlink(src, path)
|
|
|
|
def f(path, mode, contents):
|
|
with open(path, "wb") as f:
|
|
f.write(contents)
|
|
os.chmod(path, mode)
|
|
"""
|
|
|
|
OUTFILE_MAIN = """
|
|
if len(sys.argv) < 2:
|
|
exit("Usage: {} <target dir>".format(sys.argv[0]))
|
|
|
|
if not os.path.isdir(sys.argv[1]):
|
|
exit("Target dir {} not found".format(sys.argv[1]))
|
|
|
|
os.chdir(sys.argv[1])
|
|
|
|
if os.path.exists('sys'):
|
|
shutil.rmtree('sys')
|
|
"""
|
|
|
|
|
|
def handle_dir(outfile, path):
|
|
m = os.lstat(path).st_mode & 0o777
|
|
outfile.write(f"d('{path}', {m:#o})\n")
|
|
|
|
|
|
def handle_link(outfile, path):
|
|
src = os.readlink(path)
|
|
outfile.write(f"l('{path}', '{src}')\n")
|
|
|
|
|
|
def escape_single_quotes(b):
|
|
# remove the b'' wrapping each line repr
|
|
r = repr(b)[2:-1]
|
|
# python escapes all ' only if there are ' and " in the string
|
|
if '"' not in r:
|
|
r = r.replace("'", r"\'")
|
|
# return line with all ' escaped
|
|
return r
|
|
|
|
|
|
def handle_file(outfile, path):
|
|
m = os.lstat(path).st_mode & 0o777
|
|
with open(path, "rb") as f:
|
|
b = f.read()
|
|
if b.count(b"\n") > 1:
|
|
r = "\n".join( escape_single_quotes(l) for l in b.split(b"\n") )
|
|
r = f"b'''{r}'''"
|
|
else:
|
|
r = repr(b)
|
|
outfile.write(f"f('{path}', {m:#o}, {r})\n")
|
|
|
|
|
|
def process_sysdir(outfile):
|
|
for (dirpath, dirnames, filenames) in os.walk('sys'):
|
|
handle_dir(outfile, dirpath)
|
|
for d in dirnames:
|
|
path = os.path.join(dirpath, d)
|
|
if stat.S_ISLNK(os.lstat(path).st_mode):
|
|
handle_link(outfile, path)
|
|
for f in filenames:
|
|
path = os.path.join(dirpath, f)
|
|
mode = os.lstat(path).st_mode
|
|
if stat.S_ISLNK(mode):
|
|
handle_link(outfile, path)
|
|
elif stat.S_ISREG(mode):
|
|
handle_file(outfile, path)
|
|
|
|
|
|
def verify_dir(tmpd, path_a):
|
|
path_b = os.path.join(tmpd, path_a)
|
|
mode_a = os.lstat(path_a).st_mode
|
|
mode_b = os.lstat(path_b).st_mode
|
|
if not stat.S_ISDIR(mode_b):
|
|
raise Exception("Not directory")
|
|
if (mode_a & 0o777) != (mode_b & 0o777):
|
|
raise Exception("Permissions mismatch")
|
|
|
|
|
|
def verify_link(tmpd, path_a):
|
|
path_b = os.path.join(tmpd, path_a)
|
|
if not stat.S_ISLNK(os.lstat(path_b).st_mode):
|
|
raise Exception("Not symlink")
|
|
if os.readlink(path_a) != os.readlink(path_b):
|
|
raise Exception("Symlink dest mismatch")
|
|
|
|
|
|
def verify_file(tmpd, path_a):
|
|
path_b = os.path.join(tmpd, path_a)
|
|
mode_a = os.lstat(path_a).st_mode
|
|
mode_b = os.lstat(path_b).st_mode
|
|
if not stat.S_ISREG(mode_b):
|
|
raise Exception("Not file")
|
|
if (mode_a & 0o777) != (mode_b & 0o777):
|
|
raise Exception("Permissions mismatch")
|
|
if not filecmp.cmp(path_a, path_b, shallow=False):
|
|
raise Exception("File contents mismatch")
|
|
|
|
|
|
def verify_script(tmpd):
|
|
any = False
|
|
for (dirpath, dirnames, filenames) in os.walk("sys"):
|
|
any = True
|
|
try:
|
|
path = dirpath
|
|
verify_dir(tmpd, path)
|
|
for d in dirnames:
|
|
path = os.path.join(dirpath, d)
|
|
if stat.S_ISLNK(os.lstat(path).st_mode):
|
|
verify_link(tmpd, path)
|
|
for f in filenames:
|
|
path = os.path.join(dirpath, f)
|
|
mode = os.lstat(path).st_mode
|
|
if stat.S_ISLNK(mode):
|
|
verify_link(tmpd, path)
|
|
elif stat.S_ISREG(mode):
|
|
verify_file(tmpd, path)
|
|
except Exception:
|
|
print(f'FAIL on "{path}"', file=sys.stderr)
|
|
raise
|
|
if not any:
|
|
exit('Nothing found!')
|
|
|
|
if __name__ == "__main__":
|
|
if len(sys.argv) < 2:
|
|
exit('Usage: create-sys-script.py /path/to/test/')
|
|
|
|
outfile = os.path.abspath(os.path.dirname(sys.argv[0]) + '/sys-script.py')
|
|
print(f'Creating {outfile} using contents of {sys.argv[1]}/sys')
|
|
|
|
os.chdir(sys.argv[1])
|
|
|
|
with open(outfile, "w") as f:
|
|
os.chmod(outfile, OUTFILE_MODE)
|
|
f.write(OUTFILE_HEADER.replace(os.path.basename(sys.argv[0]),
|
|
os.path.basename(outfile)))
|
|
f.write(OUTFILE_FUNCS)
|
|
f.write(OUTFILE_MAIN)
|
|
process_sysdir(f)
|
|
|
|
with tempfile.TemporaryDirectory() as tmpd:
|
|
print(f'Recreating sys/ using {outfile} at {tmpd}')
|
|
subprocess.check_call([outfile, tmpd])
|
|
verify_script(tmpd)
|
|
|
|
print(f'Verification successful, {outfile} is correct')
|