Skip to content

Commit c662cc9

Browse files
[FIX] fs_storage: Resolve rooted_dir sub path is inside path virtually
Before this fix, a FileNotFoundError would ocassionally arise when 'os.getcwd()' is called due to the rooted_dir _join method to check whether the sub path is part of the parent path. This is probably caused by the number and/or combination of workers and threads and the transactions to the FS storage, having race issues. After this commit, the sub path is checked if it is contained inside the parent path virtually via posixpath and pathlib modules avoiding 'os.getcwd()' calls and running into this possible race condition.
1 parent b50f468 commit c662cc9

1 file changed

Lines changed: 14 additions & 12 deletions

File tree

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
# Copyright 2023 ACSONE SA/NV (https://www.acsone.eu).
22
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
33

4-
import os
4+
import posixpath
5+
from pathlib import PurePosixPath
56

67
from fsspec.implementations.dirfs import DirFileSystem
7-
from fsspec.implementations.local import make_path_posix
88
from fsspec.registry import register_implementation
99

1010

@@ -20,18 +20,20 @@ class RootedDirFileSystem(DirFileSystem):
2020
"""
2121

2222
def _join(self, path):
23-
path = super()._join(path)
24-
# Ensure that the path is a subpath of the root path by resolving
25-
# any relative paths.
26-
# Since the path separator is not always the same on all systems,
27-
# we need to normalize the path separator.
28-
path_posix = os.path.normpath(make_path_posix(path))
29-
root_posix = os.path.normpath(make_path_posix(self.path))
30-
if not path_posix.startswith(root_posix):
23+
joined = super()._join(path)
24+
25+
root = PurePosixPath(self.path).as_posix()
26+
rnorm = posixpath.normpath(root)
27+
28+
jnorm = posixpath.normpath(joined or ".")
29+
30+
if not (jnorm == rnorm or jnorm.startswith(rnorm + "/")):
3131
raise PermissionError(
32-
"Path %s is not a subpath of the root path %s" % (path, self.path)
32+
f"Path {path!r} resolves to {jnorm!r} which is outside "
33+
f"the root path {rnorm!r}"
3334
)
34-
return path
35+
36+
return joined
3537

3638

3739
register_implementation("rooted_dir", RootedDirFileSystem)

0 commit comments

Comments
 (0)