Skip to content

Commit

Permalink
Raise if remove a linked path ending with path separator
Browse files Browse the repository at this point in the history
- fixes #360
  • Loading branch information
mrbean-bremen committed Apr 4, 2018
1 parent c204eaa commit ae9b251
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 9 deletions.
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ The release versions are PyPi releases.
#### Infrastructure

#### Fixes
* `os.remove` shall raise if the argument ends with a path
separator ([#360](../../issues/360))
* `os.readlink` shall raise under Posix if the argument ends with a path
separator ([#359](../../issues/359))

Expand Down
22 changes: 16 additions & 6 deletions pyfakefs/fake_filesystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -2679,22 +2679,32 @@ def remove(self, path):
OSError: if path does not exist.
OSError: if removal failed.
"""
path = self.absnormpath(path)
if self.exists(path):
obj = self.resolve(path)
norm_path = self.absnormpath(path)
if self.exists(norm_path):
obj = self.resolve(norm_path)
if S_IFMT(obj.st_mode) == S_IFDIR:
link_obj = self.lresolve(path)
link_obj = self.lresolve(norm_path)
if S_IFMT(link_obj.st_mode) != S_IFLNK:
if self.is_windows_fs:
error = errno.EACCES
elif self.is_macos:
error = errno.EPERM
else:
error = errno.EISDIR
self.raise_os_error(error, path)
self.raise_os_error(error, norm_path)

norm_path = make_string_path(norm_path)
if path.endswith(self.path_separator):
if self.is_windows_fs:
error = errno.EACCES
elif self.is_macos:
error = errno.EPERM
else:
error = errno.ENOTDIR
self.raise_os_error(error, norm_path)

try:
self.remove_object(path)
self.remove_object(norm_path)
except IOError as exc:
self.raise_os_error(exc.errno, exc.filename)

Expand Down
24 changes: 22 additions & 2 deletions tests/fake_os_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -341,22 +341,42 @@ def test_lstat_trailing_sep(self):
self.assertEqual(stat, self.os.lstat(
self.base_path + self.path_separator() + self.path_separator()))

def test_link_ending_with_sep_posix(self):
def test_read_link_ending_with_sep_posix(self):
# regression test for #359
self.check_posix_only()
link_path = self.make_path('foo')
self.os.symlink(self.base_path, link_path)
self.assert_raises_os_error(errno.EINVAL,
self.os.readlink, link_path + self.os.sep)

def test_link_ending_with_sep_windows(self):
def test_read_link_ending_with_sep_windows(self):
self.check_windows_only()
self.skip_if_symlink_not_supported()
link_path = self.make_path('foo')
self.os.symlink(self.base_path, link_path)
self.assertEqual(self.base_path,
self.os.readlink(link_path + self.os.sep))

def check_remove_link_ending_with_sep(self, error_nr):
# regression test for #360
link_path = self.make_path('foo')
self.os.symlink(self.base_path, link_path)
self.assert_raises_os_error(error_nr,
self.os.remove, link_path + self.os.sep)

def test_remove_link_ending_with_sep_linux(self):
self.check_linux_only()
self.check_remove_link_ending_with_sep(errno.ENOTDIR)

def test_remove_link_ending_with_sep_macos(self):
self.check_macos_only()
self.check_remove_link_ending_with_sep(errno.EPERM)

def test_remove_link_ending_with_sep_windows(self):
self.check_windows_only()
self.skip_if_symlink_not_supported()
self.check_remove_link_ending_with_sep(errno.EACCES)

@unittest.skipIf(sys.version_info < (3, 3),
'file descriptor as path new in Python 3.3')
def test_lstat_uses_open_fd_as_path(self):
Expand Down
1 change: 0 additions & 1 deletion tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -392,4 +392,3 @@ def tearDown(self):
self.os.chdir(os.path.dirname(self.base_path))
shutil.rmtree(self.base_path, ignore_errors=True)
self.os.chdir(self.cwd)

0 comments on commit ae9b251

Please sign in to comment.