diff --git a/src/borg/archive.py b/src/borg/archive.py index 212fd3bfa..86e8a62e0 100644 --- a/src/borg/archive.py +++ b/src/borg/archive.py @@ -239,7 +239,9 @@ def OsOpen(*, flags, path=None, parent_fd=None, name=None, noatime=False, op='op try: yield fd finally: - os.close(fd) + # On windows fd is None for directories. + if fd is not None: + os.close(fd) class DownloadPipeline: diff --git a/src/borg/archiver.py b/src/borg/archiver.py index 8fb6439d5..55ef22cde 100644 --- a/src/borg/archiver.py +++ b/src/borg/archiver.py @@ -625,8 +625,10 @@ class Archiver: elif stat.S_ISDIR(st.st_mode): with OsOpen(path=path, parent_fd=parent_fd, name=name, flags=flags_dir, noatime=True, op='dir_open') as child_fd: - with backup_io('fstat'): - st = stat_update_check(st, os.fstat(child_fd)) + # child_fd is None for directories on windows, in that case a race condition check is not possible. + if child_fd is not None: + with backup_io('fstat'): + st = stat_update_check(st, os.fstat(child_fd)) if recurse: tag_names = dir_is_tagged(path, exclude_caches, exclude_if_present) if tag_names: diff --git a/src/borg/helpers/fs.py b/src/borg/helpers/fs.py index cb3f0ba8e..eecff277a 100644 --- a/src/borg/helpers/fs.py +++ b/src/borg/helpers/fs.py @@ -8,6 +8,7 @@ import sys import textwrap from .process import prepare_subprocess_env +from ..platformflags import is_win32 from ..constants import * # NOQA @@ -230,6 +231,9 @@ def os_open(*, flags, path=None, parent_fd=None, name=None, noatime=False): fname = name # use name relative to parent_fd else: fname, parent_fd = path, None # just use the path + if is_win32 and os.path.isdir(fname): + # Directories can not be opened on Windows. + return None _flags_normal = flags if noatime: _flags_noatime = _flags_normal | O_('NOATIME')