diff --git a/src/allmydata/_auto_deps.py b/src/allmydata/_auto_deps.py index 3c00f61d3..a42bc17b8 100644 --- a/src/allmydata/_auto_deps.py +++ b/src/allmydata/_auto_deps.py @@ -110,10 +110,12 @@ if sys.platform == "win32": # which includes the fix to . # * The SFTP frontend depends on Twisted 11.0.0 to fix the SSH server # rekeying bug + # * The FTP frontend depends on Twisted >=11.1.0 for + # filepath.Permissions # * We don't want Twisted >= 12.2.0 to avoid a dependency of its endpoints # code on pywin32. # - "Twisted >= 11.0.0, <= 12.1.0", + "Twisted >= 11.1.0, <= 12.1.0", # * We need Nevow >= 0.9.33 to avoid a bug in Nevow's setup.py # which imported twisted at setup time. diff --git a/src/allmydata/frontends/ftpd.py b/src/allmydata/frontends/ftpd.py index 9922a86ad..9791b813a 100644 --- a/src/allmydata/frontends/ftpd.py +++ b/src/allmydata/frontends/ftpd.py @@ -6,6 +6,7 @@ from twisted.application import service, strports from twisted.internet import defer from twisted.internet.interfaces import IConsumer from twisted.cred import portal +from twisted.python import filepath from twisted.protocols import ftp from allmydata.interfaces import IDirectoryNode, ExistingChildError, \ @@ -61,6 +62,17 @@ class WriteFile: class NoParentError(Exception): pass +# filepath.Permissions was added in Twisted-11.1.0, which we require. Twisted +# <15.0.0 expected an int, and only does '&' on it. Twisted >=15.0.0 expects +# a filepath.Permissions. This satisfies both. + +class IntishPermissions(filepath.Permissions): + def __init__(self, statModeInt): + self._tahoe_statModeInt = statModeInt + filepath.Permissions.__init__(self, statModeInt) + def __and__(self, other): + return self._tahoe_statModeInt & other + class Handler: implements(ftp.IFTPShell) def __init__(self, client, rootnode, username, convergence): @@ -200,7 +212,12 @@ class Handler: elif key == "directory": value = isdir elif key == "permissions": - value = 0600 + # Twisted-14.0.2 (and earlier) expected an int, and used it + # in a rendering function that did (mode & NUMBER). + # Twisted-15.0.0 expects a + # twisted.python.filepath.Permissions , and calls its + # .shorthand() method. This provides both. + value = IntishPermissions(0600) elif key == "hardlinks": value = 1 elif key == "modified": diff --git a/src/allmydata/test/test_ftp.py b/src/allmydata/test/test_ftp.py index c98a32096..9457e540a 100644 --- a/src/allmydata/test/test_ftp.py +++ b/src/allmydata/test/test_ftp.py @@ -93,12 +93,12 @@ class Handler(GridTestMixin, ReallyEqualMixin, unittest.TestCase): expected_root = [ ('loop', - [0, True, 0600, 1, self.FALL_OF_BERLIN_WALL, 'alice', 'alice', '??']), + [0, True, ftpd.IntishPermissions(0600), 1, self.FALL_OF_BERLIN_WALL, 'alice', 'alice', '??']), ('immutable', - [23, False, 0600, 1, self.TURN_OF_MILLENIUM, 'alice', 'alice', '??']), + [23, False, ftpd.IntishPermissions(0600), 1, self.TURN_OF_MILLENIUM, 'alice', 'alice', '??']), ('mutable', # timestamp should be 0 if no timestamp metadata is present - [0, False, 0600, 1, 0, 'alice', 'alice', '??'])] + [0, False, ftpd.IntishPermissions(0600), 1, 0, 'alice', 'alice', '??'])] d.addCallback(lambda root: self._compareDirLists(root, expected_root))