From e072a52b6c4063ce9bcfe7f893ef28dba7fcb616 Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Thu, 18 Feb 2016 23:01:55 +0100 Subject: [PATCH] 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) --- borg/archive.py | 55 +++++++++++++------------------------------------ 1 file changed, 14 insertions(+), 41 deletions(-) diff --git a/borg/archive.py b/borg/archive.py index 99c920644..8d6818aa3 100644 --- a/borg/archive.py +++ b/borg/archive.py @@ -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: