public function testMoveCrossStorage() { $storage2 = new Temporary(array()); $cache2 = $storage2->getCache(); Filesystem::mount($storage2, array(), '/bar'); $this->storage->file_put_contents('foo.txt', 'qwerty'); $this->updater->update('foo.txt'); $this->assertTrue($this->cache->inCache('foo.txt')); $this->assertFalse($cache2->inCache('bar.txt')); $cached = $this->cache->get('foo.txt'); // "rename" $storage2->file_put_contents('bar.txt', 'qwerty'); $this->storage->unlink('foo.txt'); $this->assertTrue($this->cache->inCache('foo.txt')); $this->assertFalse($cache2->inCache('bar.txt')); $this->updater->rename('foo.txt', 'bar/bar.txt'); $this->assertFalse($this->cache->inCache('foo.txt')); $this->assertTrue($cache2->inCache('bar.txt')); $cachedTarget = $cache2->get('bar.txt'); $this->assertEquals($cached['mtime'], $cachedTarget['mtime']); $this->assertEquals($cached['size'], $cachedTarget['size']); $this->assertEquals($cached['etag'], $cachedTarget['etag']); $this->assertEquals($cached['fileid'], $cachedTarget['fileid']); }
public function testMoveDisabled() { $this->storage->file_put_contents('foo.txt', 'qwerty'); $this->updater->update('foo.txt'); $this->assertTrue($this->cache->inCache('foo.txt')); $this->assertFalse($this->cache->inCache('bar.txt')); $cached = $this->cache->get('foo.txt'); $this->storage->rename('foo.txt', 'bar.txt'); $this->assertTrue($this->cache->inCache('foo.txt')); $this->assertFalse($this->cache->inCache('bar.txt')); $this->updater->disable(); $this->updater->rename('foo.txt', 'bar.txt'); $this->assertTrue($this->cache->inCache('foo.txt')); $this->assertFalse($this->cache->inCache('bar.txt')); }
public function testMove() { $this->storage->file_put_contents('foo.txt', 'qwerty'); $this->updater->update('foo.txt'); $this->assertTrue($this->cache->inCache('foo.txt')); $this->assertFalse($this->cache->inCache('bar.txt')); $cached = $this->cache->get('foo.txt'); $this->storage->rename('foo.txt', 'bar.txt'); $this->assertTrue($this->cache->inCache('foo.txt')); $this->assertFalse($this->cache->inCache('bar.txt')); $this->updater->rename('foo.txt', 'bar.txt'); $this->assertFalse($this->cache->inCache('foo.txt')); $this->assertTrue($this->cache->inCache('bar.txt')); $cachedTarget = $this->cache->get('bar.txt'); $this->assertEquals($cached['etag'], $cachedTarget['etag']); $this->assertEquals($cached['mtime'], $cachedTarget['mtime']); $this->assertEquals($cached['size'], $cachedTarget['size']); $this->assertEquals($cached['fileid'], $cachedTarget['fileid']); }
/** * Rename/move a file or folder from the source path to target path. * * @param string $path1 source path * @param string $path2 target path * * @return bool|mixed */ public function rename($path1, $path2) { $postFix1 = substr($path1, -1, 1) === '/' ? '/' : ''; $postFix2 = substr($path2, -1, 1) === '/' ? '/' : ''; $absolutePath1 = Filesystem::normalizePath($this->getAbsolutePath($path1)); $absolutePath2 = Filesystem::normalizePath($this->getAbsolutePath($path2)); if (Filesystem::isValidPath($path2) and Filesystem::isValidPath($path1) and !Filesystem::isFileBlacklisted($path2)) { $path1 = $this->getRelativePath($absolutePath1); $path2 = $this->getRelativePath($absolutePath2); $exists = $this->file_exists($path2); if ($path1 == null or $path2 == null) { return false; } $run = true; if ($this->shouldEmitHooks() && (Cache\Scanner::isPartialFile($path1) && !Cache\Scanner::isPartialFile($path2))) { // if it was a rename from a part file to a regular file it was a write and not a rename operation $this->emit_file_hooks_pre($exists, $path2, $run); } elseif ($this->shouldEmitHooks()) { \OC_Hook::emit(Filesystem::CLASSNAME, Filesystem::signal_rename, array(Filesystem::signal_param_oldpath => $this->getHookPath($path1), Filesystem::signal_param_newpath => $this->getHookPath($path2), Filesystem::signal_param_run => &$run)); } if ($run) { $this->verifyPath(dirname($path2), basename($path2)); $mp1 = $this->getMountPoint($path1 . $postFix1); $mp2 = $this->getMountPoint($path2 . $postFix2); $manager = Filesystem::getMountManager(); $mount = $manager->find($absolutePath1 . $postFix1); $storage1 = $mount->getStorage(); $internalPath1 = $mount->getInternalPath($absolutePath1 . $postFix1); list($storage2, $internalPath2) = Filesystem::resolvePath($absolutePath2 . $postFix2); if ($internalPath1 === '' and $mount instanceof MoveableMount) { if ($this->isTargetAllowed($absolutePath2)) { /** * @var \OC\Files\Mount\MountPoint | \OC\Files\Mount\MoveableMount $mount */ $sourceMountPoint = $mount->getMountPoint(); $result = $mount->moveMount($absolutePath2); $manager->moveMount($sourceMountPoint, $mount->getMountPoint()); } else { $result = false; } } elseif ($mp1 == $mp2) { if ($storage1) { $result = $storage1->rename($internalPath1, $internalPath2); } else { $result = false; } } else { if ($this->is_dir($path1)) { $result = $this->copy($path1, $path2, true); if ($result === true) { $result = $storage1->rmdir($internalPath1); } } else { $source = $this->fopen($path1 . $postFix1, 'r'); $target = $this->fopen($path2 . $postFix2, 'w'); list(, $result) = \OC_Helper::streamCopy($source, $target); if ($result !== false) { $this->touch($path2, $this->filemtime($path1)); } // close open handle - especially $source is necessary because unlink below will // throw an exception on windows because the file is locked fclose($source); fclose($target); if ($result !== false) { $result &= $storage1->unlink($internalPath1); } else { // delete partially written target file $storage2->unlink($internalPath2); // delete cache entry that was created by fopen $storage2->getCache()->remove($internalPath2); } } } if (Cache\Scanner::isPartialFile($path1) && !Cache\Scanner::isPartialFile($path2) && $result !== false) { // if it was a rename from a part file to a regular file it was a write and not a rename operation $this->updater->update($path2); if ($this->shouldEmitHooks()) { $this->emit_file_hooks_post($exists, $path2); } } elseif ($result) { $this->updater->rename($path1, $path2); if ($this->shouldEmitHooks($path1) and $this->shouldEmitHooks($path2)) { \OC_Hook::emit(Filesystem::CLASSNAME, Filesystem::signal_post_rename, array(Filesystem::signal_param_oldpath => $this->getHookPath($path1), Filesystem::signal_param_newpath => $this->getHookPath($path2))); } } return $result; } else { return false; } } else { return false; } }
/** * Rename/move a file or folder from the source path to target path. * * @param string $path1 source path * @param string $path2 target path * * @return bool|mixed */ public function rename($path1, $path2) { $absolutePath1 = Filesystem::normalizePath($this->getAbsolutePath($path1)); $absolutePath2 = Filesystem::normalizePath($this->getAbsolutePath($path2)); $result = false; if (Filesystem::isValidPath($path2) and Filesystem::isValidPath($path1) and !Filesystem::isFileBlacklisted($path2)) { $path1 = $this->getRelativePath($absolutePath1); $path2 = $this->getRelativePath($absolutePath2); $exists = $this->file_exists($path2); if ($path1 == null or $path2 == null) { return false; } $this->lockFile($path1, ILockingProvider::LOCK_SHARED, true); try { $this->lockFile($path2, ILockingProvider::LOCK_SHARED, true); } catch (LockedException $e) { $this->unlockFile($path1, ILockingProvider::LOCK_SHARED); throw $e; } $run = true; if ($this->shouldEmitHooks($path1) && (Cache\Scanner::isPartialFile($path1) && !Cache\Scanner::isPartialFile($path2))) { // if it was a rename from a part file to a regular file it was a write and not a rename operation $this->emit_file_hooks_pre($exists, $path2, $run); } elseif ($this->shouldEmitHooks($path1)) { \OC_Hook::emit(Filesystem::CLASSNAME, Filesystem::signal_rename, array(Filesystem::signal_param_oldpath => $this->getHookPath($path1), Filesystem::signal_param_newpath => $this->getHookPath($path2), Filesystem::signal_param_run => &$run)); } if ($run) { $this->verifyPath(dirname($path2), basename($path2)); $manager = Filesystem::getMountManager(); $mount1 = $this->getMount($path1); $mount2 = $this->getMount($path2); $storage1 = $mount1->getStorage(); $storage2 = $mount2->getStorage(); $internalPath1 = $mount1->getInternalPath($absolutePath1); $internalPath2 = $mount2->getInternalPath($absolutePath2); $this->changeLock($path1, ILockingProvider::LOCK_EXCLUSIVE, true); $this->changeLock($path2, ILockingProvider::LOCK_EXCLUSIVE, true); if ($internalPath1 === '' and $mount1 instanceof MoveableMount) { if ($this->isTargetAllowed($absolutePath2)) { /** * @var \OC\Files\Mount\MountPoint | \OC\Files\Mount\MoveableMount $mount1 */ $sourceMountPoint = $mount1->getMountPoint(); $result = $mount1->moveMount($absolutePath2); $manager->moveMount($sourceMountPoint, $mount1->getMountPoint()); } else { $result = false; } // moving a file/folder within the same mount point } elseif ($storage1 == $storage2) { if ($storage1) { $result = $storage1->rename($internalPath1, $internalPath2); } else { $result = false; } // moving a file/folder between storages (from $storage1 to $storage2) } else { $result = $storage2->moveFromStorage($storage1, $internalPath1, $internalPath2); } if (Cache\Scanner::isPartialFile($path1) && !Cache\Scanner::isPartialFile($path2) && $result !== false) { // if it was a rename from a part file to a regular file it was a write and not a rename operation $this->updater->update($path2); } else { if ($result) { if ($internalPath1 !== '') { // dont do a cache update for moved mounts $this->updater->rename($path1, $path2); } else { // only do etag propagation $this->getUpdater()->getPropagator()->addChange($path1); $this->getUpdater()->getPropagator()->addChange($path2); $this->getUpdater()->getPropagator()->propagateChanges(); } } } $this->changeLock($path1, ILockingProvider::LOCK_SHARED, true); $this->changeLock($path2, ILockingProvider::LOCK_SHARED, true); if (Cache\Scanner::isPartialFile($path1) && !Cache\Scanner::isPartialFile($path2) && $result !== false) { if ($this->shouldEmitHooks()) { $this->emit_file_hooks_post($exists, $path2); } } elseif ($result) { if ($this->shouldEmitHooks($path1) and $this->shouldEmitHooks($path2)) { \OC_Hook::emit(Filesystem::CLASSNAME, Filesystem::signal_post_rename, array(Filesystem::signal_param_oldpath => $this->getHookPath($path1), Filesystem::signal_param_newpath => $this->getHookPath($path2))); } } } $this->unlockFile($path1, ILockingProvider::LOCK_SHARED, true); $this->unlockFile($path2, ILockingProvider::LOCK_SHARED, true); } return $result; }