Skip to content
Snippets Groups Projects
Commit c8fa1fd6 authored by Andreas Fischer's avatar Andreas Fischer
Browse files

Refactor Large File handling code.

parent 3f8f8027
No related branches found
No related tags found
No related merge requests found
...@@ -89,9 +89,8 @@ if (\OC_Util::runningOnWindows()) { ...@@ -89,9 +89,8 @@ if (\OC_Util::runningOnWindows()) {
public function stat($path) { public function stat($path) {
$fullPath = $this->datadir . $path; $fullPath = $this->datadir . $path;
$statResult = stat($fullPath); $statResult = stat($fullPath);
if (PHP_INT_SIZE === 4) {
$filesize = self::getFileSizeWithTricks($fullPath); $filesize = $this->filesize($path);
if (!is_null($filesize)) {
$statResult['size'] = $filesize; $statResult['size'] = $filesize;
$statResult[7] = $filesize; $statResult[7] = $filesize;
} }
...@@ -109,16 +108,16 @@ if (\OC_Util::runningOnWindows()) { ...@@ -109,16 +108,16 @@ if (\OC_Util::runningOnWindows()) {
public function filesize($path) { public function filesize($path) {
if ($this->is_dir($path)) { if ($this->is_dir($path)) {
return 0; return 0;
} else { }
$fullPath = $this->datadir . $path; $fullPath = $this->datadir . $path;
if (PHP_INT_SIZE === 4) {
$filesize = self::getFileSizeWithTricks($fullPath); $helper = new \OC\LargeFileHelper;
$filesize = $helper->getFilesize($fullPath);
if (!is_null($filesize)) { if (!is_null($filesize)) {
return $filesize; return $filesize;
} }
return filesize($fullPath);
} }
return filesize($fullPath);
} }
public function isReadable($path) { public function isReadable($path) {
...@@ -221,87 +220,6 @@ if (\OC_Util::runningOnWindows()) { ...@@ -221,87 +220,6 @@ if (\OC_Util::runningOnWindows()) {
return $return; return $return;
} }
/**
* @brief Tries to get the filesize via various workarounds if necessary.
* @param string $fullPath
* @return mixed Number of bytes on success and workaround necessary, null otherwise.
*/
private static function getFileSizeWithTricks($fullPath) {
if (PHP_INT_SIZE === 4) {
// filesize() and stat() are unreliable on 32bit systems
// for big files.
// In some cases they cause an E_WARNING and return false,
// in some other cases they silently wrap around at 2^32,
// i.e. e.g. report 674347008 bytes instead of 4969314304.
$filesize = self::getFileSizeFromCurl($fullPath);
if (!is_null($filesize)) {
return $filesize;
}
$filesize = self::getFileSizeFromOS($fullPath);
if (!is_null($filesize)) {
return $filesize;
}
}
return null;
}
/**
* @brief Tries to get the filesize via a CURL HEAD request.
* @param string $fullPath
* @return mixed Number of bytes on success, null otherwise.
*/
private static function getFileSizeFromCurl($fullPath) {
if (function_exists('curl_init')) {
$ch = curl_init("file://$fullPath");
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);
$data = curl_exec($ch);
curl_close($ch);
if ($data !== false) {
$matches = array();
preg_match('/Content-Length: (\d+)/', $data, $matches);
if (isset($matches[1])) {
return 0 + $matches[1];
}
}
}
return null;
}
/**
* @brief Tries to get the filesize via COM and exec().
* @param string $fullPath
* @return mixed Number of bytes on success, null otherwise.
*/
private static function getFileSizeFromOS($fullPath) {
$name = strtolower(php_uname('s'));
// Windows OS: we use COM to access the filesystem
if (strpos($name, 'win') !== false) {
if (class_exists('COM')) {
$fsobj = new \COM("Scripting.FileSystemObject");
$f = $fsobj->GetFile($fullPath);
return $f->Size;
}
} else if (strpos($name, 'bsd') !== false) {
if (\OC_Helper::is_function_enabled('exec')) {
return 0 + exec('stat -f %z ' . escapeshellarg($fullPath));
}
} else if (strpos($name, 'linux') !== false) {
if (\OC_Helper::is_function_enabled('exec')) {
return 0 + exec('stat -c %s ' . escapeshellarg($fullPath));
}
} else {
\OC_Log::write('core',
'Unable to determine file size of "' . $fullPath . '". Unknown OS: ' . $name,
\OC_Log::ERROR);
}
return null;
}
public function hash($type, $path, $raw = false) { public function hash($type, $path, $raw = false) {
return hash_file($type, $this->datadir . $path, $raw); return hash_file($type, $this->datadir . $path, $raw);
} }
......
...@@ -111,11 +111,10 @@ class MappedLocal extends \OC\Files\Storage\Common { ...@@ -111,11 +111,10 @@ class MappedLocal extends \OC\Files\Storage\Common {
public function stat($path) { public function stat($path) {
$fullPath = $this->buildPath($path); $fullPath = $this->buildPath($path);
$statResult = stat($fullPath); $statResult = stat($fullPath);
if (PHP_INT_SIZE === 4) {
if ($statResult['size'] < 0) { $filesize = $this->filesize($path);
$size = self::getFileSizeFromOS($fullPath); $statResult['size'] = $filesize;
$statResult['size'] = $size; $statResult[7] = $filesize;
$statResult[7] = $size;
} }
return $statResult; return $statResult;
} }
...@@ -131,15 +130,16 @@ class MappedLocal extends \OC\Files\Storage\Common { ...@@ -131,15 +130,16 @@ class MappedLocal extends \OC\Files\Storage\Common {
public function filesize($path) { public function filesize($path) {
if ($this->is_dir($path)) { if ($this->is_dir($path)) {
return 0; return 0;
} else { }
$fullPath = $this->buildPath($path); $fullPath = $this->buildPath($path);
$fileSize = filesize($fullPath); if (PHP_INT_SIZE === 4) {
if ($fileSize < 0) { $helper = new \OC\LargeFileHelper;
return self::getFileSizeFromOS($fullPath); $filesize = $helper->getFilesize($fullPath);
if (!is_null($filesize)) {
return $filesize;
} }
return $fileSize;
} }
return filesize($fullPath);
} }
public function isReadable($path) { public function isReadable($path) {
...@@ -294,35 +294,6 @@ class MappedLocal extends \OC\Files\Storage\Common { ...@@ -294,35 +294,6 @@ class MappedLocal extends \OC\Files\Storage\Common {
return $return; return $return;
} }
/**
* @param string $fullPath
*/
private static function getFileSizeFromOS($fullPath) {
$name = strtolower(php_uname('s'));
// Windows OS: we use COM to access the filesystem
if (strpos($name, 'win') !== false) {
if (class_exists('COM')) {
$fsobj = new \COM("Scripting.FileSystemObject");
$f = $fsobj->GetFile($fullPath);
return $f->Size;
}
} else if (strpos($name, 'bsd') !== false) {
if (\OC_Helper::is_function_enabled('exec')) {
return (float)exec('stat -f %z ' . escapeshellarg($fullPath));
}
} else if (strpos($name, 'linux') !== false) {
if (\OC_Helper::is_function_enabled('exec')) {
return (float)exec('stat -c %s ' . escapeshellarg($fullPath));
}
} else {
\OC_Log::write('core',
'Unable to determine file size of "' . $fullPath . '". Unknown OS: ' . $name,
\OC_Log::ERROR);
}
return 0;
}
public function hash($type, $path, $raw = false) { public function hash($type, $path, $raw = false) {
return hash_file($type, $this->buildPath($path), $raw); return hash_file($type, $this->buildPath($path), $raw);
} }
......
<?php
/**
* Copyright (c) 2014 Andreas Fischer <bantu@owncloud.com>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OC;
/**
* Helper class for large files on 32-bit platforms.
*/
class LargeFileHelper {
/**
* @brief Tries to get the filesize of a file via various workarounds that
* even work for large files on 32-bit platforms.
*
* @param string $filename Path to the file.
*
* @return null|int|float Number of bytes as number (float or int) or
* null on failure.
*/
public function getFilesize($filename) {
$filesize = $this->getFilesizeViaCurl($filename);
if (!is_null($filesize)) {
return $filesize;
}
$filesize = $this->getFilesizeViaCOM($filename);
if (!is_null($filesize)) {
return $filesize;
}
$filesize = $this->getFilesizeViaExec($filename);
if (!is_null($filesize)) {
return $filesize;
}
return null;
}
/**
* @brief Tries to get the filesize of a file via a CURL HEAD request.
*
* @param string $filename Path to the file.
*
* @return null|int|float Number of bytes as number (float or int) or
* null on failure.
*/
public function getFilesizeViaCurl($filename) {
if (function_exists('curl_init')) {
$ch = curl_init("file://$filename");
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);
$data = curl_exec($ch);
curl_close($ch);
if ($data !== false) {
$matches = array();
preg_match('/Content-Length: (\d+)/', $data, $matches);
if (isset($matches[1])) {
return 0 + $matches[1];
}
}
}
return null;
}
/**
* @brief Tries to get the filesize of a file via the Windows DOM extension.
*
* @param string $filename Path to the file.
*
* @return null|int|float Number of bytes as number (float or int) or
* null on failure.
*/
public function getFilesizeViaCOM($filename) {
if (class_exists('COM')) {
$fsobj = new \COM("Scripting.FileSystemObject");
$file = $fsobj->GetFile($filename);
return 0 + $file->Size;
}
return null;
}
/**
* @brief Tries to get the filesize of a file via an exec() call.
*
* @param string $filename Path to the file.
*
* @return null|int|float Number of bytes as number (float or int) or
* null on failure.
*/
public function getFilesizeViaExec($filename) {
if (\OC_Helper::is_function_enabled('exec')) {
$os = strtolower(php_uname('s'));
if (strpos($os, 'linux') !== false) {
return 0 + exec('stat -c %s ' . escapeshellarg($filename));
} else if (strpos($os, 'bsd') !== false) {
return 0 + exec('stat -f %z ' . escapeshellarg($filename));
}
}
return null;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment