Calculate directory sizes in background

This commit is contained in:
Mikei386
2026-06-23 09:17:32 +02:00
parent 74ba8d0984
commit 53e25c4641
7 changed files with 114 additions and 11 deletions
@@ -5,17 +5,19 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') {
unav_json(unav_job_read($_GET['id'] ?? ''));
}
unav_assert_writable();
$action = $_GET['action'] ?? '';
if (!in_array($action, ['move', 'copy'], true)) {
if (!in_array($action, ['move', 'copy', 'size'], true)) {
unav_error(404, 'Unknown job action');
}
$data = unav_request_data();
$source = unav_existing_path($data['source'] ?? null);
$destination = unav_destination_path($data['destination'] ?? null);
unav_guard_destination($source['path'], $destination['path']);
$destination = null;
if (in_array($action, ['move', 'copy'], true)) {
unav_assert_writable();
$destination = unav_destination_path($data['destination'] ?? null);
unav_guard_destination($source['path'], $destination['path']);
}
$id = str_replace('.', '', uniqid($action . '-', true));
$now = date(DATE_ATOM);
@@ -27,7 +29,7 @@ $job = [
'message' => 'Queued',
'error' => null,
'source' => $source['path'],
'destination' => $destination['path'],
'destination' => $destination['path'] ?? null,
'createdAt' => $now,
'updatedAt' => $now,
];
@@ -9,12 +9,16 @@ function unav_run_job(string $id): void {
$job = unav_job_read($id);
try {
unav_worker_update($job, 'running', 5, 'Preparing');
unav_worker_guard($job['source'], $job['destination']);
if ($job['type'] === 'move') {
unav_worker_guard($job['source'], $job['destination']);
unav_worker_move($job['source'], $job['destination'], $job);
} elseif ($job['type'] === 'copy') {
unav_worker_guard($job['source'], $job['destination']);
unav_worker_copy($job['source'], $job['destination'], $job);
} elseif ($job['type'] === 'size') {
$result = unav_worker_size($job['source'], $job);
$job['result'] = $result;
} else {
throw new RuntimeException('Unknown job action');
}
@@ -55,6 +59,15 @@ function unav_worker_guard(string $source, string $destination): void {
}
}
function unav_worker_guard_source(string $source): string {
$sourceReal = realpath($source);
if ($sourceReal === false) {
throw new RuntimeException('Source not found');
}
unav_worker_assert_inside_root($sourceReal);
return $sourceReal;
}
function unav_worker_assert_inside_root(string $path): void {
foreach (unav_roots() as $root) {
if (unav_is_inside($path, $root['path'])) {
@@ -73,6 +86,38 @@ function unav_worker_move(string $source, string $destination, array &$job): voi
unav_worker_delete($source);
}
function unav_worker_size(string $source, array &$job): array {
$sourceReal = unav_worker_guard_source($source);
unav_worker_update($job, 'running', 10, 'Calculating size');
$result = unav_worker_size_recursive($sourceReal);
unav_worker_update($job, 'running', 95, 'Size calculated');
return $result;
}
function unav_worker_size_recursive(string $path): array {
if (is_link($path)) {
return ['size' => 0, 'files' => 0, 'directories' => 0];
}
if (is_file($path)) {
return ['size' => filesize($path) ?: 0, 'files' => 1, 'directories' => 0];
}
if (!is_dir($path)) {
return ['size' => 0, 'files' => 0, 'directories' => 0];
}
$total = ['size' => 0, 'files' => 0, 'directories' => 1];
foreach (scandir($path) ?: [] as $entry) {
if ($entry === '.' || $entry === '..') {
continue;
}
$child = unav_worker_size_recursive($path . '/' . $entry);
$total['size'] += $child['size'];
$total['files'] += $child['files'];
$total['directories'] += $child['directories'];
}
return $total;
}
function unav_worker_copy(string $source, string $destination, array &$job): void {
if (is_link($source)) {
throw new RuntimeException('Copying symlinks is not allowed');