quazip icon indicating copy to clipboard operation
quazip copied to clipboard

quazip don't extract file as symlink on linux

Open xlazom00 opened this issue 4 years ago • 13 comments

I have a zip file with symlinks but when I extracted files with quazip symlinked files looks like file with text to symlinked file so this https://github.com/stachenov/quazip/commit/0e5c7adc87e9d23aa80f512b282fbe526d1cc05b don't work on linux

xlazom00 avatar Nov 20 '19 10:11 xlazom00

I had no idea ZIP even supported symlinks. I'll look into it.

stachenov avatar Nov 20 '19 10:11 stachenov

@stachenov zip -y btw so I don't get that commit :) what was the purpose ? :)

xlazom00 avatar Nov 20 '19 10:11 xlazom00

No, wait. Is that my commit? Change “haad no idea” to “totally forgot” and say again, what's your problem? Show me the shortest code that doesn't work.

stachenov avatar Nov 20 '19 10:11 stachenov

@stachenov Ou sorry It is my fault :) I will need to check it one more time

xlazom00 avatar Nov 20 '19 10:11 xlazom00

@stachenov My code look like this:

QuaZip zip( filename );
QuaZipFile zipFile( &zip );
for( bool hasMore = zip.goToFirstFile(); hasMore; hasMore = zip.goToNextFile() )
{
   zipFile.open( QIODevice::ReadOnly );
   while( ( len = zipFile.read( buf, BUF_SIZE ) ) > 0 )
   {
     outputFile.write( buf, len );
   }
}

Ok so how can I detect if file in zip is symlink ?

xlazom00 avatar Nov 20 '19 11:11 xlazom00

it looks like minizip continue in development here https://github.com/nmoinvaz/minizip They also have 1.2 branch

xlazom00 avatar Nov 20 '19 12:11 xlazom00

Yes, I know, but QuaZIP needs some extra modifications in minizip. It can't be used as-is.

stachenov avatar Nov 20 '19 12:11 stachenov

I found that all information is in externalAttr So I have one method

void UpdateDownloader::getFileInfo( quint32 val, bool & isDir, bool & isSymlink ) const
{
    quint32 unixData = val >> 16;
    isDir = ( unixData & 0170000 ) == 0040000;
    isSymlink = ( unixData & 0170000 ) == 0120000;
}

QuaZipFileInfo64 info;
zip.getCurrentFileInfo( &info );

bool isDir, isSymlink;
getFileInfo( info.externalAttr, isDir, isSymlink );

ispiration is from https://github.com/nmoinvaz/minizip/blob/master/mz_zip.c#L2559 so you can detect directory and symlink with this

xlazom00 avatar Nov 20 '19 13:11 xlazom00

Right, it's the same bits that are used in QuaZipNewInfo (the commit you linked from your first post). Well, almost the same. I don't know whether it's unixData & 0170000 or unixData & 0120000. But that's not too important right now. What's important is that it turned out that QuaZIP currently supports symlink creation in the archives, but not extraction. You can do it manually for now, and I'll add a convenience method into QuaZipFileInfo64 later.

stachenov avatar Nov 21 '19 04:11 stachenov

Could you tell me if it's been fixed? or How can i to fix it. It seems that the quazip extract file by copy data, but doesn't handle file attributes?

Wzshun avatar May 26 '20 10:05 Wzshun

QuaZip is now stuck between 0.9.x and 1.0, thanks to CMake... There's the v0.9.x branch, however. If you figure out how to do it, feel free to send a PR to that branch, and I'll make it 0.10 or something. Or wait until I get to it myself, but I can't make any promises how soon it will be done. Thanks for reminding me about it, though.

stachenov avatar May 26 '20 10:05 stachenov

I sort of fixed this now with e226541cedfa611dcdbb01163772e51eda2717b6, but I'm not sure what happens if someone tries to extract an archive containing symbolic links on Windows. Qt will probably end up creating shortcuts instead, which will probably won't be what the user expect because they won't be named *.lnk and therefore won't be recognized by the OS.

stachenov avatar Oct 05 '20 19:10 stachenov

Added a Windows test in 54fd26ebf78cb51347efc3835ab480c651c3539c. Looks like it works as expected, except that links are broken, but they are useless anyway. At least extraction works in general.

The only part I'm unsure of now is this:

static void QuaZipNewInfo_setPermissions(QuaZipNewInfo *info,
        QFile::Permissions perm, bool isDir, bool isSymLink = false)
{
    quint32 uPerm = isDir ? 0040000 : 0100000;

    if ( isSymLink ) {
#ifdef Q_OS_WIN
        uPerm = 0200000;
#else
        uPerm = 0120000;
#endif
    }

I couldn't find what that Windows mask means for Unix permissions. Currently this code is executed for both symbolic links and shortcuts on Qt versions up to 5.13.x, and since 5.14 it is only executed for symbolic links, which are a rare beast on Windows. This code is sort of harmless too because the worst it can do is create ZIP archives with broken links inside. But I'll keep this open for a while in case someone has an idea how to do it right.

stachenov avatar Oct 11 '20 07:10 stachenov