physfs icon indicating copy to clipboard operation
physfs copied to clipboard

Zip with entries containing complete paths will mount but cannot stat or enumerate

Open jm-seabery opened this issue 1 year ago • 1 comments

Hi,

Had a strange issue that has occurred regarding a zip created through an external library that mounts without error in physfs but any attempt to enumerate or stat on the files inside returns the 'not found' error.

I've tested in the integrity of the zip (through Ubuntu) and there are no issues (plus the files can be extracted in other tools without error), the only guess I can make on the problem is that the entries inside the zip are not separated as two parts directory and then the file (also probably perhaps something related to the leading slash in the filenames?).

E.g. (the problem zip shows this for the integrity check)

not-working-integrity

Zipping the files directly in Ubuntu gives a working file but looks like this...

working-test-integrity

Here are the two files and some example code to hopefully show the error...

not-working.zip working.zip

int main( int argc, char* argv[] )
{
    if ( PHYSFS_init( NULL ) )
    {
        // This zip mounts fine (created by Ubuntu compress)
        if ( PHYSFS_mount( "working.zip", "root-good", 0 ) != 0 )
        {
            PHYSFS_Stat fileInfo0;
            if ( PHYSFS_stat( "root-good/0/test_file_0.txt", &fileInfo0 ) == 0 )
            {
                PHYSFS_ErrorCode errorCode = PHYSFS_getLastErrorCode();
                std::cout << PHYSFS_getErrorByCode( errorCode ) << std::endl;
            }
            else
            {
                std::cout << fileInfo0.filesize << std::endl;
            }

            PHYSFS_Stat fileInfo1;
            if ( PHYSFS_stat( "root-good/1/test_file_1.txt", &fileInfo1 ) == 0 )
            {
                PHYSFS_ErrorCode errorCode = PHYSFS_getLastErrorCode();
                std::cout << PHYSFS_getErrorByCode( errorCode ) << std::endl;
            }
            else
            {
                std::cout << fileInfo1.filesize << std::endl;
            }

            PHYSFS_unmount( "root-good" );
        }

        // This zip mounts but cannot find the files
        if ( PHYSFS_mount( "not-working.zip", "root-bad", 0 ) != 0 )
        {
            PHYSFS_Stat fileInfo0;
            if ( PHYSFS_stat( "root-bad/0/test_file_0.txt", &fileInfo0 ) == 0 )
            {
                PHYSFS_ErrorCode errorCode = PHYSFS_getLastErrorCode();
                std::cout << PHYSFS_getErrorByCode( errorCode ) << std::endl;
            }
            else
            {
                std::cout << fileInfo0.filesize << std::endl;
            }

            PHYSFS_Stat fileInfo1;
            if ( PHYSFS_stat( "root-bad/1/test_file_1.txt", &fileInfo1 ) == 0 )
            {
                PHYSFS_ErrorCode errorCode = PHYSFS_getLastErrorCode();
                std::cout << PHYSFS_getErrorByCode( errorCode ) << std::endl;
            }
            else
            {
                std::cout << fileInfo1.filesize << std::endl;
            }

            PHYSFS_unmount( "root-bad" );
        }
        PHYSFS_deinit();
    }
}

Thanks in advance for any enlightenment on this :)

jm-seabery avatar Sep 12 '23 11:09 jm-seabery

According to https://pkwaredownloads.blob.core.windows.net/pem/APPNOTE.txt

4.4.17.1 The name of the file, with optional relative path. The path stored MUST NOT contain a drive or device letter, or a leading slash.

Probably confuses DirTree lookup but not detected/handled when parsing the central archive during mount.

undernorthernsky avatar Apr 20 '24 18:04 undernorthernsky