From 65a258c677cea42c1772995b10402fd142ede8f1 Mon Sep 17 00:00:00 2001 From: Martin Langhoff Date: Thu, 21 Aug 2008 17:04:31 +1200 Subject: [PATCH] Backport of 4efdd691a 2007-06-28 Jeremy Katz * livecd.py (copytree): Preserve owners on copy (#243479). Also add support for preserving SELinux xattrs during the copy process --- livecd.py | 46 +++++++++++++++++++++++++++------------------- 1 files changed, 27 insertions(+), 19 deletions(-) diff --git a/livecd.py b/livecd.py index 7713344..b2b8bf5 100644 --- a/livecd.py +++ b/livecd.py @@ -23,6 +23,8 @@ import shutil import time import subprocess +import selinux + from rhpl.translate import _, N_ from flags import flags @@ -38,8 +40,13 @@ import packages import logging log = logging.getLogger("anaconda") -def copytree(src, dst, symlinks=False): +class Error(EnvironmentError): + pass + +def copytree(src, dst, symlinks=False, preserveOwner=False, + preserveSelinux=False): # copy of shutil.copytree which doesn't require dst to not exist + # and which also has options to preserve the owner and selinux contexts names = os.listdir(src) if not os.path.isdir(dst): os.makedirs(dst) @@ -52,10 +59,14 @@ def copytree(src, dst, symlinks=False): linkto = os.readlink(srcname) os.symlink(linkto, dstname) elif os.path.isdir(srcname): - copytree(srcname, dstname, symlinks) + copytree(srcname, dstname, symlinks, preserveOwner, preserveSelinux) else: - shutil.copy2(srcname, dstname) - # XXX What about devices, sockets etc.? + shutil.copyfile(srcname, dstname) + if preserveOwner: + os.chown(dstname, os.stat(srcname)[stat.ST_UID], os.stat(srcname)[stat.ST_GID]) + if preserveSelinux: + selinux.lsetfilecon(dstname, selinux.lgetfilecon(srcname)[1]) + shutil.copystat(srcname, dstname) except (IOError, os.error), why: errors.append((srcname, dstname, str(why))) # catch the Error from the recursive copytree so that we can @@ -63,6 +74,10 @@ def copytree(src, dst, symlinks=False): except Error, err: errors.extend(err.args[0]) try: + if preserveOwner: + os.chown(dst, os.stat(src)[stat.ST_UID], os.stat(src)[stat.ST_GID]) + if preserveSelinux: + selinux.lsetfilecon(dst, selinux.lgetfilecon(src)[1]) shutil.copystat(src, dst) except OSError, why: errors.extend((src, dst, str(why))) @@ -216,11 +231,15 @@ class LiveCDCopyBackend(backend.AnacondaBackend): wait.refresh() log.info("doing the copy for %s" %(tocopy,)) - entry.umount(anaconda.rootPath) - entry.mount(anaconda.rootPath + "/mnt") - # XXX: should use something with selinux knowledge... + # unmount subdirs + this one and then remount under /mnt + for e in fsdict[tocopy] + [entry]: + e.umount(anaconda.rootPath) + for e in [entry] + fsdict[tocopy]: + e.mount(anaconda.rootPath + "/mnt") + copytree("%s/%s" %(anaconda.rootPath, tocopy), - "%s/mnt/%s" %(anaconda.rootPath, tocopy)) + "%s/mnt/%s" %(anaconda.rootPath, tocopy), True, True, + flags.selinux) shutil.rmtree("%s/%s" %(anaconda.rootPath, tocopy)) wait.refresh() entry.umount(anaconda.rootPath + "/mnt") @@ -232,17 +251,6 @@ class LiveCDCopyBackend(backend.AnacondaBackend): pass wait.refresh() - # XXX: we should be preserving contexts on our copy, but - # this will do for now - for dir, subdirs, files in os.walk(os.path.normpath("%s/%s" %(anaconda.rootPath, tocopy))): - dir = dir[len(anaconda.rootPath):] - for f in map(lambda x: "%s/%s" %(dir, x), files) + [dir]: - if not os.access("%s/%s" %(anaconda.rootPath, f), os.R_OK): - continue - ret = isys.resetFileContext(os.path.normpath(f), - anaconda.rootPath) - log.info("set fc of %s to %s" %(f, ret)) - wait.refresh() # ensure that non-fstab filesystems are mounted in the chroot if flags.selinux: -- 1.5.5.1