summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZac Medico <zmedico@gentoo.org>2007-09-26 04:46:33 +0000
committerZac Medico <zmedico@gentoo.org>2007-09-26 04:46:33 +0000
commit2aec000c6ac2b236bdd9dba00d3a001d7fdcea7b (patch)
treed405b861ab2764e1a3ac9a60318dbc3b95c872f0
parent8e2d9cd5ab9aabbfe1e65f635e7a10c473240d69 (diff)
downloadportage-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.py83
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)