diff --git a/.gitignore b/.gitignore index ec5b7e6..20f9887 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ obj/ riderModule.iml /.idea/ /.vs/ -/_ReSharper.Caches/ \ No newline at end of file +/_ReSharper.Caches/ +.idea \ No newline at end of file diff --git a/WinAVFS.CLI/7z_amd64.dll b/WinAVFS.CLI/7z_amd64.dll deleted file mode 100644 index 0ba2232..0000000 Binary files a/WinAVFS.CLI/7z_amd64.dll and /dev/null differ diff --git a/WinAVFS.CLI/7z_x86.dll b/WinAVFS.CLI/7z_x86.dll deleted file mode 100644 index e5ae0c9..0000000 Binary files a/WinAVFS.CLI/7z_x86.dll and /dev/null differ diff --git a/WinAVFS.CLI/Program.cs b/WinAVFS.CLI/Program.cs deleted file mode 100644 index f36ee47..0000000 --- a/WinAVFS.CLI/Program.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using WinAVFS.Core; - -namespace WinAVFS.CLI -{ - internal class Program - { - public static void Main(string[] args) - { - if (args.Length != 2) - { - Console.WriteLine(@"Usage: WinAVFS.CLI.exe "); - Console.WriteLine(@"Example: WinAVFS.CLI.exe D:\1.zip Z:\"); - return; - } - - var fs = new ReadOnlyAVFS(new SevenZipProvider(args[0])); - fs.Mount(args[1]); - } - } -} \ No newline at end of file diff --git a/WinAVFS.CLI/Properties/AssemblyInfo.cs b/WinAVFS.CLI/Properties/AssemblyInfo.cs deleted file mode 100644 index e31aeb8..0000000 --- a/WinAVFS.CLI/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Reflection; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("WinAVFS.CLI")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("WinAVFS.CLI")] -[assembly: AssemblyCopyright("Copyright © DeepAQ 2020")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("0769F9F7-0BC5-4A7C-A8DC-BAD02D4C8E6B")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] \ No newline at end of file diff --git a/WinAVFS.CLI/WinAVFS.CLI.csproj b/WinAVFS.CLI/WinAVFS.CLI.csproj deleted file mode 100644 index 037b268..0000000 --- a/WinAVFS.CLI/WinAVFS.CLI.csproj +++ /dev/null @@ -1,71 +0,0 @@ - - - - - Debug - AnyCPU - {0769F9F7-0BC5-4A7C-A8DC-BAD02D4C8E6B} - Exe - Properties - WinAVFS.CLI - WinAVFS.CLI - v4.6 - 512 - default - - - pdbonly - true - TRACE - prompt - 4 - bin\x64\Release\ - x64 - - - true - full - false - DEBUG;TRACE - prompt - 4 - bin\x64\Debug\ - x64 - - - - - - - - - - - - - - - {0feb6b9c-fd58-4f32-b704-f1a85f967340} - WinAVFS.Core - - - - - 7z.dll - Always - - - 7z64.dll - Always - - - - - - diff --git a/WinAVFS.Core/ConcurrentObjectPool.cs b/WinAVFS.Core/ConcurrentObjectPool.cs deleted file mode 100644 index de073a2..0000000 --- a/WinAVFS.Core/ConcurrentObjectPool.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; - -namespace WinAVFS.Core -{ - public class ConcurrentObjectPool - { - private readonly ConcurrentBag pool; - private readonly Func factory; - - public ConcurrentObjectPool(Func factory) - { - this.pool = new ConcurrentBag(); - this.factory = factory; - } - - public T Get() - { - return this.pool.TryTake(out var item) ? item : factory(); - } - - public void Put(T item) - { - this.pool.Add(item); - } - - public T[] GetAll() - { - return this.pool.ToArray(); - } - } -} \ No newline at end of file diff --git a/WinAVFS.Core/FSTree.cs b/WinAVFS.Core/FSTree.cs deleted file mode 100644 index 0ddbc49..0000000 --- a/WinAVFS.Core/FSTree.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace WinAVFS.Core -{ - public class FSTree - { - public FSTreeNode Root { get; set; } - } -} \ No newline at end of file diff --git a/WinAVFS.Core/IArchiveProvider.cs b/WinAVFS.Core/IArchiveProvider.cs deleted file mode 100644 index a7229dc..0000000 --- a/WinAVFS.Core/IArchiveProvider.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using System.IO; - -namespace WinAVFS.Core -{ - public interface IArchiveProvider : IDisposable - { - FSTree ReadFSTree(); - - void ExtractFileUnmanaged(FSTreeNode node, IntPtr buffer); - } -} \ No newline at end of file diff --git a/WinAVFS.Core/SevenZipProvider.cs b/WinAVFS.Core/SevenZipProvider.cs deleted file mode 100644 index b173d15..0000000 --- a/WinAVFS.Core/SevenZipProvider.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System; -using System.IO; -using System.Runtime.InteropServices; -using SevenZip; - -namespace WinAVFS.Core -{ - public class SevenZipProvider : IArchiveProvider - { - private readonly ConcurrentObjectPool extractorPool; - - public SevenZipProvider(string path) - { - Console.WriteLine($"Loading archive {path} with 7z.dll"); - this.extractorPool = new ConcurrentObjectPool(() => new SevenZipExtractor(path)); - } - - public void Dispose() - { - foreach (var archive in this.extractorPool.GetAll()) - { - archive.Dispose(); - } - } - - public FSTree ReadFSTree() - { - var extractor = this.extractorPool.Get(); - var root = new FSTreeNode(true); - foreach (var entry in extractor.ArchiveFileData) - { - // Console.WriteLine($"Loading {entry.FileName} into FS tree"); - var paths = entry.FileName.Split('/', '\\'); - var node = root; - for (var i = 0; i < paths.Length - 1; i++) - { - node = node.GetOrAddChild(true, paths[i]); - } - - if (!string.IsNullOrEmpty(paths[paths.Length - 1])) - { - node = node.GetOrAddChild(entry.IsDirectory, paths[paths.Length - 1], (long) entry.Size, - (long) entry.Size, entry.Index); - node.CreationTime = entry.CreationTime; - node.LastAccessTime = entry.LastAccessTime; - node.LastWriteTime = entry.LastWriteTime; - // if (!node.IsDirectory && node.Buffer == IntPtr.Zero) - // { - // node.Buffer = Marshal.AllocHGlobal((IntPtr) node.Length); - // } - } - } - - Console.WriteLine($"Loaded {extractor.FilesCount} entries from archive"); - this.extractorPool.Put(extractor); - return new FSTree {Root = root}; - } - - public void ExtractFileUnmanaged(FSTreeNode node, IntPtr buffer) - { - if (!(node.Context is int index)) - { - throw new ArgumentException(); - } - - unsafe - { - using var target = new UnmanagedMemoryStream((byte*) buffer.ToPointer(), node.Length, node.Length, - FileAccess.Write); - var extractor = this.extractorPool.Get(); - extractor.ExtractFile(index, target); - this.extractorPool.Put(extractor); - } - } - } -} \ No newline at end of file diff --git a/WinAVFS.Core/WinAVFS.Core.csproj b/WinAVFS.Core/WinAVFS.Core.csproj deleted file mode 100644 index 5a0d0e4..0000000 --- a/WinAVFS.Core/WinAVFS.Core.csproj +++ /dev/null @@ -1,20 +0,0 @@ - - - - net46 - default - true - Release;Debug - x64 - - - - - - - - - - - - diff --git a/WinAvfs.Cli/Program.cs b/WinAvfs.Cli/Program.cs new file mode 100644 index 0000000..dc7019d --- /dev/null +++ b/WinAvfs.Cli/Program.cs @@ -0,0 +1,45 @@ +using DokanNet; +using DokanNet.Logging; +using WinAvfs.Core; + +namespace WinAvfs.CLI +{ + public abstract class Program + { + public static void Main(string[] args) + { + if (args.Length != 2) + { + Console.WriteLine(@"Usage: WinAVFS.CLI.exe "); + Console.WriteLine(@"Example: WinAVFS.CLI.exe D:\1.zip Z:\"); + return; + } + + var pathToArchive = args[0]; + var mountPoint = args[1]; + + var provider = new ZipArchiveProvider(pathToArchive); + + var mre = new ManualResetEvent(false); + var dokanLogger = new NullLogger(); + using var dokan = new Dokan(dokanLogger); + Console.CancelKeyPress += (_, e) => + { + e.Cancel = true; + mre.Set(); + }; + + var sampleFs = new ReadOnlyAvfs(provider, provider.ReadFsTree()); + var dokanBuilder = new DokanInstanceBuilder(dokan) + .ConfigureOptions(options => + { + options.Options = DokanOptions.WriteProtection | DokanOptions.MountManager; + options.MountPoint = mountPoint; + }); + using (dokanBuilder.Build(sampleFs)) + { + mre.WaitOne(); + } + } + } +} \ No newline at end of file diff --git a/WinAvfs.Cli/WinAvfs.Cli.csproj b/WinAvfs.Cli/WinAvfs.Cli.csproj new file mode 100644 index 0000000..931ca56 --- /dev/null +++ b/WinAvfs.Cli/WinAvfs.Cli.csproj @@ -0,0 +1,24 @@ + + + Exe + net8.0 + WinAvfs.Cli + WinAvfs.Cli + false + True + true + true + enable + enable + WinAvfs + Cli + Nuget package of 'Cli' provided by WinAvfs + WinAvfs.Cli + nuget package dotnet csproj dependencies + README.md + + + + + + \ No newline at end of file diff --git a/WinAvfs.Core/FSTree.cs b/WinAvfs.Core/FSTree.cs new file mode 100644 index 0000000..63cf5e5 --- /dev/null +++ b/WinAvfs.Core/FSTree.cs @@ -0,0 +1,7 @@ +namespace WinAvfs.Core +{ + public class FsTree + { + public FsTreeNode Root { get; set; } + } +} \ No newline at end of file diff --git a/WinAVFS.Core/FSTreeNode.cs b/WinAvfs.Core/FSTreeNode.cs similarity index 54% rename from WinAVFS.Core/FSTreeNode.cs rename to WinAvfs.Core/FSTreeNode.cs index 97c29c1..27d208f 100644 --- a/WinAVFS.Core/FSTreeNode.cs +++ b/WinAvfs.Core/FSTreeNode.cs @@ -1,20 +1,18 @@ -using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; +using System.Runtime.InteropServices; -namespace WinAVFS.Core +namespace WinAvfs.Core { - public class FSTreeNode + public class FsTreeNode { - public FSTreeNode Parent { get; private set; } + public FsTreeNode Parent { get; private set; } - public string Name { get; private set; } = ""; + public string Name { get; private set; } = string.Empty; - public string FullName { get; private set; } = ""; + public string FullName { get; private set; } = string.Empty; - public long Length { get; private set; } = 0; + public long Length { get; private set; } - public long CompressedLength { get; private set; } = 0; + public long CompressedLength { get; private set; } public DateTime? CreationTime { get; internal set; } @@ -22,52 +20,52 @@ public class FSTreeNode public DateTime? LastWriteTime { get; internal set; } - public Dictionary Children { get; } + public Dictionary Children { get; } - public bool IsDirectory => this.Children != null; + public bool IsDirectory => Children != null; public object Context { get; internal set; } public IntPtr Buffer { get; internal set; } = IntPtr.Zero; - private bool extracted = false; + private bool _extracted; - public FSTreeNode() : this(false) + public FsTreeNode() : this(false) { } - public FSTreeNode(bool isDirectory) + public FsTreeNode(bool isDirectory) { if (isDirectory) { - this.Children = new Dictionary(); + Children = new Dictionary(); } } - public FSTreeNode GetOrAddChild(bool isDirectory, string name, long length = 0, long compressedLength = 0, + public FsTreeNode GetOrAddChild(bool isDirectory, string name, long length = 0, long compressedLength = 0, object context = null) { - if (this.Children == null) + if (Children == null) { return null; } var caseInsensitiveName = name.ToLower(); - if (this.Children.ContainsKey(caseInsensitiveName)) + if (Children.TryGetValue(caseInsensitiveName, out var addChild)) { - return this.Children[caseInsensitiveName]; + return addChild; } - var child = new FSTreeNode(isDirectory) + var child = new FsTreeNode(isDirectory) { Parent = this, Name = name, - FullName = $"{this.FullName}\\{name}", + FullName = $"{FullName}\\{name}", Length = length, CompressedLength = compressedLength, Context = context, }; - this.Children[caseInsensitiveName] = child; + Children[caseInsensitiveName] = child; if (!isDirectory) { @@ -85,24 +83,24 @@ public FSTreeNode GetOrAddChild(bool isDirectory, string name, long length = 0, public void FillBuffer(Action extractAction) { - if (this.extracted || this.IsDirectory) + if (_extracted || IsDirectory) { return; } lock (this) { - if (!this.extracted) + if (!_extracted) { - if (this.Buffer == IntPtr.Zero) + if (Buffer == IntPtr.Zero) { - this.Buffer = Marshal.AllocHGlobal((IntPtr) this.Length); + Buffer = Marshal.AllocHGlobal((IntPtr) Length); } try { - extractAction(this.Buffer); - this.extracted = true; + extractAction(Buffer); + _extracted = true; } catch (Exception ex) { diff --git a/WinAvfs.Core/IArchiveProvider.cs b/WinAvfs.Core/IArchiveProvider.cs new file mode 100644 index 0000000..a74e688 --- /dev/null +++ b/WinAvfs.Core/IArchiveProvider.cs @@ -0,0 +1,10 @@ + +namespace WinAvfs.Core +{ + public interface IArchiveProvider : IDisposable + { + FsTree ReadFsTree(); + + void ExtractFileUnmanaged(FsTreeNode node, IntPtr buffer); + } +} \ No newline at end of file diff --git a/WinAVFS.Core/ReadOnlyAVFS.cs b/WinAvfs.Core/ReadOnlyAVFS.cs similarity index 76% rename from WinAVFS.Core/ReadOnlyAVFS.cs rename to WinAvfs.Core/ReadOnlyAVFS.cs index d164cab..c0066c2 100644 --- a/WinAVFS.Core/ReadOnlyAVFS.cs +++ b/WinAvfs.Core/ReadOnlyAVFS.cs @@ -1,78 +1,46 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.IO; -using System.Linq; +using System.Collections.Concurrent; using System.Security.AccessControl; using DokanNet; -using DokanNet.Logging; using FileAccess = DokanNet.FileAccess; -namespace WinAVFS.Core +namespace WinAvfs.Core { - public class ReadOnlyAVFS : IDokanOperationsUnsafe + public class ReadOnlyAvfs(IArchiveProvider archiveProvider, FsTree fsTree) : IDokanOperationsUnsafe { - private IArchiveProvider archiveProvider; - private FSTree fsTree; + private static readonly FileInformation[] EmptyFileInformation = []; + private readonly DateTime _defaultTime = DateTime.Now; - public ReadOnlyAVFS(IArchiveProvider archiveProvider) - { - this.archiveProvider = archiveProvider; - } - - public void Mount(string mountPoint) - { - this.Unmount(mountPoint); - - this.fsTree = this.archiveProvider.ReadFSTree(); - this.Mount(mountPoint, DokanOptions.WriteProtection | DokanOptions.MountManager, new NullLogger()); - } - - public void Unmount(string mountPoint) - { - Dokan.RemoveMountPoint(mountPoint); - this.fsTree = null; - } + private readonly ConcurrentDictionary _nodeCache = new(); - #region Private helper methods - - private static readonly FileInformation[] EmptyFileInformation = new FileInformation[0]; - private readonly DateTime defaultTime = DateTime.Now; - - private readonly ConcurrentDictionary nodeCache = - new ConcurrentDictionary(); - - private FSTreeNode GetNode(string fileName, IDokanFileInfo info = null) + private FsTreeNode GetNode(string fileName, IDokanFileInfo info = null) { if (info?.Context != null) { - return (FSTreeNode) info.Context; + return (FsTreeNode) info.Context; } fileName = fileName.ToLower(); - if (nodeCache.TryGetValue(fileName, out var nodeFromCache)) + if (_nodeCache.TryGetValue(fileName, out var nodeFromCache)) { return nodeFromCache; } var paths = fileName.Split('\\'); - var node = this.fsTree.Root; + var node = fsTree.Root; foreach (var path in paths.Where(y => !string.IsNullOrEmpty(y))) { - if (!node.IsDirectory || !node.Children.ContainsKey(path)) + if (!node.IsDirectory || !node.Children.TryGetValue(path, out var child)) { return null; } - node = node.Children[path]; + node = child; } - nodeCache.TryAdd(fileName, node); + _nodeCache.TryAdd(fileName, node); return node; } - #endregion - #region Dokan filesystem implementation public NtStatus CreateFile(string fileName, FileAccess access, FileShare share, FileMode mode, @@ -85,7 +53,7 @@ public NtStatus CreateFile(string fileName, FileAccess access, FileShare share, if (info.Context == null) { - var node = this.GetNode(fileName); + var node = GetNode(fileName); if (node == null) { if (mode == FileMode.OpenOrCreate) @@ -123,13 +91,13 @@ public NtStatus ReadFile(string fileName, IntPtr buffer, uint bufferLength, out IDokanFileInfo info) { bytesRead = 0; - var node = this.GetNode(fileName, info); + var node = GetNode(fileName, info); if (node == null) { return NtStatus.ObjectPathNotFound; } - node.FillBuffer(buf => this.archiveProvider.ExtractFileUnmanaged(node, buf)); + node.FillBuffer(buf => archiveProvider.ExtractFileUnmanaged(node, buf)); unsafe { @@ -163,7 +131,7 @@ public NtStatus FlushFileBuffers(string fileName, IDokanFileInfo info) public NtStatus GetFileInformation(string fileName, out FileInformation fileInfo, IDokanFileInfo info) { fileInfo = new FileInformation(); - var node = this.GetNode(fileName, info); + var node = GetNode(fileName, info); if (node == null) { return NtStatus.ObjectPathNotFound; @@ -171,9 +139,9 @@ public NtStatus GetFileInformation(string fileName, out FileInformation fileInfo fileInfo.FileName = node.FullName; fileInfo.Attributes = node.IsDirectory ? FileAttributes.Directory : FileAttributes.Normal; - fileInfo.CreationTime = node.CreationTime ?? this.defaultTime; - fileInfo.LastAccessTime = node.LastAccessTime ?? this.defaultTime; - fileInfo.LastWriteTime = node.LastWriteTime ?? this.defaultTime; + fileInfo.CreationTime = node.CreationTime ?? _defaultTime; + fileInfo.LastAccessTime = node.LastAccessTime ?? _defaultTime; + fileInfo.LastWriteTime = node.LastWriteTime ?? _defaultTime; fileInfo.Length = node.Length; return NtStatus.Success; } @@ -181,7 +149,7 @@ public NtStatus GetFileInformation(string fileName, out FileInformation fileInfo public NtStatus FindFiles(string fileName, out IList files, IDokanFileInfo info) { files = EmptyFileInformation; - var node = this.GetNode(fileName, info); + var node = GetNode(fileName, info); if (node == null) { return NtStatus.ObjectPathNotFound; @@ -191,9 +159,9 @@ public NtStatus FindFiles(string fileName, out IList files, IDo { FileName = child.Value.Name, Attributes = child.Value.IsDirectory ? FileAttributes.Directory : FileAttributes.Normal, - CreationTime = child.Value.CreationTime ?? this.defaultTime, - LastAccessTime = child.Value.LastAccessTime ?? this.defaultTime, - LastWriteTime = child.Value.LastWriteTime ?? this.defaultTime, + CreationTime = child.Value.CreationTime ?? _defaultTime, + LastAccessTime = child.Value.LastAccessTime ?? _defaultTime, + LastWriteTime = child.Value.LastWriteTime ?? _defaultTime, Length = child.Value.Length }).ToList(); return NtStatus.Success; @@ -255,7 +223,9 @@ public NtStatus UnlockFile(string fileName, long offset, long length, IDokanFile public NtStatus GetDiskFreeSpace(out long freeBytesAvailable, out long totalNumberOfBytes, out long totalNumberOfFreeBytes, IDokanFileInfo info) { - freeBytesAvailable = totalNumberOfFreeBytes = totalNumberOfBytes = this.fsTree.Root.Length; + totalNumberOfBytes = fsTree.Root.Length; + freeBytesAvailable = 0; + totalNumberOfFreeBytes = 0; return NtStatus.Success; } @@ -263,7 +233,7 @@ public NtStatus GetVolumeInformation(out string volumeLabel, out FileSystemFeatu out string fileSystemName, out uint maximumComponentLength, IDokanFileInfo info) { volumeLabel = "AVFS"; - fileSystemName = "exFAT"; + fileSystemName = "avfs"; features = FileSystemFeatures.CasePreservedNames | FileSystemFeatures.UnicodeOnDisk | FileSystemFeatures.VolumeIsCompressed | FileSystemFeatures.ReadOnlyVolume; maximumComponentLength = 260; @@ -283,6 +253,12 @@ public NtStatus SetFileSecurity(string fileName, FileSystemSecurity security, Ac return NtStatus.AccessDenied; } + public NtStatus Mounted(string mountPoint, IDokanFileInfo info) + { + Console.WriteLine($"Mounted readonly filesystem at {mountPoint}"); + return NtStatus.Success; + } + public NtStatus Mounted(IDokanFileInfo info) { Console.WriteLine($"Mounted readonly filesystem"); diff --git a/WinAvfs.Core/WinAvfs.Core.csproj b/WinAvfs.Core/WinAvfs.Core.csproj new file mode 100644 index 0000000..33ce01c --- /dev/null +++ b/WinAvfs.Core/WinAvfs.Core.csproj @@ -0,0 +1,15 @@ + + + Library + net8.0 + WinAvfs.Core + WinAvfs.Core + false + false + enable + true + + + + + \ No newline at end of file diff --git a/WinAVFS.Core/ZipArchiveProvider.cs b/WinAvfs.Core/ZipArchiveProvider.cs similarity index 68% rename from WinAVFS.Core/ZipArchiveProvider.cs rename to WinAvfs.Core/ZipArchiveProvider.cs index dac364f..1c5b5bb 100644 --- a/WinAVFS.Core/ZipArchiveProvider.cs +++ b/WinAvfs.Core/ZipArchiveProvider.cs @@ -1,30 +1,28 @@ -using System; -using System.IO; -using System.IO.Compression; +using System.IO.Compression; using System.Text; -namespace WinAVFS.Core +namespace WinAvfs.Core { public class ZipArchiveProvider : IArchiveProvider { - private readonly ZipArchive archive; + private readonly ZipArchive _archive; public ZipArchiveProvider(string path) { Console.WriteLine($"Opening archive {path}"); - this.archive = new ZipArchive(new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read), + _archive = new ZipArchive(new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read), ZipArchiveMode.Read, false, Encoding.Default); } public void Dispose() { - this.archive?.Dispose(); + _archive?.Dispose(); } - public FSTree ReadFSTree() + public FsTree ReadFsTree() { - var root = new FSTreeNode(true); - foreach (var entry in archive.Entries) + var root = new FsTreeNode(true); + foreach (var entry in _archive.Entries) { Console.WriteLine($"Loading {entry.FullName} into FS tree"); var paths = entry.FullName.Split('/', '\\'); @@ -34,7 +32,7 @@ public FSTree ReadFSTree() node = node.GetOrAddChild(true, paths[i]); } - var name = paths[paths.Length - 1]; + var name = paths[^1]; if (!string.IsNullOrEmpty(name)) { node = node.GetOrAddChild(false, name, entry.Length, entry.CompressedLength, entry); @@ -44,11 +42,11 @@ public FSTree ReadFSTree() node.Context = entry; } - Console.WriteLine($"Loaded {archive.Entries.Count} entries from archive"); - return new FSTree {Root = root}; + Console.WriteLine($"Loaded {_archive.Entries.Count} entries from archive"); + return new FsTree {Root = root}; } - public void ExtractFileUnmanaged(FSTreeNode node, IntPtr buffer) + public void ExtractFileUnmanaged(FsTreeNode node, IntPtr buffer) { if (!(node.Context is ZipArchiveEntry entry)) { diff --git a/WinAVFS.sln b/WinAvfs.sln similarity index 78% rename from WinAVFS.sln rename to WinAvfs.sln index 4754999..60b6133 100644 --- a/WinAVFS.sln +++ b/WinAvfs.sln @@ -1,8 +1,8 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WinAVFS.Core", "WinAVFS.Core\WinAVFS.Core.csproj", "{0FEB6B9C-FD58-4F32-B704-F1A85F967340}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WinAvfs.Core", "WinAVFS.Core\WinAvfs.Core.csproj", "{0FEB6B9C-FD58-4F32-B704-F1A85F967340}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WinAVFS.CLI", "WinAVFS.CLI\WinAVFS.CLI.csproj", "{0769F9F7-0BC5-4A7C-A8DC-BAD02D4C8E6B}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WinAvfs.Cli", "WinAVFS.Cli\WinAvfs.Cli.csproj", "{0769F9F7-0BC5-4A7C-A8DC-BAD02D4C8E6B}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution