Merge pull request #678 from ThomasWaldmann/fix-open

fix _open_rb noatime handling, fixes #657
This commit is contained in:
TW 2016-02-20 13:29:36 +01:00
commit 3d0e51115c
1 changed files with 14 additions and 41 deletions

View File

@ -41,6 +41,9 @@ ITEMS_CHUNKER_PARAMS = (12, 16, 14, HASH_WINDOW_SIZE)
has_lchmod = hasattr(os, 'lchmod')
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:
@ -544,7 +547,7 @@ Number of files: {0.stats.nfiles}'''.format(
item = {b'path': safe_path}
# Only chunkify the file if needed
if chunks is None:
fh = Archive._open_rb(path, st)
fh = Archive._open_rb(path)
with os.fdopen(fh, 'rb') as fd:
chunks = []
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)
@staticmethod
def _open_rb(path, st):
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:
fd = os.open(p, flags_noatime)
except PermissionError:
# Was this EPERM due to the O_NOATIME flag?
fd = os.open(p, flags_normal)
# Yes, it was -- otherwise the above line would have thrown
# another exception.
nonlocal euid
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)
def _open_rb(path):
try:
# 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:
if flags_noatime == flags_normal:
# we do not have O_NOATIME, no need to try again:
raise
# Was this EPERM due to the O_NOATIME flag? Try again without it:
return os.open(path, flags_normal)
# this set must be kept complete, otherwise the RobustUnpacker might malfunction: