changeset 241:d3c8a74922cd

* 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 (`..`).
author cmlenz
date Sun, 02 Oct 2005 17:16:20 +0000
parents 24e91cbae6e0
children 372d1de2e3ec
files bitten/slave.py bitten/util/archive.py
diffstat 2 files changed, 17 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- 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__':
--- 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:
Copyright (C) 2012-2017 Edgewall Software