<?php
 
// +---------------------------------------------------------------+
 
// | File Stats Class                                              |
 
// +---------------------------------------------------------------+
 
// | Works with large files on 32 bit systems                      |
 
// +---------------------------------------------------------------+
 
// | Authors:       Jamie Curnow  <[email protected]>                    |
 
// +---------------------------------------------------------------+
 
 
// $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;
 
        }
 
 
 
    }
 
 
 
 
 |