chore: move streamCopy implementation from OC_Helper to OCP\Files

The function was already there but called the legacy version.
So moved the implementation and migrated all usages of it.
Sadly the interface was slightly different so adjusted it to be
compatible with both legacy and the OCP one.

Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
This commit is contained in:
Ferdinand Thiessen 2025-05-16 00:07:33 +02:00
parent 12fdcd0826
commit 01db539d0a
No known key found for this signature in database
GPG key ID: 45FAE7268762B400
11 changed files with 66 additions and 41 deletions

View file

@ -19,6 +19,7 @@ use OCA\DAV\Connector\Sabre\Exception\Forbidden as DAVForbiddenException;
use OCA\DAV\Connector\Sabre\Exception\UnsupportedMediaType;
use OCP\App\IAppManager;
use OCP\Encryption\Exceptions\GenericEncryptionException;
use OCP\Files;
use OCP\Files\EntityTooLargeException;
use OCP\Files\FileInfo;
use OCP\Files\ForbiddenException;
@ -229,7 +230,7 @@ class File extends Node implements IFile {
// because we have no clue about the cause we can only throw back a 500/Internal Server Error
throw new Exception($this->l10n->t('Could not write file contents'));
}
[$count, $result] = \OC_Helper::streamCopy($data, $target);
[$count, $result] = Files::streamCopy($data, $target, true);
fclose($target);
}

View file

@ -23,6 +23,7 @@ use OCA\Files_Versions\Versions\IVersionManager;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\Command\IBus;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files;
use OCP\Files\FileInfo;
use OCP\Files\Folder;
use OCP\Files\IMimeTypeDetector;
@ -416,10 +417,12 @@ class Storage {
try {
// TODO add a proper way of overwriting a file while maintaining file ids
if ($storage1->instanceOfStorage('\OC\Files\ObjectStore\ObjectStoreStorage') || $storage2->instanceOfStorage('\OC\Files\ObjectStore\ObjectStoreStorage')) {
if ($storage1->instanceOfStorage(\OC\Files\ObjectStore\ObjectStoreStorage::class)
|| $storage2->instanceOfStorage(\OC\Files\ObjectStore\ObjectStoreStorage::class)
) {
$source = $storage1->fopen($internalPath1, 'r');
$target = $storage2->fopen($internalPath2, 'w');
[, $result] = \OC_Helper::streamCopy($source, $target);
[, $result] = Files::streamCopy($source, $target, true);
fclose($source);
fclose($target);

View file

@ -675,6 +675,12 @@
</ParamNameMismatch>
</file>
<file src="apps/dav/lib/Connector/Sabre/File.php">
<DeprecatedClass>
<code><![CDATA[Files::streamCopy($data, $target, true)]]></code>
</DeprecatedClass>
<DeprecatedMethod>
<code><![CDATA[Files::streamCopy($data, $target, true)]]></code>
</DeprecatedMethod>
<LessSpecificReturnStatement>
<code><![CDATA[$this->node]]></code>
</LessSpecificReturnStatement>
@ -1965,14 +1971,13 @@
</file>
<file src="apps/files_versions/lib/Storage.php">
<DeprecatedClass>
<code><![CDATA[Files::streamCopy($source, $target, true)]]></code>
<code><![CDATA[\OC_Util::setupFS($uid)]]></code>
</DeprecatedClass>
<DeprecatedMethod>
<code><![CDATA[Files::streamCopy($source, $target, true)]]></code>
<code><![CDATA[dispatch]]></code>
</DeprecatedMethod>
<RedundantCondition>
<code><![CDATA[$storage1->instanceOfStorage('\OC\Files\ObjectStore\ObjectStoreStorage')]]></code>
</RedundantCondition>
</file>
<file src="apps/oauth2/lib/Controller/OauthApiController.php">
<NoInterfaceProperties>

View file

@ -19,6 +19,7 @@ use OC\Files\ObjectStore\ObjectStoreStorage;
use OC\Files\Storage\Wrapper\Encryption;
use OC\Files\Storage\Wrapper\Jail;
use OC\Files\Storage\Wrapper\Wrapper;
use OCP\Files;
use OCP\Files\Cache\ICache;
use OCP\Files\Cache\IPropagator;
use OCP\Files\Cache\IScanner;
@ -205,7 +206,7 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage,
} else {
$sourceStream = $this->fopen($source, 'r');
$targetStream = $this->fopen($target, 'w');
[, $result] = \OC_Helper::streamCopy($sourceStream, $targetStream);
[, $result] = Files::streamCopy($sourceStream, $targetStream, true);
if (!$result) {
Server::get(LoggerInterface::class)->warning("Failed to write data while copying $source to $target");
}
@ -734,7 +735,7 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage,
throw new GenericFileException("Failed to open $path for writing");
}
try {
[$count, $result] = \OC_Helper::streamCopy($stream, $target);
[$count, $result] = Files::streamCopy($stream, $target, true);
if (!$result) {
throw new GenericFileException('Failed to copy stream');
}

View file

@ -7,6 +7,8 @@
*/
namespace OC\Files\Storage;
use OCP\Files;
/**
* Storage backend class for providing common filesystem operation methods
* which are not storage-backend specific.
@ -45,7 +47,7 @@ trait LocalTempFileTrait {
}
$tmpFile = \OC::$server->getTempManager()->getTemporaryFile($extension);
$target = fopen($tmpFile, 'w');
\OC_Helper::streamCopy($source, $target);
Files::streamCopy($source, $target);
fclose($target);
return $tmpFile;
}

View file

@ -21,6 +21,7 @@ use OCP\Encryption\Exceptions\InvalidHeaderException;
use OCP\Encryption\IFile;
use OCP\Encryption\IManager;
use OCP\Encryption\Keys\IStorage;
use OCP\Files;
use OCP\Files\Cache\ICacheEntry;
use OCP\Files\Mount\IMountPoint;
use OCP\Files\Storage;
@ -684,7 +685,7 @@ class Encryption extends Wrapper {
try {
$source = $sourceStorage->fopen($sourceInternalPath, 'r');
$target = $this->fopen($targetInternalPath, 'w');
[, $result] = \OC_Helper::streamCopy($source, $target);
[, $result] = Files::streamCopy($source, $target, true);
} finally {
if (is_resource($source)) {
fclose($source);
@ -893,7 +894,7 @@ class Encryption extends Wrapper {
public function writeStream(string $path, $stream, ?int $size = null): int {
// always fall back to fopen
$target = $this->fopen($path, 'w');
[$count, $result] = \OC_Helper::streamCopy($stream, $target);
[$count, $result] = Files::streamCopy($stream, $target, true);
fclose($stream);
fclose($target);

View file

@ -11,6 +11,7 @@ use OC\Files\Cache\Wrapper\CacheJail;
use OC\Files\Cache\Wrapper\JailPropagator;
use OC\Files\Cache\Wrapper\JailWatcher;
use OC\Files\Filesystem;
use OCP\Files;
use OCP\Files\Cache\ICache;
use OCP\Files\Cache\IPropagator;
use OCP\Files\Cache\IWatcher;
@ -253,7 +254,7 @@ class Jail extends Wrapper {
return $storage->writeStream($this->getUnjailedPath($path), $stream, $size);
} else {
$target = $this->fopen($path, 'w');
[$count, $result] = \OC_Helper::streamCopy($stream, $target);
$count = Files::streamCopy($stream, $target);
fclose($stream);
fclose($target);
return $count;

View file

@ -9,6 +9,7 @@ namespace OC\Files\Storage\Wrapper;
use OC\Files\Storage\FailedStorage;
use OC\Files\Storage\Storage;
use OCP\Files;
use OCP\Files\Cache\ICache;
use OCP\Files\Cache\IPropagator;
use OCP\Files\Cache\IScanner;
@ -322,7 +323,7 @@ class Wrapper implements \OC\Files\Storage\Storage, ILockingStorage, IWriteStrea
return $storage->writeStream($path, $stream, $size);
} else {
$target = $this->fopen($path, 'w');
[$count, $result] = \OC_Helper::streamCopy($stream, $target);
$count = Files::streamCopy($stream, $target);
fclose($stream);
fclose($target);
return $count;

View file

@ -17,6 +17,7 @@ use OC\User\Manager as UserManager;
use OC\User\User;
use OCA\Files_Sharing\SharedMount;
use OCP\Constants;
use OCP\Files;
use OCP\Files\Cache\ICacheEntry;
use OCP\Files\ConnectionLostException;
use OCP\Files\EmptyFileNameException;
@ -629,7 +630,7 @@ class View {
[$storage, $internalPath] = $this->resolvePath($path);
$target = $storage->fopen($internalPath, 'w');
if ($target) {
[, $result] = \OC_Helper::streamCopy($data, $target);
[, $result] = Files::streamCopy($data, $target, true);
fclose($target);
fclose($data);

View file

@ -158,31 +158,10 @@ class OC_Helper {
* @param resource $source
* @param resource $target
* @return array the number of bytes copied and result
* @deprecated 5.0.0 - Use \OCP\Files::streamCopy
*/
public static function streamCopy($source, $target) {
if (!$source or !$target) {
return [0, false];
}
$bufSize = 8192;
$result = true;
$count = 0;
while (!feof($source)) {
$buf = fread($source, $bufSize);
$bytesWritten = fwrite($target, $buf);
if ($bytesWritten !== false) {
$count += $bytesWritten;
}
// note: strlen is expensive so only use it when necessary,
// on the last block
if ($bytesWritten === false
|| ($bytesWritten < $bufSize && $bytesWritten < strlen($buf))
) {
// write error, could be disk full ?
$result = false;
break;
}
}
return [$count, $result];
return \OCP\Files::streamCopy($source, $target, true);
}
/**

View file

@ -85,15 +85,45 @@ class Files {
/**
* Copy the contents of one stream to another
*
* @template T of null|true
* @param resource $source
* @param resource $target
* @return int the number of bytes copied
* @param T $includeResult
* @return int|array
* @psalm-return (T is true ? array{0: int, 1: bool} : int)
* @since 5.0.0
* @since 32.0.0 added $includeResult parameter
* @deprecated 14.0.0
*/
public static function streamCopy($source, $target) {
[$count, ] = \OC_Helper::streamCopy($source, $target);
return $count;
public static function streamCopy($source, $target, ?bool $includeResult = null) {
if (!$source or !$target) {
return $includeResult ? [0, false] : 0;
}
$bufSize = 8192;
$count = 0;
$result = true;
while (!feof($source)) {
$buf = fread($source, $bufSize);
if ($buf === false) {
$result = false;
break;
}
$bytesWritten = fwrite($target, $buf);
if ($bytesWritten !== false) {
$count += $bytesWritten;
}
if ($bytesWritten === false
|| ($bytesWritten < $bufSize && $bytesWritten < strlen($buf))
) {
$result = false;
break;
}
}
return $includeResult ? [$count, $result] : $count;
}
/**