Skip to content

Commit 1aafca1

Browse files
committed
Resolve paths in symlinks before adding to ZIP file
1 parent 1a1195f commit 1aafca1

File tree

1 file changed

+21
-7
lines changed

1 file changed

+21
-7
lines changed

src/main/php/xp/lambda/PackageLambda.class.php

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@
66
use util\cmd\Console;
77

88
class PackageLambda {
9-
const COMPRESSION_THRESHOLD = 24;
9+
const COMPRESSION_THRESHOLD= 24;
10+
11+
const IS_LINK= 0120000;
12+
const IS_FILE= 0100000;
13+
const IS_FOLDER= 0040000;
1014

1115
private $target, $sources, $exclude, $compression;
1216

@@ -26,11 +30,21 @@ public function __construct(Path $target, Sources $sources, string $exclude= '#(
2630
}
2731

2832
/** Adds ZIP file entries */
29-
private function add(ZipArchiveWriter $zip, Path $path) {
33+
private function add(ZipArchiveWriter $zip, Path $path, Path $base, $prefix= '') {
3034
if (preg_match($this->exclude, $path->toString('/'))) return;
3135

32-
$relative= $path->relativeTo($this->sources->base);
33-
if ($path->isFile()) {
36+
$stat= lstat($path);
37+
$relative= $prefix.$path->relativeTo($base);
38+
39+
// Handle the following file types:
40+
// - Links: Resolve, then handle link targets
41+
// - Files: Add to ZIP
42+
// - Folders: Recursively add all subfolders and files therein
43+
if (self::IS_LINK === ($stat['mode'] & self::IS_LINK)) {
44+
$resolved= new Path(readlink($path));
45+
$base= $resolved->isFile() ? new Path(dirname($resolved)) : $resolved;
46+
yield from $this->add($zip, $resolved, $base, $relative.DIRECTORY_SEPARATOR);
47+
} else if (self::IS_FILE === ($stat['mode'] & self::IS_FILE)) {
3448
$file= $zip->add(new ZipFileEntry($relative));
3549

3650
// See https://stackoverflow.com/questions/46716095/minimum-file-size-for-compression-algorithms
@@ -39,10 +53,10 @@ private function add(ZipArchiveWriter $zip, Path $path) {
3953
}
4054
(new StreamTransfer($path->asFile()->in(), $file->out()))->transferAll();
4155
yield $file;
42-
} else {
56+
} else if (self::IS_FOLDER === ($stat['mode'] & self::IS_FOLDER)) {
4357
yield $zip->add(new ZipDirEntry($relative));
4458
foreach ($path->asFolder()->entries() as $entry) {
45-
yield from $this->add($zip, $entry);
59+
yield from $this->add($zip, $entry, $base, $prefix);
4660
}
4761
}
4862
}
@@ -56,7 +70,7 @@ public function run(): int {
5670
foreach ($sources as $i => $source) {
5771
Console::writef("\e[34m => [%d/%d] ", $i + 1, $total);
5872
$entries= 0;
59-
foreach ($this->add($z, new Path($source)) as $entry) {
73+
foreach ($this->add($z, new Path($source), $this->sources->base) as $entry) {
6074
$entries++;
6175
Console::writef('%-60s %4d%s', substr($entry->getName(), -60), $entries, str_repeat("\x08", 65));
6276
}

0 commit comments

Comments
 (0)