mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Add an Attribute field to DirectoryEntry
Makes the behavior more like FS
This commit is contained in:
parent
bc986a4d0b
commit
f3d7054c79
10 changed files with 115 additions and 77 deletions
|
@ -1,6 +1,9 @@
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using DiscUtils;
|
||||
using LibHac.IO;
|
||||
|
||||
using DirectoryEntry = LibHac.IO.DirectoryEntry;
|
||||
using IFileSystem = LibHac.IO.IFileSystem;
|
||||
|
||||
|
@ -26,20 +29,19 @@ namespace LibHac.Nand
|
|||
|
||||
public IEnumerable<DirectoryEntry> Read()
|
||||
{
|
||||
if (Mode.HasFlag(OpenDirectoryMode.Directories))
|
||||
foreach (DiscFileSystemInfo entry in DirInfo.GetFileSystemInfos())
|
||||
{
|
||||
foreach (DiscDirectoryInfo dir in DirInfo.GetDirectories())
|
||||
{
|
||||
yield return new DirectoryEntry(dir.Name, FullPath + '/' + dir.Name, DirectoryEntryType.Directory, 0);
|
||||
}
|
||||
}
|
||||
bool isDir = (entry.Attributes & FileAttributes.Directory) != 0;
|
||||
|
||||
if (Mode.HasFlag(OpenDirectoryMode.Files))
|
||||
{
|
||||
foreach (DiscFileInfo file in DirInfo.GetFiles())
|
||||
if (!CanReturnEntry(isDir, Mode)) continue;
|
||||
|
||||
DirectoryEntryType type = isDir ? DirectoryEntryType.File : DirectoryEntryType.Directory;
|
||||
long length = isDir ? 0 : ((DiscFileInfo)entry).Length;
|
||||
|
||||
yield return new DirectoryEntry(entry.Name, FullPath + '/' + entry.Name, type, length)
|
||||
{
|
||||
yield return new DirectoryEntry(file.Name, FullPath + '/' + file.Name, DirectoryEntryType.File, file.Length);
|
||||
}
|
||||
Attributes = entry.Attributes.ToNxAttributes()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -47,17 +49,21 @@ namespace LibHac.Nand
|
|||
{
|
||||
int count = 0;
|
||||
|
||||
if (Mode.HasFlag(OpenDirectoryMode.Directories))
|
||||
foreach (DiscFileSystemInfo entry in DirInfo.GetFileSystemInfos())
|
||||
{
|
||||
count += DirInfo.GetDirectories().Length;
|
||||
}
|
||||
bool isDir = (entry.Attributes & FileAttributes.Directory) != 0;
|
||||
|
||||
if (Mode.HasFlag(OpenDirectoryMode.Files))
|
||||
{
|
||||
count += DirInfo.GetFiles().Length;
|
||||
if (CanReturnEntry(isDir, Mode)) count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static bool CanReturnEntry(bool isDir, OpenDirectoryMode mode)
|
||||
{
|
||||
return isDir && (mode & OpenDirectoryMode.Directories) != 0 ||
|
||||
!isDir && (mode & OpenDirectoryMode.Files) != 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,18 +68,21 @@ namespace LibHac.Nand
|
|||
throw new FileNotFoundException(path);
|
||||
}
|
||||
|
||||
public FileAttributes GetFileAttributes(string path)
|
||||
public NxFileAttributes GetFileAttributes(string path)
|
||||
{
|
||||
path = ToDiscUtilsPath(PathTools.Normalize(path));
|
||||
|
||||
return Fs.GetAttributes(path);
|
||||
return Fs.GetAttributes(path).ToNxAttributes();
|
||||
}
|
||||
|
||||
public void SetFileAttributes(string path, FileAttributes attributes)
|
||||
public void SetFileAttributes(string path, NxFileAttributes attributes)
|
||||
{
|
||||
path = ToDiscUtilsPath(PathTools.Normalize(path));
|
||||
|
||||
Fs.SetAttributes(path, attributes);
|
||||
FileAttributes attributesOld = File.GetAttributes(path);
|
||||
FileAttributes attributesNew = attributesOld.ApplyNxAttributes(attributes);
|
||||
|
||||
Fs.SetAttributes(path, attributesNew);
|
||||
}
|
||||
|
||||
public long GetFileSize(string path)
|
||||
|
|
|
@ -23,19 +23,18 @@ namespace LibHac.IO
|
|||
{
|
||||
foreach (DirectoryEntry entry in ParentDirectory.Read())
|
||||
{
|
||||
bool isSplit = ParentFileSystem.IsSplitFile(entry.FullPath);
|
||||
bool isSplit = ConcatenationFileSystem.HasConcatenationFileAttribute(entry.Attributes);
|
||||
|
||||
if (!CanReturnEntry(entry, isSplit)) continue;
|
||||
|
||||
if (!isSplit)
|
||||
if (isSplit)
|
||||
{
|
||||
yield return entry;
|
||||
}
|
||||
else
|
||||
{
|
||||
long size = ParentFileSystem.GetConcatenationFileSize(entry.FullPath);
|
||||
yield return new DirectoryEntry(entry.Name, entry.FullPath, DirectoryEntryType.File, size);
|
||||
entry.Type = DirectoryEntryType.File;
|
||||
entry.Size = ParentFileSystem.GetConcatenationFileSize(entry.FullPath);
|
||||
entry.Attributes = NxFileAttributes.None;
|
||||
}
|
||||
|
||||
yield return entry;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -45,7 +44,7 @@ namespace LibHac.IO
|
|||
|
||||
foreach (DirectoryEntry entry in ParentDirectory.Read())
|
||||
{
|
||||
bool isSplit = ParentFileSystem.IsSplitFile(entry.FullPath);
|
||||
bool isSplit = ConcatenationFileSystem.HasConcatenationFileAttribute(entry.Attributes);
|
||||
|
||||
if (CanReturnEntry(entry, isSplit)) count++;
|
||||
}
|
||||
|
|
|
@ -18,11 +18,14 @@ namespace LibHac.IO
|
|||
SplitFileSize = splitFileSize;
|
||||
}
|
||||
|
||||
internal bool IsSplitFile(string path)
|
||||
internal bool IsConcatenationFile(string path)
|
||||
{
|
||||
FileAttributes attributes = BaseFileSystem.GetFileAttributes(path);
|
||||
return HasConcatenationFileAttribute(BaseFileSystem.GetFileAttributes(path));
|
||||
}
|
||||
|
||||
return (attributes & FileAttributes.Directory) != 0 && (attributes & FileAttributes.Archive) != 0;
|
||||
internal static bool HasConcatenationFileAttribute(NxFileAttributes attributes)
|
||||
{
|
||||
return (attributes & NxFileAttributes.Directory) != 0 && (attributes & NxFileAttributes.Archive) != 0;
|
||||
}
|
||||
|
||||
public void CreateDirectory(string path)
|
||||
|
@ -51,10 +54,10 @@ namespace LibHac.IO
|
|||
|
||||
// A concatenation file directory can't contain normal files
|
||||
string parentDir = PathTools.GetParentDirectory(path);
|
||||
if (IsSplitFile(parentDir)) throw new IOException("Cannot create files inside of a concatenation file");
|
||||
if (IsConcatenationFile(parentDir)) throw new IOException("Cannot create files inside of a concatenation file");
|
||||
|
||||
BaseFileSystem.CreateDirectory(path);
|
||||
FileAttributes attributes = BaseFileSystem.GetFileAttributes(path) | FileAttributes.Archive;
|
||||
NxFileAttributes attributes = BaseFileSystem.GetFileAttributes(path) | NxFileAttributes.Archive;
|
||||
BaseFileSystem.SetFileAttributes(path, attributes);
|
||||
|
||||
long remaining = size;
|
||||
|
@ -74,7 +77,7 @@ namespace LibHac.IO
|
|||
{
|
||||
path = PathTools.Normalize(path);
|
||||
|
||||
if (IsSplitFile(path))
|
||||
if (IsConcatenationFile(path))
|
||||
{
|
||||
throw new DirectoryNotFoundException(path);
|
||||
}
|
||||
|
@ -86,7 +89,7 @@ namespace LibHac.IO
|
|||
{
|
||||
path = PathTools.Normalize(path);
|
||||
|
||||
if (!IsSplitFile(path))
|
||||
if (!IsConcatenationFile(path))
|
||||
{
|
||||
BaseFileSystem.DeleteFile(path);
|
||||
}
|
||||
|
@ -105,7 +108,7 @@ namespace LibHac.IO
|
|||
{
|
||||
path = PathTools.Normalize(path);
|
||||
|
||||
if (IsSplitFile(path))
|
||||
if (IsConcatenationFile(path))
|
||||
{
|
||||
throw new DirectoryNotFoundException(path);
|
||||
}
|
||||
|
@ -119,7 +122,7 @@ namespace LibHac.IO
|
|||
{
|
||||
path = PathTools.Normalize(path);
|
||||
|
||||
if (!IsSplitFile(path))
|
||||
if (!IsConcatenationFile(path))
|
||||
{
|
||||
return BaseFileSystem.OpenFile(path, mode);
|
||||
}
|
||||
|
@ -143,7 +146,7 @@ namespace LibHac.IO
|
|||
srcPath = PathTools.Normalize(srcPath);
|
||||
dstPath = PathTools.Normalize(dstPath);
|
||||
|
||||
if (IsSplitFile(srcPath))
|
||||
if (IsConcatenationFile(srcPath))
|
||||
{
|
||||
throw new DirectoryNotFoundException();
|
||||
}
|
||||
|
@ -156,7 +159,7 @@ namespace LibHac.IO
|
|||
srcPath = PathTools.Normalize(srcPath);
|
||||
dstPath = PathTools.Normalize(dstPath);
|
||||
|
||||
if (IsSplitFile(srcPath))
|
||||
if (IsConcatenationFile(srcPath))
|
||||
{
|
||||
BaseFileSystem.RenameDirectory(srcPath, dstPath);
|
||||
}
|
||||
|
@ -170,21 +173,21 @@ namespace LibHac.IO
|
|||
{
|
||||
path = PathTools.Normalize(path);
|
||||
|
||||
return BaseFileSystem.DirectoryExists(path) && !IsSplitFile(path);
|
||||
return BaseFileSystem.DirectoryExists(path) && !IsConcatenationFile(path);
|
||||
}
|
||||
|
||||
public bool FileExists(string path)
|
||||
{
|
||||
path = PathTools.Normalize(path);
|
||||
|
||||
return BaseFileSystem.FileExists(path) || BaseFileSystem.DirectoryExists(path) && IsSplitFile(path);
|
||||
return BaseFileSystem.FileExists(path) || BaseFileSystem.DirectoryExists(path) && IsConcatenationFile(path);
|
||||
}
|
||||
|
||||
public DirectoryEntryType GetEntryType(string path)
|
||||
{
|
||||
path = PathTools.Normalize(path);
|
||||
|
||||
if (IsSplitFile(path)) return DirectoryEntryType.File;
|
||||
if (IsConcatenationFile(path)) return DirectoryEntryType.File;
|
||||
|
||||
return BaseFileSystem.GetEntryType(path);
|
||||
}
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
namespace LibHac.IO
|
||||
using System;
|
||||
|
||||
namespace LibHac.IO
|
||||
{
|
||||
public class DirectoryEntry
|
||||
{
|
||||
public string Name { get; }
|
||||
public string FullPath { get; }
|
||||
public DirectoryEntryType Type { get; }
|
||||
public long Size { get; }
|
||||
public string Name { get; set; }
|
||||
public string FullPath { get; set; }
|
||||
public NxFileAttributes Attributes { get; set; }
|
||||
public DirectoryEntryType Type { get; set; }
|
||||
public long Size { get; set; }
|
||||
|
||||
public DirectoryEntry(string name, string fullPath, DirectoryEntryType type, long size)
|
||||
{
|
||||
|
@ -21,4 +24,12 @@
|
|||
Directory,
|
||||
File
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum NxFileAttributes
|
||||
{
|
||||
None = 0,
|
||||
Directory = 1 << 0,
|
||||
Archive = 1 << 1
|
||||
}
|
||||
}
|
||||
|
|
|
@ -166,6 +166,17 @@ namespace LibHac.IO
|
|||
name.AsSpan(), ignoreCase);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static NxFileAttributes ToNxAttributes(this FileAttributes attributes)
|
||||
{
|
||||
return (NxFileAttributes)(((int)attributes >> 4) & 3);
|
||||
}
|
||||
|
||||
public static FileAttributes ApplyNxAttributes(this FileAttributes attributes, NxFileAttributes nxAttributes)
|
||||
{
|
||||
var nxAttributeBits = (FileAttributes)(((int)attributes & 3) << 4);
|
||||
return attributes | nxAttributeBits;
|
||||
}
|
||||
}
|
||||
|
||||
[Flags]
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
using System.IO;
|
||||
|
||||
namespace LibHac.IO
|
||||
namespace LibHac.IO
|
||||
{
|
||||
public interface IAttributeFileSystem : IFileSystem
|
||||
{
|
||||
FileAttributes GetFileAttributes(string path);
|
||||
void SetFileAttributes(string path, FileAttributes attributes);
|
||||
NxFileAttributes GetFileAttributes(string path);
|
||||
void SetFileAttributes(string path, NxFileAttributes attributes);
|
||||
long GetFileSize(string path);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace LibHac.IO
|
||||
{
|
||||
|
@ -25,20 +25,19 @@ namespace LibHac.IO
|
|||
|
||||
public IEnumerable<DirectoryEntry> Read()
|
||||
{
|
||||
if (Mode.HasFlag(OpenDirectoryMode.Directories))
|
||||
foreach (FileSystemInfo entry in DirInfo.EnumerateFileSystemInfos())
|
||||
{
|
||||
foreach (DirectoryInfo dir in DirInfo.EnumerateDirectories())
|
||||
{
|
||||
yield return new DirectoryEntry(dir.Name, FullPath + '/' + dir.Name, DirectoryEntryType.Directory, 0);
|
||||
}
|
||||
}
|
||||
bool isDir = (entry.Attributes & FileAttributes.Directory) != 0;
|
||||
|
||||
if (Mode.HasFlag(OpenDirectoryMode.Files))
|
||||
{
|
||||
foreach (FileInfo file in DirInfo.EnumerateFiles())
|
||||
if (!CanReturnEntry(isDir, Mode)) continue;
|
||||
|
||||
DirectoryEntryType type = isDir ? DirectoryEntryType.Directory : DirectoryEntryType.File;
|
||||
long length = isDir ? 0 : ((FileInfo)entry).Length;
|
||||
|
||||
yield return new DirectoryEntry(entry.Name, FullPath + '/' + entry.Name, type, length)
|
||||
{
|
||||
yield return new DirectoryEntry(file.Name, FullPath + '/' + file.Name, DirectoryEntryType.File, file.Length);
|
||||
}
|
||||
Attributes = entry.Attributes.ToNxAttributes()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,17 +45,21 @@ namespace LibHac.IO
|
|||
{
|
||||
int count = 0;
|
||||
|
||||
if (Mode.HasFlag(OpenDirectoryMode.Directories))
|
||||
foreach (FileSystemInfo entry in DirInfo.EnumerateFileSystemInfos())
|
||||
{
|
||||
count += DirInfo.EnumerateDirectories().Count();
|
||||
}
|
||||
bool isDir = (entry.Attributes & FileAttributes.Directory) != 0;
|
||||
|
||||
if (Mode.HasFlag(OpenDirectoryMode.Files))
|
||||
{
|
||||
count += DirInfo.EnumerateFiles().Count();
|
||||
if (CanReturnEntry(isDir, Mode)) count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static bool CanReturnEntry(bool isDir, OpenDirectoryMode mode)
|
||||
{
|
||||
return isDir && (mode & OpenDirectoryMode.Directories) != 0 ||
|
||||
!isDir && (mode & OpenDirectoryMode.Files) != 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,16 +26,21 @@ namespace LibHac.IO
|
|||
return Path.Combine(BasePath, path.TrimStart('/'));
|
||||
}
|
||||
|
||||
public FileAttributes GetFileAttributes(string path)
|
||||
public NxFileAttributes GetFileAttributes(string path)
|
||||
{
|
||||
path = PathTools.Normalize(path);
|
||||
return File.GetAttributes(ResolveLocalPath(path));
|
||||
return File.GetAttributes(ResolveLocalPath(path)).ToNxAttributes();
|
||||
}
|
||||
|
||||
public void SetFileAttributes(string path, FileAttributes attributes)
|
||||
public void SetFileAttributes(string path, NxFileAttributes attributes)
|
||||
{
|
||||
path = PathTools.Normalize(path);
|
||||
File.SetAttributes(ResolveLocalPath(path), attributes);
|
||||
string localPath = ResolveLocalPath(path);
|
||||
|
||||
FileAttributes attributesOld = File.GetAttributes(localPath);
|
||||
FileAttributes attributesNew = attributesOld.ApplyNxAttributes(attributes);
|
||||
|
||||
File.SetAttributes(localPath, attributesNew);
|
||||
}
|
||||
|
||||
public long GetFileSize(string path)
|
||||
|
|
|
@ -10,7 +10,6 @@ namespace LibHac.IO
|
|||
public class PartitionFileSystemBuilder
|
||||
{
|
||||
private const int HeaderSize = 0x10;
|
||||
private const int MetaDataAlignment = 0x20;
|
||||
|
||||
private List<Entry> Entries { get; } = new List<Entry>();
|
||||
private long CurrentOffset { get; set; }
|
||||
|
|
Loading…
Reference in a new issue