Skip to content
This repository has been archived by the owner on Oct 2, 2024. It is now read-only.

Commit

Permalink
PR #1738: set --no-xattrs if filesystem claims not to support
Browse files Browse the repository at this point in the history
  • Loading branch information
reidpr authored Oct 18, 2023
1 parent db58648 commit 5000f03
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 6 deletions.
15 changes: 9 additions & 6 deletions lib/build_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,8 +276,13 @@ def __init__(self, image_root, path):
self.large_name = None
self.xattrs = dict()
if ch.save_xattrs:
for xattr in os.listxattr(self.path_abs, follow_symlinks=False):
self.xattrs[xattr] = os.getxattr(self.path_abs, xattr, follow_symlinks=False)
for xattr in ch.ossafe(os.listxattr,
"can’t list xattrs: %s" % self.path_abs,
self.path_abs, follow_symlinks=False):
self.xattrs[xattr] = \
ch.ossafe(os.getxattr, ("can’t get xattr: %s: %s"
% (self.path_abs, xattr)),
self.path_abs, xattr, follow_symlinks=False)

def __getstate__(self):
return { a:v for (a,v) in self.__dict__.items()
Expand Down Expand Up @@ -481,10 +486,8 @@ def git_restore(self, quick):
ch.ossafe(os.mkfifo, "can’t make FIFO: %s" % self.path, self.path_abs)
elif (self.path.git_incompatible_p):
self.path_abs.git_escaped.rename_(self.path_abs)
if ch.save_xattrs:
for (xattr, val) in self.xattrs.items():
ch.ossafe(os.setxattr, "unable to restore xattr: %s" % xattr,
self.path_abs, xattr, val, follow_symlinks=False)
for (xattr, val) in self.xattrs.items():
self.path_abs.setxattr(xattr, val, follow_symlinks=False)
# Recurse children.
if (len(self.children) > 0):
for child in self.children.values():
Expand Down
41 changes: 41 additions & 0 deletions lib/filesystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,31 @@ def git_incompatible_p(self):
"Return True if I can’t be stored in Git because of my name."
return self.name.startswith(".git")

@property
def is_root(self):
return (str(self) == "/")

@property
def mountpoint(self):
"""Return the mount point of the filesystem containing me (or, if
symlink, the file pointed to)."""
# https://stackoverflow.com/a/4453715
try:
pc = self.resolve(strict=True)
except RuntimeError:
ch.FATAL("not found, can’t resolve: %s" % self)
# Unclear whether ismount() deals correctly with the root directory, so
# do the stat(2) stuff ourself.
dev_child = pc.stat().st_dev
while (not pc.is_root):
dev_parent = pc.parent.stat().st_dev
if (dev_child != dev_parent):
return pc
pc = pc.parent
# Got all the way up to root without finding a transition, so we’re on
# the root filesystem.
return Path("/")

@classmethod
def gzip_set(cls):
"""Set gzip class attribute on first call to file_gzip().
Expand Down Expand Up @@ -383,6 +408,22 @@ def rmtree(self):
else:
assert False, "unimplemented"

def setxattr(self, name, value, follow_symlinks=True):
if (ch.save_xattrs):
try:
os.setxattr(self, name, value, follow_symlinks)
except OSError as x:
if (x.errno == errno.ENOTSUP): # no OSError subclass
ch.WARNING("xattrs not supported on %s, setting --no-xattr"
% (self.mountpoint))
ch.save_xattrs = False
else:
ch.FATAL("can’t set xattr: %s: %s: %s"
% (self, name, x.strerror))
if (not ch.save_xattrs): # not “else” because could have change in “if”
ch.DEBUG("xattrs disabled, ignoring: %s: %s" % (self, name))
return

def stat_(self, links):
"""An error-checking version of stat(). Note that we cannot simply
change the definition of stat() to be ossafe, as the exists() method
Expand Down

0 comments on commit 5000f03

Please sign in to comment.