diff options
author | Zac Medico <zmedico@gentoo.org> | 2007-09-26 04:46:33 +0000 |
---|---|---|
committer | Zac Medico <zmedico@gentoo.org> | 2007-09-26 04:46:33 +0000 |
commit | 2aec000c6ac2b236bdd9dba00d3a001d7fdcea7b (patch) | |
tree | d405b861ab2764e1a3ac9a60318dbc3b95c872f0 | |
parent | 8e2d9cd5ab9aabbfe1e65f635e7a10c473240d69 (diff) | |
download | portage-2aec000c6ac2b236bdd9dba00d3a001d7fdcea7b.tar.gz portage-2aec000c6ac2b236bdd9dba00d3a001d7fdcea7b.tar.bz2 portage-2aec000c6ac2b236bdd9dba00d3a001d7fdcea7b.zip |
Bugs #168772 and #193695 - During unmerge, only ignore specific
exceptions raised from unlink() and rmdir() calls.
Bug #193695 - Add support for FreeBSD chflags during unmerge. This
code is adapted from the code that already exists in movefile()
for the merge phase.
In movefile() FreeBSD chflags handling, use chflags instead of
lchflags when temporarily adjusting the flags on the parent
directory since we want to follow any symlinks to the real
parent directory.
(trunk r7803:7807)
svn path=/main/branches/2.1.2/; revision=7832
-rw-r--r-- | pym/portage.py | 83 |
1 files changed, 64 insertions, 19 deletions
diff --git a/pym/portage.py b/pym/portage.py index 47d204b63..39ecb0dab 100644 --- a/pym/portage.py +++ b/pym/portage.py @@ -4148,9 +4148,11 @@ def movefile(src,dest,newmtime=None,sstat=None,mysettings=None): if bsd_chflags: if destexists and dstat.st_flags != 0: bsd_chflags.lchflags(dest, 0) + # Use normal stat/chflags for the parent since we want to + # follow any symlinks to the real parent directory. pflags = os.stat(os.path.dirname(dest)).st_flags if pflags != 0: - bsd_chflags.lchflags(os.path.dirname(dest), 0) + bsd_chflags.chflags(os.path.dirname(dest), 0) if destexists: if stat.S_ISLNK(dstat[stat.ST_MODE]): @@ -4257,7 +4259,7 @@ def movefile(src,dest,newmtime=None,sstat=None,mysettings=None): if bsd_chflags: # Restore the flags we saved before moving if pflags: - bsd_chflags.lchflags(os.path.dirname(dest), pflags) + bsd_chflags.chflags(os.path.dirname(dest), pflags) return newmtime @@ -7446,7 +7448,30 @@ class dblink: #process symlinks second-to-last, directories last. mydirs = [] + ignored_unlink_errnos = (errno.ENOENT, errno.EISDIR) modprotect = os.path.join(self.vartree.root, "lib/modules/") + + def unlink(file_name, lstatobj): + if bsd_chflags: + if lstatobj.st_flags != 0: + bsd_chflags.lchflags(file_name, 0) + parent_name = os.path.dirname(file_name) + # Use normal stat/chflags for the parent since we want to + # follow any symlinks to the real parent directory. + pflags = os.stat(parent_name).st_flags + if pflags != 0: + bsd_chflags.chflags(parent_name, 0) + try: + if not stat.S_ISLNK(lstatobj.st_mode): + # Remove permissions to ensure that any hardlinks to + # suid/sgid files are rendered harmless. + os.chmod(file_name, 0) + os.unlink(file_name) + finally: + if bsd_chflags and pflags != 0: + # Restore the parent flags we saved before unlinking + bsd_chflags.chflags(parent_name, pflags) + def show_unmerge(zing, desc, file_type, file_name): writemsg_stdout("%s %s %s %s\n" % \ (zing, desc.ljust(8), file_type, file_name)) @@ -7496,13 +7521,11 @@ class dblink: not (islink and statobj and stat.S_ISDIR(statobj.st_mode)) and \ not self.isprotected(obj): try: - # Remove permissions to ensure that any hardlinks to - # suid/sgid files are rendered harmless. - if statobj and not islink: - os.chmod(obj, 0) - os.unlink(obj) + unlink(obj, lstatobj) except EnvironmentError, e: - pass + if e.errno not in ignored_unlink_errnos: + raise + del e show_unmerge("<<<", "", file_type, obj) continue @@ -7528,9 +7551,12 @@ class dblink: # contents as a directory even if it happens to correspond # to a symlink when it's merged to the live filesystem. try: - os.unlink(obj) + unlink(obj, lstatobj) show_unmerge("<<<", "", file_type, obj) - except (OSError,IOError),e: + except (OSError, IOError),e: + if e.errno not in ignored_unlink_errnos: + raise + del e show_unmerge("!!!", "", file_type, obj) elif pkgfiles[objkey][0] == "obj": if statobj is None or not stat.S_ISREG(statobj.st_mode): @@ -7550,13 +7576,11 @@ class dblink: show_unmerge("---", "!md5", file_type, obj) continue try: - # Remove permissions to ensure that any hardlinks to - # suid/sgid files are rendered harmless. - if not islink: - os.chmod(obj, 0) - os.unlink(obj) + unlink(obj, lstatobj) except (OSError,IOError),e: - pass + if e.errno not in ignored_unlink_errnos: + raise + del e show_unmerge("<<<", "", file_type, obj) elif pkgfiles[objkey][0] == "fif": if not stat.S_ISFIFO(lstatobj[stat.ST_MODE]): @@ -7571,10 +7595,31 @@ class dblink: for obj in mydirs: try: - os.rmdir(obj) + if bsd_chflags: + lstatobj = os.lstat(obj) + if lstatobj.st_flags != 0: + bsd_chflags.lchflags(obj, 0) + parent_name = os.path.dirname(obj) + # Use normal stat/chflags for the parent since we want to + # follow any symlinks to the real parent directory. + pflags = os.stat(parent_name).st_flags + if pflags != 0: + bsd_chflags.chflags(parent_name, 0) + try: + os.rmdir(obj) + finally: + if bsd_chflags and pflags != 0: + # Restore the parent flags we saved before unlinking + bsd_chflags.chflags(parent_name, pflags) show_unmerge("<<<", "", "dir", obj) - except (OSError, IOError): - show_unmerge("---", "!empty", "dir", obj) + except EnvironmentError, e: + if e.errno not in (errno.ENOENT, + errno.EEXIST, errno.ENOTEMPTY, + errno.ENOTDIR): + raise + if e.errno != errno.ENOENT: + show_unmerge("---", "!empty", "dir", obj) + del e #remove self from vartree database so that our own virtual gets zapped if we're the last node self.vartree.zap(self.mycpv) |