phpzip

Preserve symlinks when creating zip file with php ZipArchive


I am building archive with ZipArchive from directory which contains symbolic links which I want to preserve. Example structure:

-- file1
-- file2
-- directory/file3 --> ../file1

When I execute the code I have below, directory/file3 is present in the archive but instead of being symlink, it has the contents of file. Although it works, there are large amount of links that I want to preserve to keep archive size smaller.

    $zip = new ZipArchive();
    $zip->open($zipFile, ZipArchive::CREATE | ZipArchive::OVERWRITE)

    foreach($filesToZip as $name => $file) {
        if (!$file->isDir()) {
            $filePath = $file->getPathname();
            $relativePath = substr($filePath, strlen($rootPath) + 1);
            $zip->addFile($filePath, $relativePath);
        }
    }

    $zip->close();

What would you recommend as solution?

I also tried using file->getRealPath() which just makes the problem worse since it adds the file with its absolute path into the archive.


Solution

  • A symbolic link is essentially a text file, the content of which is the target path, and the file itself has a mode flag l.

    The principle is simple, but the functions involved are a bit complex:

    if(is_link($filePath)) {
        $targetPath = readlink($filePath);
        $stat = lstat($filePath);
        $zip->addFromString($relativePath, $targetPath);
        $zip->setExternalAttributesName($relativePath,
                                        ZipArchive::OPSYS_UNIX, 
                                        $stat['mode'] << 16);
    }