mirror of https://github.com/borgbackup/borg.git
fix _open_rb noatime handling, fixes #657
(not tested by me for the #657 scenario, but at least all our unit tests, including the atime test, worked)
This commit is contained in:
parent
8c083c737e
commit
e072a52b6c
|
@ -41,6 +41,9 @@ ITEMS_CHUNKER_PARAMS = (12, 16, 14, HASH_WINDOW_SIZE)
|
||||||
has_lchmod = hasattr(os, 'lchmod')
|
has_lchmod = hasattr(os, 'lchmod')
|
||||||
has_lchflags = hasattr(os, 'lchflags')
|
has_lchflags = hasattr(os, 'lchflags')
|
||||||
|
|
||||||
|
flags_normal = os.O_RDONLY | getattr(os, 'O_BINARY', 0)
|
||||||
|
flags_noatime = flags_normal | getattr(os, 'O_NOATIME', 0)
|
||||||
|
|
||||||
|
|
||||||
class DownloadPipeline:
|
class DownloadPipeline:
|
||||||
|
|
||||||
|
@ -544,7 +547,7 @@ Number of files: {0.stats.nfiles}'''.format(
|
||||||
item = {b'path': safe_path}
|
item = {b'path': safe_path}
|
||||||
# Only chunkify the file if needed
|
# Only chunkify the file if needed
|
||||||
if chunks is None:
|
if chunks is None:
|
||||||
fh = Archive._open_rb(path, st)
|
fh = Archive._open_rb(path)
|
||||||
with os.fdopen(fh, 'rb') as fd:
|
with os.fdopen(fh, 'rb') as fd:
|
||||||
chunks = []
|
chunks = []
|
||||||
for chunk in self.chunker.chunkify(fd, fh):
|
for chunk in self.chunker.chunkify(fd, fh):
|
||||||
|
@ -566,46 +569,16 @@ Number of files: {0.stats.nfiles}'''.format(
|
||||||
yield Archive(repository, key, manifest, name, cache=cache)
|
yield Archive(repository, key, manifest, name, cache=cache)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _open_rb(path, st):
|
def _open_rb(path):
|
||||||
flags_normal = os.O_RDONLY | getattr(os, 'O_BINARY', 0)
|
|
||||||
flags_noatime = flags_normal | getattr(os, 'O_NOATIME', 0)
|
|
||||||
euid = None
|
|
||||||
|
|
||||||
def open_simple(p, s):
|
|
||||||
return os.open(p, flags_normal)
|
|
||||||
|
|
||||||
def open_noatime(p, s):
|
|
||||||
return os.open(p, flags_noatime)
|
|
||||||
|
|
||||||
def open_noatime_if_owner(p, s):
|
|
||||||
if euid == 0 or s.st_uid == euid:
|
|
||||||
# we are root or owner of file
|
|
||||||
return open_noatime(p, s)
|
|
||||||
else:
|
|
||||||
return open_simple(p, s)
|
|
||||||
|
|
||||||
def open_noatime_with_fallback(p, s):
|
|
||||||
try:
|
try:
|
||||||
fd = os.open(p, flags_noatime)
|
# if we have O_NOATIME, this likely will succeed if we are root or owner of file:
|
||||||
|
return os.open(path, flags_noatime)
|
||||||
except PermissionError:
|
except PermissionError:
|
||||||
# Was this EPERM due to the O_NOATIME flag?
|
if flags_noatime == flags_normal:
|
||||||
fd = os.open(p, flags_normal)
|
# we do not have O_NOATIME, no need to try again:
|
||||||
# Yes, it was -- otherwise the above line would have thrown
|
raise
|
||||||
# another exception.
|
# Was this EPERM due to the O_NOATIME flag? Try again without it:
|
||||||
nonlocal euid
|
return os.open(path, flags_normal)
|
||||||
euid = os.geteuid()
|
|
||||||
# So in future, let's check whether the file is owned by us
|
|
||||||
# before attempting to use O_NOATIME.
|
|
||||||
Archive._open_rb = open_noatime_if_owner
|
|
||||||
return fd
|
|
||||||
|
|
||||||
if flags_noatime != flags_normal:
|
|
||||||
# Always use O_NOATIME version.
|
|
||||||
Archive._open_rb = open_noatime_with_fallback
|
|
||||||
else:
|
|
||||||
# Always use non-O_NOATIME version.
|
|
||||||
Archive._open_rb = open_simple
|
|
||||||
return Archive._open_rb(path, st)
|
|
||||||
|
|
||||||
|
|
||||||
# this set must be kept complete, otherwise the RobustUnpacker might malfunction:
|
# this set must be kept complete, otherwise the RobustUnpacker might malfunction:
|
||||||
|
|
Loading…
Reference in New Issue