From cedec593ee32d7e8b988c9df7c08020df52dbdb3 Mon Sep 17 00:00:00 2001
From: Thomas Mueller <thomas.mueller@tmit.eu>
Date: Fri, 4 Jan 2013 23:03:26 +0100
Subject: [PATCH] Fallback to use COM or exec('stat ..') is only executed if
 stat or filesize return negative values. Special case of BSD has been added
 as stat syntax differs In addition unknown OS is logged

---
 lib/filestorage/local.php | 47 +++++++++++++++++++++++++++++----------
 1 file changed, 35 insertions(+), 12 deletions(-)

diff --git a/lib/filestorage/local.php b/lib/filestorage/local.php
index 0bf6ad2d3d7..435fcb692a3 100644
--- a/lib/filestorage/local.php
+++ b/lib/filestorage/local.php
@@ -29,22 +29,15 @@ class OC_Filestorage_Local extends OC_Filestorage_Common{
 		return is_file($this->datadir.$path);
 	}
 	public function stat($path) {
-		$fullPath = $this->datadir.$path;
+		$fullPath = $this->datadir . $path;
 		$statResult = stat($fullPath);
 
-		// special case for 32-bit systems
-		if (PHP_INT_SIZE===4) {
-			if (!(strtoupper(substr(PHP_OS, 0, 3)) == 'WIN'))
-				$size = (float)exec('stat -c %s '. escapeshellarg ($fullPath));
-			else{
-				$fsobj = new COM("Scripting.FileSystemObject");
-				$f = $fsobj->GetFile($fullPath);
-				$size = $f->Size;
-			}
-
+		if ($statResult['size'] < 0) {
+			$size = self::getFileSizeFromOS($fullPath);
 			$statResult['size'] = $size;
 			$statResult[7] = $size;
 		}
+		return $statResult;
 
 		return $statResult;
 	}
@@ -59,7 +52,13 @@ class OC_Filestorage_Local extends OC_Filestorage_Common{
 		if($this->is_dir($path)) {
 			return 0;
 		}else{
-			return filesize($this->datadir.$path);
+			$fullPath = $this->datadir . $path;
+			$fileSize = filesize($fullPath);
+			if ($fileSize < 0) {
+				return self::getFileSizeFromOS($fullPath);
+			}
+
+			return $fileSize;
 		}
 	}
 	public function isReadable($path) {
@@ -173,6 +172,30 @@ class OC_Filestorage_Local extends OC_Filestorage_Common{
 		return $return;
 	}
 
+	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', 'Unknown OS: '.$name, OC_Log::ERROR);
+		}
+
+		return 0;
+	}
+
 	public function hash($path, $type, $raw=false) {
 		return hash_file($type, $this->datadir.$path, $raw);
 	}
-- 
GitLab