ZIP uncompressEntry and alias files


#1

When i uncompress arhive which contains folder alias files, aliases became ordinary files/documents.

I use ZIP uncompressEntry() function. Any ideas how to avoid this issue?

Thx!


#2

I can’t really imagine that aliases would work in a zip file! Do they work if you use a normal desktop zip tool??


#3

If i use OSX unzip (doubleclick on zip file in Finder), it works properly.


#4

But don’t aliases use absolute paths? And what about file systems that don’t support aliases? I can’t really see it being something that we could make work on all platforms…


#5

Google finds in the Zip-Specifications:

4.5.7 -UNIX Extra Field (0x000d):

       The following is the layout of the UNIX "extra" block.
       Note: all fields are stored in Intel low-byte/high-byte 
       order.

        Value       Size          Description
        -----       ----          -----------
(UNIX)  0x000d      2 bytes       Tag for this "extra" block type
        TSize       2 bytes       Size for the following data block
        Atime       4 bytes       File last access time
        Mtime       4 bytes       File last modification time
        Uid         2 bytes       File user ID
        Gid         2 bytes       File group ID
        (var)       variable      Variable length data field

       The variable length data field will contain file type 
       specific data.  Currently the only values allowed are
       the original "linked to" file names for hard or symbolic 
       links, and the major and minor device node numbers for
       character and block device nodes.  Since device nodes
       cannot be either symbolic or hard links, only one set of
       variable length data is stored.  Link files will have the
       name of the original file stored.  This name is NOT NULL
       terminated.  Its size can be determined by checking TSize -
       12.  Device entries will have eight bytes stored as two 4
       byte entries (in little endian format).  The first entry
       will be the major device number, and the second the minor
       device number.

On platforms that don’t support symbolic links, they probably would create a copy of the file on extracting, if the file is inside the archive or ignore it?


#6

In OSX Terminal, the only command line tool which properly preserves aliases from zip file is DITTO. UNZIP doesn’t work properly.


#7

I had a similar problem while creating Zip archives using juce ZipFile::Builder and I fixed it on our JUCE fork.
On MacOSX, while compressing folders containing both files and symbolic links, JUCE handles any symlink as a regular file, creating a zip archive that contains both original files and linked files as compressed entries.
This way when uncompressing the zip archive, using any zip tool, you obtain the original folder with multiple copies of original files and no symlinks.

Besides wasting some storage space, this could cause unpredictable results: e.g. ZipFile::Builder while compressing signed AAX plugin bundles, code signature gets corrupted, since it contains also a symbolic link (ProTools will see this as tampering with aax signing and just report the plugin as invalid).

I’ve adapted my code to the latest develop commit and produced a patch that you can find attached, if you want give it a look.
This will not fix wrong handling of symlinks while uncompressing zips from JUCE, but I think ZipFile::uncompressEntry could be easily patched in a similar way to handle external attributes header field correctly.
I left some comments to explain how the external attributes bit mask is built, with some references.
I checked an HEX dump of a zip file created with MacOSX archive utility (that does support symlinks) and I see they are handled in a similar way, as BSD and GNU Linux do.

juce_ZipFile_cpp_addSymlinks_dev_patch.diff.txt (4.6 KB)


#8

+1 just run into the same issue, would be nice if the juce::ZipFile handles symblic links inside the zip correctly -> both compressing and uncompressing


#9

Thanks. This is now on develop with commits c048f5d and 7bcd6a5.


#10

cool, i didn’t check it yet, but one short question:
Does it support relative paths as link target, a symbolic link can have a relative nature like ../../file
When i read symlink (fullPath.toRawUTF8(), it looks like it always uses the full-path

http://pubs.opengroup.org/onlinepubs/009695399/functions/symlink.html

The string pointed to by path1 shall be treated only as a character string and shall not be validated as a pathname.

PS: for example AAX uses a relative link inside the bundle, if i move the bundle after extracting, the path wouldn’t work anymore


#11

This would require us to change File::createSymbolicLink as this does not support relative paths atm.


#12

or make and additional free function

File::createSymbolicLink(String relativeTargetPath, const File& linkFileToCreate)
{
 
   // windows? relativeTargetPath.replaceSeparatorChar 
 
   if (symlink (relativeTargetPath.toRawUTF8(), linkFileToCreate.getFullPathName().toRawUTF8()) == -1)
    { .. }
}

#13

OK this is now fixed on develop with commits 06d20b2 and 7a1937b.

The first commit includes two new File methods to create and read relative symbolic links:

/** Create a symbolic link to a native path and return a boolean to indicate success.

    Use this method if you want to create a link to a relative path or a special native
    file path (such as a device file on Windows).
*/
static bool createSymbolicLink (const File& linkFileToCreate,
                                const String& nativePathOfTarget,
                                bool overwriteExisting);

/** This returns the native path that the symbolic link points to. The returned path
    is a native path of the current OS and can be a relative, absolute or special path. */
String getNativeLinkedTarget() const;

The second commit adds support for relative symbolic links when compressing or uncompressing zip archives.