# Public License as described in the bup LICENSE file.
from __future__ import absolute_import, print_function
-from binascii import hexlify
from copy import deepcopy
from errno import EACCES, EINVAL, ENOTTY, ENOSYS, EOPNOTSUPP
from io import BytesIO
from time import gmtime, strftime
-import errno, os, sys, stat, time, pwd, grp, socket, struct
+import errno, os, sys, stat, time, socket, struct
-from bup import compat, vint, xstat
-from bup.compat import py_maj
+from bup import vint, xstat
from bup.drecurse import recursive_dirlist
from bup.helpers import add_error, mkdirp, log, is_superuser, format_filesize
from bup.io import path_msg
if _have_lchmod:
try:
os.lchmod(path, stat.S_IMODE(self.mode))
- except errno.ENOSYS: # Function not implemented
- pass
+ except OSError as e:
+ # - "Function not implemented"
+ # - "Operation not supported" might be generated by glibc
+ if e.errno in (errno.ENOSYS, errno.EOPNOTSUPP):
+ pass
+ else:
+ raise
elif not stat.S_ISLNK(self.mode):
os.chmod(path, stat.S_IMODE(self.mode))
try:
if stat.S_ISLNK(st.st_mode):
self.symlink_target = os.readlink(path)
+ # might have read a different link than the
+ # one that was in place when we did stat()
+ self.size = len(self.symlink_target)
except OSError as e:
add_error('readlink: %s' % e)
def from_path(path, statinfo=None, archive_path=None,
save_symlinks=True, hardlink_target=None,
- normalized=False):
+ normalized=False, after_stat=None):
# This function is also a test hook; see test-save-errors
"""Return the metadata associated with the path. When normalized is
true, return the metadata appropriate for a typical save, which
result = Metadata()
result.path = archive_path
st = statinfo or xstat.lstat(path)
+ if after_stat:
+ after_stat(path)
result._add_common(path, st)
if save_symlinks:
result._add_symlink_target(path, st)