NativeSeekDriver::getFileSize()   B
last analyzed

Complexity

Conditions 5
Paths 5

Size

Total Lines 33
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
c 3
b 0
f 0
dl 0
loc 33
rs 8.439
cc 5
eloc 17
nc 5
nop 1
1
<?php
2
3
namespace BigFileTools\Driver;
4
5
use BigFileTools\Utils;
6
use Brick\Math\BigInteger;
7
8
class NativeSeekDriver implements ISizeDriver
9
{
10
	/**
11
	 * Returns file size by seeking at the end of file
12
	 * @see http://www.php.net/manual/en/function.filesize.php#79023
13
	 * @see http://www.php.net/manual/en/function.filesize.php#102135
14
	 * @param string $path Full path to file
15
	 * @return BigInteger
16
	 * @throws Exception
17
	 */
18
	public function getFileSize($path)
19
	{
20
		// This should work for large files on 64bit platforms and for small files everywhere
21
		$fp = fopen($path, "rb");
22
		if (!$fp) {
23
			throw new Exception("Cannot open specified file for reading.");
24
		}
25
26
		$flockResult = flock($fp, LOCK_SH);
27
		$seekResult = fseek($fp, 0, SEEK_END);
28
		$position = ftell($fp);
29
		flock($fp, LOCK_UN);
30
		fclose($fp);
31
32
		if($flockResult === false) {
33
			throw new Exception("Couldn't get file lock. Operation abandoned.");
34
		}
35
36
		if($seekResult !== 0) {
37
			throw new Exception("Seeking to end of file failed");
38
		}
39
40
		if($position === false) {
41
			throw new Exception("Cannot determine position in file. ftell() failed.");
42
		}
43
44
		// PHP uses internally (in C) UNSIGNED integer for file size.
45
		// PHP uses signed implicitly
46
		// convert signed (max val +2^31) -> unsigned integer will extend range for 32-bit to (+2^32)
47
		return BigInteger::of(
48
			sprintf("%u", $position)
49
		);
50
	}
51
}