]> source.dussan.org Git - nextcloud-server.git/commitdiff
Disable part files for OC ext storage backend + s2s backend
authorVincent Petry <pvince81@owncloud.com>
Wed, 7 Jan 2015 20:21:51 +0000 (21:21 +0100)
committerVincent Petry <pvince81@owncloud.com>
Wed, 7 Jan 2015 20:21:51 +0000 (21:21 +0100)
When uploading files to an OC ext storage backend or when using server
to server sharing storage, part files aren't needed because the backend
already has its own part files and takes care of the final atomic rename
operation.

This also fixes issues when using two encrypted ownCloud instances where
one mounts the other either as external storage (ownCloud backend) or
through server to server sharing.

lib/private/connector/sabre/file.php

index 76ebe3ed9fe8b1ba09464c3b80e3eeaac3ba8e3d..cd05db8e12a9872daa0c8bdef62c1fb674849cbc 100644 (file)
@@ -74,8 +74,16 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements \Sabre\
                        return $this->createFileChunked($data);
                }
 
-               // mark file as partial while uploading (ignored by the scanner)
-               $partFilePath = $this->path . '.ocTransferId' . rand() . '.part';
+               list($storage, $internalPath) = $this->fileView->resolvePath($this->path);
+               $needsPartFile = $this->needsPartFile($storage);
+
+               if ($needsPartFile) {
+                       // mark file as partial while uploading (ignored by the scanner)
+                       $partFilePath = $this->path . '.ocTransferId' . rand() . '.part';
+               } else {
+                       // upload file directly as the final path
+                       $partFilePath = $this->path;
+               }
 
                try {
                        $putOkay = $this->fileView->file_put_contents($partFilePath, $data);
@@ -123,19 +131,21 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements \Sabre\
                                }
                        }
 
-                       // rename to correct path
-                       try {
-                               $renameOkay = $this->fileView->rename($partFilePath, $this->path);
-                               $fileExists = $this->fileView->file_exists($this->path);
-                               if ($renameOkay === false || $fileExists === false) {
-                                       \OC_Log::write('webdav', '\OC\Files\Filesystem::rename() failed', \OC_Log::ERROR);
-                                       $this->fileView->unlink($partFilePath);
-                                       throw new \Sabre\DAV\Exception('Could not rename part file to final file');
+                       if ($needsPartFile) {
+                               // rename to correct path
+                               try {
+                                       $renameOkay = $this->fileView->rename($partFilePath, $this->path);
+                                       $fileExists = $this->fileView->file_exists($this->path);
+                                       if ($renameOkay === false || $fileExists === false) {
+                                               \OC_Log::write('webdav', '\OC\Files\Filesystem::rename() failed', \OC_Log::ERROR);
+                                               $this->fileView->unlink($partFilePath);
+                                               throw new \Sabre\DAV\Exception('Could not rename part file to final file');
+                                       }
+                               }
+                               catch (\OCP\Files\LockNotAcquiredException $e) {
+                                       // the file is currently being written to by another process
+                                       throw new OC_Connector_Sabre_Exception_FileLocked($e->getMessage(), $e->getCode(), $e);
                                }
-                       }
-                       catch (\OCP\Files\LockNotAcquiredException $e) {
-                               // the file is currently being written to by another process
-                               throw new OC_Connector_Sabre_Exception_FileLocked($e->getMessage(), $e->getCode(), $e);
                        }
 
                        // allow sync clients to send the mtime along in a header
@@ -267,23 +277,31 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements \Sabre\
                }
 
                if ($chunk_handler->isComplete()) {
+                       list($storage, $internalPath) = $this->fileView->resolvePath($path);
+                       $needsPartFile = $this->needsPartFile($storage);
 
                        try {
-                               // we first assembly the target file as a part file
-                               $partFile = $path . '/' . $info['name'] . '.ocTransferId' . $info['transferid'] . '.part';
-                               $chunk_handler->file_assemble($partFile);
-
-                               // here is the final atomic rename
-                               $targetPath = $path . '/' . $info['name'];
-                               $renameOkay = $this->fileView->rename($partFile, $targetPath);
-                               $fileExists = $this->fileView->file_exists($targetPath);
-                               if ($renameOkay === false || $fileExists === false) {
-                                       \OC_Log::write('webdav', '\OC\Files\Filesystem::rename() failed', \OC_Log::ERROR);
-                                       // only delete if an error occurred and the target file was already created
-                                       if ($fileExists) {
-                                               $this->fileView->unlink($targetPath);
+                               if ($needsPartFile) {
+                                       // we first assembly the target file as a part file
+                                       $partFile = $path . '/' . $info['name'] . '.ocTransferId' . $info['transferid'] . '.part';
+                                       $chunk_handler->file_assemble($partFile);
+
+                                       // here is the final atomic rename
+                                       $targetPath = $path . '/' . $info['name'];
+                                       $renameOkay = $this->fileView->rename($partFile, $targetPath);
+                                       $fileExists = $this->fileView->file_exists($targetPath);
+                                       if ($renameOkay === false || $fileExists === false) {
+                                               \OC_Log::write('webdav', '\OC\Files\Filesystem::rename() failed', \OC_Log::ERROR);
+                                               // only delete if an error occurred and the target file was already created
+                                               if ($fileExists) {
+                                                       $this->fileView->unlink($targetPath);
+                                               }
+                                               throw new \Sabre\DAV\Exception('Could not rename part file assembled from chunks');
                                        }
-                                       throw new \Sabre\DAV\Exception('Could not rename part file assembled from chunks');
+                               } else {
+                                       // assemble directly into the final file
+                                       $partFile = $path . '/' . $info['name'];
+                                       $chunk_handler->file_assemble($partFile);
                                }
 
                                // allow sync clients to send the mtime along in a header
@@ -303,4 +321,19 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements \Sabre\
 
                return null;
        }
+
+       /**
+        * Returns whether a part file is needed for the given storage
+        * or whether the file can be assembled/uploaded directly on the
+        * target storage.
+        *
+        * @param \OCP\Files\Storage $storage storage to check
+        * @param bool true if the storage needs part file handling
+        */
+       private function needsPartFile($storage) {
+               // TODO: in the future use ChunkHandler provided by storage
+               // and/or add method on Storage called "needsPartFile()"
+               return !$storage->instanceOfStorage('OCA\Files_Sharing\External\Storage') &&
+                       !$storage->instanceOfStorage('OC\Files\Storage\OwnCloud');
+       }       
 }