Changeset 1682:ec059f9d9dc8


Ignore:
Timestamp:
Oct 28, 2017, 10:49:35 PM (14 months ago)
Author:
Stefan Schwarzer <sschwarzer@…>
Branch:
default
Message:
Handle infinite link chains in `isdir` and `isfile`

If `FTPHost.path.isdir` and `FTPHost.path.isfile` run into an infinite
link chain, return `False`, as the corresponding functions in
`os.path` do.

Before, `isdir` and `isfile` would raise a `PermanentError` with the
information that a recursive link chain was detected. This behavior,
in turn, led to a failure in `FTPHost.walk` (see ticket #107).

ticket: 107
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • ftputil/error.py

    r1606 r1682  
    112112    pass
    113113
     114class RecursiveLinksError(PermanentError):
     115    """Raised if an infinite link structure is detected."""
     116    pass
     117
    114118# Currently not used
    115119class SyncError(PermanentError):
  • ftputil/path.py

    r1680 r1682  
    138138            stat_result = self._host.stat(
    139139                            path, _exception_for_missing_path=False)
     140        except ftputil.error.RecursiveLinksError:
     141            return False
     142        except ftputil.error.RootDirError:
     143            return False
     144        else:
    140145            if stat_result is None:
     146                # Non-existent path
    141147                return False
    142148            else:
    143149                return stat.S_ISREG(stat_result.st_mode)
    144         except ftputil.error.RootDirError:
    145             return False
    146150
    147151    def isdir(self, path):
     
    160164            stat_result = self._host.stat(
    161165                            path, _exception_for_missing_path=False)
     166        except ftputil.error.RecursiveLinksError:
     167            return False
     168        except ftputil.error.RootDirError:
     169            return True
     170        else:
    162171            if stat_result is None:
     172                # Non-existent path
    163173                return False
    164174            else:
    165175                return stat.S_ISDIR(stat_result.st_mode)
    166         except ftputil.error.RootDirError:
    167             return True
    168176
    169177    def islink(self, path):
     
    177185            lstat_result = self._host.lstat(
    178186                             path, _exception_for_missing_path=False)
     187        except ftputil.error.RootDirError:
     188            return False
     189        else:
    179190            if lstat_result is None:
     191                # Non-existent path
    180192                return False
    181193            else:
    182194                return stat.S_ISLNK(lstat_result.st_mode)
    183         except ftputil.error.RootDirError:
    184             return False
    185195
    186196    def walk(self, top, func, arg):
  • ftputil/stat.py

    r1625 r1682  
    681681            if path in visited_paths:
    682682                # We had seen this path already.
    683                 raise ftputil.error.PermanentError(
     683                raise ftputil.error.RecursiveLinksError(
    684684                  "recursive link structure detected for remote path '{0}'".
    685685                  format(original_path))
  • test/mock_ftplib.py

    r1602 r1682  
    220220lrwxrwxrwx   1 45854    200            15 Jan 19  2002 bad_link -> python/bad_link
    221221drwxr-sr-x   2 45854    200           512 May  4  2000 dir with spaces
     222drwxr-sr-x   2 45854    200           512 May  4  2000 python
    222223drwxr-sr-x   2 45854    200           512 May  4  2000 file_name_test""",
    223224
  • test/test_path.py

    r1679 r1682  
    8686            host._dir("/home dir")
    8787
    88     def test_isdir_isfile_islink_with_exception(self):
    89         """Test failing `FTPHost._Path.isdir/isfile/islink`."""
     88    def test_isdir_isfile_islink_with_dir_failure(self):
     89        """
     90        Test failing `FTPHost._Path.isdir/isfile/islink` because of
     91        failing `_dir` call.
     92        """
    9093        host = test_base.ftp_host_factory(ftp_host_class=FailingFTPHost)
    9194        testdir = "/home/sschwarzer"
     
    99102        with pytest.raises(FTPOSError):
    100103            host.path.islink("index.html")
     104
     105    def test_isdir_isfile_with_infinite_link_chain(self):
     106        """
     107        Test if `isdir` and `isfile` return `False` if they encounter
     108        an infinite link chain.
     109        """
     110        host = test_base.ftp_host_factory()
     111        assert host.path.isdir("/home/bad_link") is False
     112        assert host.path.isfile("/home/bad_link") is False
    101113
    102114    def test_exists(self):
Note: See TracChangeset for help on using the changeset viewer.