mirror of
https://github.com/flatcar/scripts.git
synced 2025-08-08 05:26:58 +02:00
221 lines
8.2 KiB
Python
Executable File
221 lines
8.2 KiB
Python
Executable File
#!/usr/bin/python
|
|
|
|
# Copyright (c) 2015 The CoreOS Authors. All rights reserved.
|
|
# Use of this source code is governed by a BSD-style license that can be
|
|
# found in the LICENSE file.
|
|
|
|
from __future__ import unicode_literals
|
|
|
|
import fnmatch
|
|
import os
|
|
import stat
|
|
import sys
|
|
|
|
import portage
|
|
from portage import dep
|
|
from portage import output
|
|
from portage.dep.soname.SonameAtom import SonameAtom
|
|
from portage.dep.soname.parse import parse_soname_deps
|
|
|
|
VARDB = portage.db[portage.root]["vartree"].dbapi
|
|
|
|
# TODO(marneam): possibly accept globs for arch and sonames
|
|
IGNORE_MISSING = {
|
|
# /usr/lib/go/src/debug/elf/testdata/gcc-386-freebsd-exec
|
|
# /usr/lib/go/src/debug/elf/testdata/gcc-amd64-linux-exec
|
|
"dev-lang/go": [SonameAtom("x86_32", "libc.so.6"),
|
|
SonameAtom("x86_64", "libc.so.6")],
|
|
"dev-lang/go-bootstrap": [SonameAtom("x86_32", "libc.so.6"),
|
|
SonameAtom("x86_64", "libc.so.6")],
|
|
|
|
# https://bugs.gentoo.org/show_bug.cgi?id=554582
|
|
"net-firewall/ebtables": [SonameAtom("arm_64", "libebt_802_3.so"),
|
|
SonameAtom("arm_64", "libebt_among.so"),
|
|
SonameAtom("arm_64", "libebt_arp.so"),
|
|
SonameAtom("arm_64", "libebt_arpreply.so"),
|
|
SonameAtom("arm_64", "libebt_ip.so"),
|
|
SonameAtom("arm_64", "libebt_ip6.so"),
|
|
SonameAtom("arm_64", "libebt_limit.so"),
|
|
SonameAtom("arm_64", "libebt_log.so"),
|
|
SonameAtom("arm_64", "libebt_mark.so"),
|
|
SonameAtom("arm_64", "libebt_mark_m.so"),
|
|
SonameAtom("arm_64", "libebt_nat.so"),
|
|
SonameAtom("arm_64", "libebt_nflog.so"),
|
|
SonameAtom("arm_64", "libebt_pkttype.so"),
|
|
SonameAtom("arm_64", "libebt_redirect.so"),
|
|
SonameAtom("arm_64", "libebt_standard.so"),
|
|
SonameAtom("arm_64", "libebt_stp.so"),
|
|
SonameAtom("arm_64", "libebt_ulog.so"),
|
|
SonameAtom("arm_64", "libebt_vlan.so"),
|
|
SonameAtom("arm_64", "libebtable_broute.so"),
|
|
SonameAtom("arm_64", "libebtable_filter.so"),
|
|
SonameAtom("arm_64", "libebtable_nat.so"),
|
|
SonameAtom("x86_64", "libebt_802_3.so"),
|
|
SonameAtom("x86_64", "libebt_among.so"),
|
|
SonameAtom("x86_64", "libebt_arp.so"),
|
|
SonameAtom("x86_64", "libebt_arpreply.so"),
|
|
SonameAtom("x86_64", "libebt_ip.so"),
|
|
SonameAtom("x86_64", "libebt_ip6.so"),
|
|
SonameAtom("x86_64", "libebt_limit.so"),
|
|
SonameAtom("x86_64", "libebt_log.so"),
|
|
SonameAtom("x86_64", "libebt_mark.so"),
|
|
SonameAtom("x86_64", "libebt_mark_m.so"),
|
|
SonameAtom("x86_64", "libebt_nat.so"),
|
|
SonameAtom("x86_64", "libebt_nflog.so"),
|
|
SonameAtom("x86_64", "libebt_pkttype.so"),
|
|
SonameAtom("x86_64", "libebt_redirect.so"),
|
|
SonameAtom("x86_64", "libebt_standard.so"),
|
|
SonameAtom("x86_64", "libebt_stp.so"),
|
|
SonameAtom("x86_64", "libebt_ulog.so"),
|
|
SonameAtom("x86_64", "libebt_vlan.so"),
|
|
SonameAtom("x86_64", "libebtable_broute.so"),
|
|
SonameAtom("x86_64", "libebtable_filter.so"),
|
|
SonameAtom("x86_64", "libebtable_nat.so")],
|
|
}
|
|
|
|
USR_LINKS = ("/bin/", "/sbin/", "/lib/", "/lib32/", "/lib64/")
|
|
|
|
IGNORE_SHEBANG = (
|
|
b"*/python2.7/cgi.py",
|
|
b"*/usr/lib64/modules/*/source/scripts/*",
|
|
b"*/usr/share/nova-agent/*/etc/gentoo/nova-agent",
|
|
b"*/tmp/*",
|
|
)
|
|
|
|
def provided_sonames():
|
|
for cpv in VARDB.cpv_all():
|
|
raw = VARDB.aux_get(cpv, ["PROVIDES"])[0]
|
|
for atom in parse_soname_deps(raw):
|
|
yield atom
|
|
|
|
# soname.provided in PORTAGE_CONFIGROOT
|
|
for atom in VARDB.settings.soname_provided:
|
|
yield atom
|
|
|
|
def ignore_sonames(cpv):
|
|
for key in dep.match_to_list(cpv, IGNORE_MISSING.iterkeys()):
|
|
for atom in IGNORE_MISSING[key]:
|
|
yield atom
|
|
|
|
def missing_sonames():
|
|
provided = frozenset(provided_sonames())
|
|
for cpv in VARDB.cpv_all():
|
|
raw = VARDB.aux_get(cpv, ["REQUIRES"])[0]
|
|
requires = frozenset(parse_soname_deps(raw))
|
|
ignore = frozenset(ignore_sonames(cpv))
|
|
missing = requires - provided - ignore
|
|
if missing:
|
|
yield (cpv, missing)
|
|
|
|
def usr_conflicts():
|
|
for cpv in VARDB.cpv_all():
|
|
raw = VARDB.aux_get(cpv, ["CONTENTS"])[0]
|
|
usr = set()
|
|
root = set()
|
|
|
|
# format is:
|
|
# obj /path goo 123
|
|
# dir /path/foo
|
|
# sym /this -> that 123
|
|
# and so on
|
|
for line in raw.split("\n"):
|
|
if line[:4] != "obj " and line[:4] != "sym ":
|
|
continue
|
|
|
|
# yeah, hard to read, trying to make it fast...
|
|
i = line.find("/", 5)
|
|
topdir = line[4:i+1]
|
|
if topdir == "/usr/":
|
|
j = line.find("/", 9)
|
|
nextdir = line[8:j+1]
|
|
if nextdir in USR_LINKS:
|
|
end = line.find(" ", 8)
|
|
usr.add(line[8:end])
|
|
elif topdir in USR_LINKS:
|
|
end = line.find(" ", 4)
|
|
root.add(line[4:end])
|
|
|
|
conflicts = frozenset(root).intersection(usr)
|
|
if conflicts:
|
|
yield (cpv, conflicts)
|
|
|
|
def check_libs():
|
|
ok = True
|
|
for cpv, sonames in missing_sonames():
|
|
error("%s is missing libraries:", cpv)
|
|
for soname in sonames:
|
|
error("\t%s", soname)
|
|
ok = False
|
|
return ok
|
|
|
|
def check_usr():
|
|
ok = True
|
|
for cpv, conflicts in usr_conflicts():
|
|
error("%s has paths that conflict with /usr", cpv)
|
|
for path in conflicts:
|
|
error("\t%s", path)
|
|
ok = False
|
|
return ok
|
|
|
|
def is_exe(path):
|
|
# just check other, assuming root or group only commands are not scripts.
|
|
perms = stat.S_IROTH|stat.S_IXOTH
|
|
mode = os.lstat(path).st_mode
|
|
return stat.S_ISREG(mode) and mode&perms == perms
|
|
|
|
def check_shebang():
|
|
ok = True
|
|
cache = {}
|
|
root = os.environ.get("ROOT", b"/")
|
|
for parent, _, files in os.walk(root):
|
|
for path in [os.path.join(parent, f) for f in files]:
|
|
if any(fnmatch.fnmatchcase(path,i) for i in IGNORE_SHEBANG):
|
|
continue
|
|
if not is_exe(path):
|
|
continue
|
|
with open(path, "r") as fd:
|
|
line = fd.readline(80)
|
|
if not line.startswith(b"#!"):
|
|
continue
|
|
cmd = line[2:].rstrip().split(None,1)[0]
|
|
if cmd not in cache:
|
|
cache[cmd] = os.path.exists(root+cmd)
|
|
if not cache[cmd]:
|
|
relpath = path[len(root):]
|
|
error("%s: %s does not exist", relpath, cmd)
|
|
ok = False
|
|
return ok
|
|
|
|
def error(fmt, *args):
|
|
sys.stderr.write(output.red(fmt % args))
|
|
sys.stderr.write("\n")
|
|
|
|
def main():
|
|
ok = True
|
|
check_funcs = {
|
|
"libs": check_libs,
|
|
"usr": check_usr,
|
|
"shebang": check_shebang,
|
|
}
|
|
|
|
if not sys.stderr.isatty():
|
|
output.nocolor()
|
|
|
|
checks = sys.argv[1:]
|
|
if not checks:
|
|
checks = check_funcs.keys()
|
|
|
|
for check in checks:
|
|
func = check_funcs.get(check)
|
|
if func:
|
|
ok = func() and ok
|
|
else:
|
|
error("Unknown test name '%s'", check)
|
|
error("Valid tests: %s", " ".join(check_funcs))
|
|
ok = False
|
|
|
|
return 0 if ok else 1
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|