xoofx / zio

A cross-platform abstract/virtual filesystem framework with many built-ins filesystems for .NET
BSD 2-Clause "Simplified" License
806 stars 61 forks source link

ZipArchiveFS `DirectoryExists` doesn't work as expected #79

Closed Banane9 closed 1 month ago

Banane9 commented 9 months ago

Unless DirectoryEntries have been created using Zio, DirectoryExists on ZipArchiveFileSystems will return false for any path except the root, despite files containing the path existing.

While zip files themselves have no notion of directories, it is inconsistent and inconvenient if this is not handled uniformly by this abstration layer.

This is occuring while using Zio as a NuGet package on .net 4.6.2

Banane9 commented 9 months ago

Okay, can't even Open any files, even with paths returned by EnumeratePaths (which also doesn't work outside of the root folder).

I suspect it has to do with the conditionals replacing / with \ only for .net 4.5, but nothing else and another version of the package being used on .net 4.6.2 by default.

Banane9 commented 9 months ago

Okay - it was actually the opposite.

Forcing it to use the netstandard2.0 version made accessing files work, at least. Haven't checked the directory test.

GerardSmit commented 7 months ago

Maybe related, in ZipArchiveFileSystem.cs there is a comment:

// .Net4.5 uses a backslash as directory separator.

and then the string is fullname is being replaced with the correct separator:

https://github.com/xoofx/zio/blob/a563d0c58ff7b816ce9fe9783ad1df40e35ab923/src/Zio/FileSystems/ZipArchiveFileSystem.cs#L59-L69 However, .Replace returns a new string; it doesn't manipulate the current string. So the result is never being used.

I think this code has to be moved into the .ToDictionary:

https://github.com/xoofx/zio/blob/a563d0c58ff7b816ce9fe9783ad1df40e35ab923/src/Zio/FileSystems/ZipArchiveFileSystem.cs#L72

To for example:

_entries = _archive.Entries.ToDictionary(e =>
{
#if NETFRAMEWORK // .Net4.5 uses a backslash as directory separator 
    var fullName = e.FullName.Replace('/', DirectorySeparator);
#else 
    var fullName = e.FullName.Replace('\\', DirectorySeparator); 
#endif 

    return fullName.ToLowerInvariant();
}, e => e); 

However, if you install the NuGet package as .NET Standard 2.0 in .NET Framework, it will use the '\\'-separator. I'm not sure if that's a problem.