SFTP: allow FXF_WRITE | FXF_TRUNC (#1050).
authordavid-sarah <david-sarah@jacaranda.org>
Wed, 19 May 2010 04:32:40 +0000 (21:32 -0700)
committerdavid-sarah <david-sarah@jacaranda.org>
Wed, 19 May 2010 04:32:40 +0000 (21:32 -0700)
src/allmydata/frontends/sftpd.py
src/allmydata/test/test_sftp.py

index d68eeca259e2b65d60eb4df6abc50dd6700be73c..68fb5192ed2d009793679cdd4457c3b7ea95a725 100644 (file)
@@ -657,7 +657,6 @@ class GeneralSFTPFile(PrefixingLogMixin):
 
         if (flags & FXF_TRUNC) or not filenode:
             # We're either truncating or creating the file, so we don't need the old contents.
-            assert flags & FXF_CREAT, flags
             self.consumer = OverwriteableFileConsumer(self.check_abort, 0, tempfile_maker)
             self.consumer.finish()
         else:
@@ -878,9 +877,6 @@ class SFTPUserHandler(ConchUser, PrefixingLogMixin):
                             "invalid file open flags: at least one of FXF_READ and FXF_WRITE must be set")
 
         if not (flags & FXF_CREAT):
-            if flags & FXF_TRUNC:
-                raise SFTPError(FX_BAD_MESSAGE,
-                                "invalid file open flags: FXF_TRUNC cannot be set without FXF_CREAT")
             if flags & FXF_EXCL:
                 raise SFTPError(FX_BAD_MESSAGE,
                                 "invalid file open flags: FXF_EXCL cannot be set without FXF_CREAT")
index 04c67ef77b519757683d2d60aeef897b6f13d6a1..eb9eb9ee2edb051828e905c13c6c7768413367c1 100644 (file)
@@ -534,9 +534,9 @@ class Handler(GridTestMixin, ShouldFailMixin, unittest.TestCase):
             self.shouldFailWithSFTPError(sftp.FX_NO_SUCH_FILE, "openFile '' WRITE|CREAT|TRUNC",
                                          self.handler.openFile, "", sftp.FXF_WRITE | sftp.FXF_CREAT | sftp.FXF_TRUNC, {}))
 
-        # TRUNC is not valid without CREAT
+        # TRUNC is not valid without CREAT if the file does not already exist
         d.addCallback(lambda ign:
-            self.shouldFailWithSFTPError(sftp.FX_BAD_MESSAGE, "openFile newfile WRITE|TRUNC",
+            self.shouldFailWithSFTPError(sftp.FX_NO_SUCH_FILE, "openFile newfile WRITE|TRUNC",
                                          self.handler.openFile, "newfile", sftp.FXF_WRITE | sftp.FXF_TRUNC, {}))
 
         # EXCL is not valid without CREAT
@@ -672,6 +672,20 @@ class Handler(GridTestMixin, ShouldFailMixin, unittest.TestCase):
         d.addCallback(lambda node: download_to_data(node))
         d.addCallback(lambda data: self.failUnlessReallyEqual(data, "01234567890123"))
 
+        # test WRITE | TRUNC without CREAT, when the file already exists
+        # This is invalid according to section 6.3 of the SFTP spec, but required for interoperability,
+        # since POSIX does allow O_WRONLY | O_TRUNC.
+        d.addCallback(lambda ign:
+                      self.handler.openFile("newfile", sftp.FXF_WRITE | sftp.FXF_TRUNC, {}))
+        def _write_trunc(wf):
+            d2 = wf.writeChunk(0, "01234")
+            d2.addCallback(lambda ign: wf.close())
+            return d2
+        d.addCallback(_write_trunc)
+        d.addCallback(lambda ign: self.root.get(u"newfile"))
+        d.addCallback(lambda node: download_to_data(node))
+        d.addCallback(lambda data: self.failUnlessReallyEqual(data, "01234"))
+
         # test EXCL flag
         d.addCallback(lambda ign:
                       self.handler.openFile("excl", sftp.FXF_WRITE | sftp.FXF_CREAT |
@@ -1033,4 +1047,4 @@ class Handler(GridTestMixin, ShouldFailMixin, unittest.TestCase):
             self.shouldFailWithSFTPError(sftp.FX_OP_UNSUPPORTED, "extendedRequest foo bar",
                                          self.handler.extendedRequest, "foo", "bar"))
 
-        return d
\ No newline at end of file
+        return d