|
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
|
|
|
|