<?php
// +---------------------------------------------------------------+
// | File Stats Class |
// +---------------------------------------------------------------+
// | Works with large files on 32 bit systems |
// +---------------------------------------------------------------+
// | Authors: Jamie Curnow <jc@jc21.com> |
// +---------------------------------------------------------------+
// $Id:$
class File_Stats {
const TYPE_DIR = 1;
const TYPE_FILE = 2;
const OPSYS_LINUX = 1;
const OPSYS_BSD = 2;
const OPSYS_WIN = 3;
/**
* What is this operating system?
*
* @var int
* @access protected
*
**/
protected $_opsys = self::OPSYS_LINUX;
/**
* Should we use Windows COM objects?
*
* @var bool
* @access protected
*
**/
protected $_use_win_com = true;
/**
* Are we using a 32 bit operating system/PHP binary?
*
* @var bool
* @access protected
*
**/
protected $_is_32_bit = true;
/**
* Constructor
*
* @access public
* @return void
*/
public function __construct() {
$this->_determineOpSys();
$this->_is_32_bit = (PHP_INT_MAX > 2147483647 ? false : true);
}
/**
* Should we use Windows COM Objects?
*
* @access protected
* @param bool $bool
* @return void
*/
public function setUseWinCom($bool) {
$this->_use_win_com = (bool) $bool;
}
/**
* Determine the operating system we're running on
*
* @access protected
* @return int
*/
protected function _determineOpSys() {
$name = strtolower(php_uname('s'));
if (strpos($name, 'win') !== false) {
$this->_opsys = self::OPSYS_WIN;
} else if (strpos($name, 'bsd') !== false) {
$this->_opsys = self::OPSYS_BSD;
} else if (strpos($name, 'linux') !== false) {
$this->_opsys = self::OPSYS_LINUX;
}
}
/**
* Get the filesize of a file
*
* @access public
* @param string $file
* @return int
*/
public function getFileSize($file) {
// Only go into workaround methods if this is a 32 bit operating system
if ($this->_is_32_bit) {
$filesize = 0;
if ($this->_opsys == self::OPSYS_WIN && $this->_use_win_com) {
// Don't bother checking if filesize() failed, on windows it doesn't fail
// and instead rolls over the integer boundary.
$filesize = $this->_getLargeFileSize($file);
} else {
$filesize = (@filesize($file) ? filesize($file) : $this->_getLargeFileSize($file));
}
return $filesize;
} else {
return filesize($file);
}
}
/**
* Attempt to return the filesize for files larger than 2gb on 32bit systems
*
* @access protected
* @param string $file
* @return float
*/
protected function _getLargeFileSize($file) {
if ($file && strlen($file)) {
switch ($this->_opsys) {
case self::OPSYS_BSD:
return (float) exec('stat -f %z '. escapeshellarg ($file));
break;
case self::OPSYS_LINUX:
$file = $this->_getRealPath($file);
return (float) exec('stat -c %s '. escapeshellarg ($file));
break;
case self::OPSYS_WIN:
try {
$fsobj = new COM("Scripting.FileSystemObject");
$f = $fsobj->GetFile($file);
return $f->Size;
} catch(Exception $e) {
return 0;
}
break;
}
}
return 0;
}
/**
* Get the Modified Time of a file
*
* @access public
* @param string $file
* @return int
*/
public function getFileModifiedTime($file) {
// Only go into workaround methods if this is a 32 bit operating system
if ($this->_is_32_bit) {
return (@filemtime($file) ? filemtime($file) : $this->_getLargeFileModifiedTime($file));
} else {
return filemtime($file);
}
}
/**
* Attempt to return the modified time for files larger than 2gb on 32bit systems
*
* @access protected
* @param string $file
* @return int
*/
protected function _getLargeFileModifiedTime($file) {
if ($file && strlen($file)) {
switch ($this->_opsys) {
case self::OPSYS_BSD:
return exec('stat -f %m '. escapeshellarg ($file));
break;
case self::OPSYS_LINUX:
$file = $this->_getRealPath($file);
return exec('stat -c %Y '. escapeshellarg ($file));
break;
}
}
return 0;
}
/**
* Find out the Type of file on disk, it's either a Directory or a File.
*
* @access public
* @param string $file
* @return int
*/
public function getFileType($file) {
// Only go into workaround methods if this is a 32 bit operating system
if ($this->_is_32_bit) {
return $this->_getLargeFileType($file);
} else {
return (is_dir($file) ? self::TYPE_DIR : self::TYPE_FILE);
}
}
/**
* Attempt to return the filetype for files/dirs larger than 2gb on 32bit systems
*
* @access protected
* @param string $file
* @return float
*/
protected function _getLargeFileType($file) {
if ($file && strlen($file)) {
switch ($this->_opsys) {
case self::OPSYS_BSD:
$type = strtolower(exec('stat -f %HT '. escapeshellarg ($file)));
if (strpos($type, 'directory') !== false) {
return self::TYPE_DIR;
} else if (strpos($type, 'symbolic') !== false) {
$file = $this->_getRealPath($file);
return $this->_getLargeFileType($file);
} else {
return self::TYPE_FILE;
}
return $var;
break;
case self::OPSYS_LINUX:
$var = false;
$type = strtolower(exec ('stat -c %F '. escapeshellarg ($file)));
if (strpos($type, 'directory') !== false) {
return self::TYPE_DIR;
} else if (strpos($type, 'symbolic') !== false) {
$file = $this->_getRealPath($file);
return $this->_getLargeFileType($file);
} else {
return self::TYPE_FILE;
}
return $var;
break;
case self::OPSYS_WIN:
return (is_dir($file) ? self::TYPE_DIR : self::TYPE_FILE);
break;
}
}
return false;
}
/**
* A 32 bit compatible version of realpath()
*
* @access protected
* @param string $file
* @return string
*/
protected function _getRealPath($file) {
if ($file && strlen($file)) {
// Only go into workaround methods if this is a 32 bit operating system
if ($this->_is_32_bit) {
switch ($this->_opsys) {
case self::OPSYS_LINUX:
$var = false;
return exec ('readlink -f '. escapeshellarg ($file));
break;
}
}
return realpath($file);
}
return false;
}
}
|