# HG changeset patch # User cmlenz # Date 1128273380 0 # Node ID d3c8a74922cd4202c8b316b74cb832f96fcf9d2c # Parent 24e91cbae6e01792ff980e5851b3d081aae4460b * Add an option to `bitten-slave` that tells it to keep any files in the working directory. * Some safety measures for the unpacking of `tar` archives: no `chown`-ing, no absolute paths or paths containing up-references (`..`). diff --git a/bitten/slave.py b/bitten/slave.py --- a/bitten/slave.py +++ b/bitten/slave.py @@ -31,7 +31,7 @@ """Build slave.""" def __init__(self, ip, port, name=None, config=None, dry_run=False, - work_dir=None): + work_dir=None, keep_files=False): beep.Initiator.__init__(self, ip, port) self.name = name self.config = config @@ -41,6 +41,7 @@ elif not os.path.exists(work_dir): os.makedirs(work_dir) self.work_dir = work_dir + self.keep_files = keep_files def greeting_received(self, profiles): if OrchestrationProfileHandler.URI not in profiles: @@ -150,8 +151,9 @@ recipe = Recipe(self.recipe_xml, path, self.config) self.execute_build(msgno, recipe) finally: - shutil.rmtree(path) - os.unlink(archive_path) + if not self.session.keep_files: + shutil.rmtree(path) + os.remove(archive_path) def execute_build(self, msgno, recipe): log.info('Building in directory %s', recipe.ctxt.basedir) @@ -244,6 +246,9 @@ metavar='FILE', help='path to configuration file') parser.add_option('-d', '--work-dir', action='store', dest='work_dir', metavar='DIR', help='working directory for builds') + parser.add_option('-k', '--keep-files', action='store_const', + dest='keep_files', const=True, + help='don\'t delete files after builds') parser.add_option('-n', '--dry-run', action='store_const', dest='dry_run', const=True, help='don\'t report results back to master') parser.add_option('--debug', action='store_const', dest='loglevel', @@ -276,13 +281,14 @@ logger.addHandler(handler) slave = Slave(host, port, name=options.name, config=options.config, - dry_run=options.dry_run, work_dir=options.work_dir) + dry_run=options.dry_run, work_dir=options.work_dir, + keep_files=options.keep_files) try: slave.run() except KeyboardInterrupt: slave.quit() - if os.path.isdir(slave.work_dir): + if not options.keep_files and os.path.isdir(slave.work_dir): shutil.rmtree(slave.work_dir) if __name__ == '__main__': diff --git a/bitten/util/archive.py b/bitten/util/archive.py --- a/bitten/util/archive.py +++ b/bitten/util/archive.py @@ -157,10 +157,14 @@ if format in ('bzip2', 'gzip'): try: tar_file = tarfile.open(filename) + tar_file.chown = lambda *args: None # Don't chown extracted members try: for tarinfo in tar_file: - names.append(tarinfo.name) - tar_file.extract(tarinfo, dest_path) + if tarinfo.isfile() or tarinfo.isdir(): + if tarinfo.name.startswith('/') or '..' in tarinfo.name: + continue + names.append(tarinfo.name) + tar_file.extract(tarinfo, dest_path) finally: tar_file.close() except tarfile.TarError, e: