##
-# Copyright (c) 2013 Peter Palfrader <peter@palfrader.org>
+# Copyright (c) 2013, 2017 Peter Palfrader <peter@palfrader.org>
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
sys.exit(1)
def get_session_owner(session):
- if re.search('[^0-9a-zA-Z_-]', session):
+ if re.search('^\.|~$|[^0-9a-zA-Z_.~-]', session):
die("Invalid session name.")
path = os.path.join('/var/lib/schroot/session', session)
die("Session owner mismatch.")
def os_supports_unshare():
- if platform.uname()[0] == 'GNU/kFreeBSD':
+ if platform.uname()[0] in ('GNU/kFreeBSD', 'GNU'):
return False
return True
def __init__(self, session, args, unshare=True):
self.unshare = unshare
if not os_supports_unshare(): self.unshare = False
- s,r = self.run('schroot', '-c', session, '--run-session', '--', 'env', 'DEBIAN_FRONTEND=noninteractive', *args)
+ s,r = self.run('schroot', '-c', session, '--directory=/', '--run-session', '--', 'env', 'DEBIAN_FRONTEND=noninteractive', *args)
if s != 0:
die("Command %s exited due to signal %d."%(' '.join(args), s))
if r != 0:
cmdstr = ' '.join(pipes.quote(s) for s in cmd)
cmd = ['unshare', '--uts', '--ipc', '--net', '--']
cmd += ['sh', '-c', 'ip addr add 127.0.0.1/8 dev lo && ip link set dev lo up && %s'%(cmdstr)]
- pid, fd = pty.fork()
+ (r, w) = os.pipe()
+ pid, ptyfd = pty.fork()
if pid == pty.CHILD:
+ os.close(r)
fd = os.open("/dev/null", os.O_RDWR)
os.dup2(fd, 0) # stdin
+ os.dup2(w, 1) # stdout
+ os.dup2(w, 2) # stderr
os.execlp(cmd[0], *cmd)
+ os.close(w)
try:
while 1:
- b = os.read(fd, 1)
+ b = os.read(r, 1)
if b == "": break
sys.stdout.write(b)
except OSError, e:
if e[0] == EIO: pass
else: raise
- os.close(fd)
+ os.close(r)
+ os.close(ptyfd) # we don't care about that one
p,v = os.waitpid(pid, 0)
s,r = WrappedRunner.get_ret(v)
return s,r
elif op == "install":
self.apt_install(args)
elif op == "build-dep":
- self.apt_build_dep(args)
+ try:
+ args.remove("--arch-only")
+ archonly = True
+ except ValueError:
+ archonly = False
+ self.apt_build_dep(args, archonly)
else:
die("Invalid operation %s"%(op,))
self.apt_simulate_and_ask(['dist-upgrade'])
def apt_install(self, packages):
+ packages = self.reject_invalid_packages(packages)
self.apt_simulate_and_ask(['install', '--'] + packages)
- def apt_build_dep(self, packages):
- self.apt_simulate_and_ask(['build-dep', '--'] + packages)
+ def apt_build_dep(self, packages, archonly=False):
+ packages = self.reject_invalid_packages(packages)
+ cmd = (['--arch-only'] if archonly else []) + ['build-dep', '--']
+ self.apt_simulate_and_ask(cmd + packages)
def apt_simulate_and_ask(self, cmd, split_download=True, run_clean=True):
if not self.assume_yes:
def secure_run(self, args, unshare=True):
WrappedRunner(self.session, args, unshare)
+ @staticmethod
+ def reject_invalid_packages(pkgs):
+ """filter package names
+
+ reject package names that start with . or /, as they are
+ not valid package names, but can be used to install local files
+ which we do not want.
+ """
+ new_pkgs = []
+ for p in pkgs:
+ if p.startswith('.') or p.startswith('/'):
+ die("invalid package name: %s"%(p,))
+ new_pkgs.append(p)
+ return new_pkgs
+
parser = optparse.OptionParser()
parser.set_usage("""%prog [options] -c <session-chroot> [-y] -- <command>