1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Storeman; |
4
|
|
|
|
5
|
|
|
abstract class FilesystemUtility |
6
|
|
|
{ |
7
|
|
|
/** |
8
|
|
|
* Does the same thing as its php core counterpart but returns atime, ctime and mtime in full precision. |
9
|
|
|
* |
10
|
|
|
* @param string $path |
11
|
|
|
* @return array |
12
|
|
|
* @throws \RuntimeException |
13
|
|
|
*/ |
14
|
|
|
public static function lstat(string $path): array |
15
|
|
|
{ |
16
|
|
|
exec('stat ' . escapeshellarg('-c%D;%i;%f;%h;%u;%g;%t;%s;%x;%y;%z;%B;%b') . ' ' . escapeshellarg($path) . ' 2>&1', $output, $exitCode); |
17
|
|
|
|
18
|
|
|
if ($exitCode !== 0) |
19
|
|
|
{ |
20
|
|
|
throw new \RuntimeException(); |
21
|
|
|
} |
22
|
|
|
|
23
|
|
|
$array = str_getcsv($output[0], ';'); |
24
|
|
|
|
25
|
|
|
$stat = [ |
26
|
|
|
'dev' => hexdec($array[0]), |
27
|
|
|
'ino' => (int)$array[1], |
28
|
|
|
'mode' => hexdec($array[2]), |
29
|
|
|
'nlink' => (int)$array[3], |
30
|
|
|
'uid' => (int)$array[4], |
31
|
|
|
'gid' => (int)$array[5], |
32
|
|
|
'rdev' => hexdec($array[6]), |
33
|
|
|
'size' => (int)$array[7], |
34
|
|
|
'atime' => static::parseTime($array[8]), |
35
|
|
|
'mtime' => static::parseTime($array[9]), |
36
|
|
|
'ctime' => static::parseTime($array[10]), |
37
|
|
|
'blksize' => (int)$array[11], |
38
|
|
|
'blocks' => (int)$array[12], |
39
|
|
|
]; |
40
|
|
|
|
41
|
|
|
// for full compatibility |
42
|
|
|
$stat[0] = $stat['dev']; |
43
|
|
|
$stat[1] = $stat['ino']; |
44
|
|
|
$stat[2] = $stat['mode']; |
45
|
|
|
$stat[3] = $stat['nlink']; |
46
|
|
|
$stat[4] = $stat['uid']; |
47
|
|
|
$stat[5] = $stat['gid']; |
48
|
|
|
$stat[6] = $stat['rdev']; |
49
|
|
|
$stat[7] = $stat['size']; |
50
|
|
|
$stat[8] = $stat['atime']; |
51
|
|
|
$stat[9] = $stat['mtime']; |
52
|
|
|
$stat[10] = $stat['ctime']; |
53
|
|
|
$stat[11] = $stat['blksize']; |
54
|
|
|
$stat[12] = $stat['blocks']; |
55
|
|
|
|
56
|
|
|
return $stat; |
57
|
|
|
} |
58
|
|
|
|
59
|
|
|
/** |
60
|
|
|
* Parses strings like this: 2018-07-11 00:40:23.636828641 +0200 |
61
|
|
|
* Returns unix timestamp with sub-second resolution as float. |
62
|
|
|
* |
63
|
|
|
* @param string $timeString |
64
|
|
|
* @return float |
65
|
|
|
*/ |
66
|
|
|
public static function parseTime(string $timeString): float |
67
|
|
|
{ |
68
|
|
|
$fractionStringEnd = strpos($timeString, ' ', 19); |
69
|
|
|
$reducedPrecisionString = substr($timeString, 0, 19) . substr($timeString, $fractionStringEnd); |
70
|
|
|
|
71
|
|
|
$time = (float)\DateTime::createFromFormat('Y-m-d H:i:s O', $reducedPrecisionString)->getTimestamp(); |
72
|
|
|
$time += (float)substr($timeString, 19, $fractionStringEnd - 19); |
73
|
|
|
|
74
|
|
|
return $time; |
75
|
|
|
} |
76
|
|
|
|
77
|
|
|
/** |
78
|
|
|
* Rebuilds time string like this from given unixtime: 2018-07-11 00:40:23.636828641 +0200 |
79
|
|
|
* |
80
|
|
|
* @param float $timestamp |
81
|
|
|
* @param int $decimals |
82
|
|
|
* @param \DateTimeZone $timeZone |
83
|
|
|
* @return string |
84
|
|
|
*/ |
85
|
|
|
public static function buildTime(float $timestamp, int $decimals = 9, \DateTimeZone $timeZone = null): string |
86
|
|
|
{ |
87
|
|
|
$dateTime = \DateTime::createFromFormat('U', (int)$timestamp); |
88
|
|
|
$timestampString = sprintf("%.{$decimals}f", $timestamp); |
89
|
|
|
|
90
|
|
|
if ($timeZone) |
91
|
|
|
{ |
92
|
|
|
$dateTime->setTimezone($timeZone); |
93
|
|
|
} |
94
|
|
|
|
95
|
|
|
$string = $dateTime->format('Y-m-d H:i:s'); |
96
|
|
|
$string .= substr($timestampString, strpos($timestampString, '.')); |
97
|
|
|
$string .= " {$dateTime->format('O')}"; |
98
|
|
|
|
99
|
|
|
return $string; |
100
|
|
|
} |
101
|
|
|
} |
102
|
|
|
|