Index: twisted/test/test_ftp.py
===================================================================
--- twisted/test/test_ftp.py	(revision 34577)
+++ twisted/test/test_ftp.py	(working copy)
@@ -2589,6 +2589,29 @@
         return self.assertFailure(d, ftp.FileNotFoundError)
 
 
+    def test_accessNotAllowed(self):
+        """
+        access should fail on a resource for which we can't list its content.
+        """
+        path = 'foo'
+        self.createDirectory(path)
+        self.root.child(path).chmod(000)
+        d = self.shell.access((path,))
+
+        def revert_permissions(result_or_failure):
+            """Folder permissions are reverted so that any clean function
+            will be allowed to remove the folder.
+            """
+            self.root.child(path).chmod(0700)
+            self.root.child(path).remove()
+            return result_or_failure
+
+        d.addBoth(revert_permissions)
+        return self.assertFailure(d, ftp.PermissionDeniedError)
+
+    if not os.name == 'posix':
+        test_accessNotAllowed.skip = "test_accessNotAllowed not supported"
+
     def test_openForReading(self):
         """
         Check that openForReading returns an object providing C{ftp.IReadFile}.
Index: twisted/protocols/ftp.py
===================================================================
--- twisted/protocols/ftp.py	(revision 34577)
+++ twisted/protocols/ftp.py	(working copy)
@@ -1674,6 +1674,12 @@
 
 
     def access(self, path):
+        """
+        See L{IFTPShell.access}.
+
+        If path doesn't exists, it returns L{FileNotFoundError}.
+        It checks path access by issuing a folder listing command.
+        """ 
         p = self._path(path)
         if not p.exists():
             # Again, win32 doesn't report a sane error after, so let's fail
