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.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
using DiscUtils;
|
using DiscUtils;
|
||||||
using LibHac.IO;
|
using LibHac.IO;
|
||||||
|
|
||||||
using DirectoryEntry = LibHac.IO.DirectoryEntry;
|
using DirectoryEntry = LibHac.IO.DirectoryEntry;
|
||||||
using IFileSystem = LibHac.IO.IFileSystem;
|
using IFileSystem = LibHac.IO.IFileSystem;
|
||||||
|
|
||||||
|
@ -26,20 +29,19 @@ namespace LibHac.Nand
|
||||||
|
|
||||||
public IEnumerable<DirectoryEntry> Read()
|
public IEnumerable<DirectoryEntry> Read()
|
||||||
{
|
{
|
||||||
if (Mode.HasFlag(OpenDirectoryMode.Directories))
|
foreach (DiscFileSystemInfo entry in DirInfo.GetFileSystemInfos())
|
||||||
{
|
{
|
||||||
foreach (DiscDirectoryInfo dir in DirInfo.GetDirectories())
|
bool isDir = (entry.Attributes & FileAttributes.Directory) != 0;
|
||||||
{
|
|
||||||
yield return new DirectoryEntry(dir.Name, FullPath + '/' + dir.Name, DirectoryEntryType.Directory, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Mode.HasFlag(OpenDirectoryMode.Files))
|
if (!CanReturnEntry(isDir, Mode)) continue;
|
||||||
{
|
|
||||||
foreach (DiscFileInfo file in DirInfo.GetFiles())
|
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;
|
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))
|
if (CanReturnEntry(isDir, Mode)) count++;
|
||||||
{
|
|
||||||
count += DirInfo.GetFiles().Length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 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);
|
throw new FileNotFoundException(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public FileAttributes GetFileAttributes(string path)
|
public NxFileAttributes GetFileAttributes(string path)
|
||||||
{
|
{
|
||||||
path = ToDiscUtilsPath(PathTools.Normalize(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));
|
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)
|
public long GetFileSize(string path)
|
||||||
|
|
|
@ -23,19 +23,18 @@ namespace LibHac.IO
|
||||||
{
|
{
|
||||||
foreach (DirectoryEntry entry in ParentDirectory.Read())
|
foreach (DirectoryEntry entry in ParentDirectory.Read())
|
||||||
{
|
{
|
||||||
bool isSplit = ParentFileSystem.IsSplitFile(entry.FullPath);
|
bool isSplit = ConcatenationFileSystem.HasConcatenationFileAttribute(entry.Attributes);
|
||||||
|
|
||||||
if (!CanReturnEntry(entry, isSplit)) continue;
|
if (!CanReturnEntry(entry, isSplit)) continue;
|
||||||
|
|
||||||
if (!isSplit)
|
if (isSplit)
|
||||||
{
|
{
|
||||||
yield return entry;
|
entry.Type = DirectoryEntryType.File;
|
||||||
}
|
entry.Size = ParentFileSystem.GetConcatenationFileSize(entry.FullPath);
|
||||||
else
|
entry.Attributes = NxFileAttributes.None;
|
||||||
{
|
|
||||||
long size = ParentFileSystem.GetConcatenationFileSize(entry.FullPath);
|
|
||||||
yield return new DirectoryEntry(entry.Name, entry.FullPath, DirectoryEntryType.File, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
yield return entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +44,7 @@ namespace LibHac.IO
|
||||||
|
|
||||||
foreach (DirectoryEntry entry in ParentDirectory.Read())
|
foreach (DirectoryEntry entry in ParentDirectory.Read())
|
||||||
{
|
{
|
||||||
bool isSplit = ParentFileSystem.IsSplitFile(entry.FullPath);
|
bool isSplit = ConcatenationFileSystem.HasConcatenationFileAttribute(entry.Attributes);
|
||||||
|
|
||||||
if (CanReturnEntry(entry, isSplit)) count++;
|
if (CanReturnEntry(entry, isSplit)) count++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,11 +18,14 @@ namespace LibHac.IO
|
||||||
SplitFileSize = splitFileSize;
|
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)
|
public void CreateDirectory(string path)
|
||||||
|
@ -51,10 +54,10 @@ namespace LibHac.IO
|
||||||
|
|
||||||
// A concatenation file directory can't contain normal files
|
// A concatenation file directory can't contain normal files
|
||||||
string parentDir = PathTools.GetParentDirectory(path);
|
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);
|
BaseFileSystem.CreateDirectory(path);
|
||||||
FileAttributes attributes = BaseFileSystem.GetFileAttributes(path) | FileAttributes.Archive;
|
NxFileAttributes attributes = BaseFileSystem.GetFileAttributes(path) | NxFileAttributes.Archive;
|
||||||
BaseFileSystem.SetFileAttributes(path, attributes);
|
BaseFileSystem.SetFileAttributes(path, attributes);
|
||||||
|
|
||||||
long remaining = size;
|
long remaining = size;
|
||||||
|
@ -74,7 +77,7 @@ namespace LibHac.IO
|
||||||
{
|
{
|
||||||
path = PathTools.Normalize(path);
|
path = PathTools.Normalize(path);
|
||||||
|
|
||||||
if (IsSplitFile(path))
|
if (IsConcatenationFile(path))
|
||||||
{
|
{
|
||||||
throw new DirectoryNotFoundException(path);
|
throw new DirectoryNotFoundException(path);
|
||||||
}
|
}
|
||||||
|
@ -86,7 +89,7 @@ namespace LibHac.IO
|
||||||
{
|
{
|
||||||
path = PathTools.Normalize(path);
|
path = PathTools.Normalize(path);
|
||||||
|
|
||||||
if (!IsSplitFile(path))
|
if (!IsConcatenationFile(path))
|
||||||
{
|
{
|
||||||
BaseFileSystem.DeleteFile(path);
|
BaseFileSystem.DeleteFile(path);
|
||||||
}
|
}
|
||||||
|
@ -105,7 +108,7 @@ namespace LibHac.IO
|
||||||
{
|
{
|
||||||
path = PathTools.Normalize(path);
|
path = PathTools.Normalize(path);
|
||||||
|
|
||||||
if (IsSplitFile(path))
|
if (IsConcatenationFile(path))
|
||||||
{
|
{
|
||||||
throw new DirectoryNotFoundException(path);
|
throw new DirectoryNotFoundException(path);
|
||||||
}
|
}
|
||||||
|
@ -119,7 +122,7 @@ namespace LibHac.IO
|
||||||
{
|
{
|
||||||
path = PathTools.Normalize(path);
|
path = PathTools.Normalize(path);
|
||||||
|
|
||||||
if (!IsSplitFile(path))
|
if (!IsConcatenationFile(path))
|
||||||
{
|
{
|
||||||
return BaseFileSystem.OpenFile(path, mode);
|
return BaseFileSystem.OpenFile(path, mode);
|
||||||
}
|
}
|
||||||
|
@ -143,7 +146,7 @@ namespace LibHac.IO
|
||||||
srcPath = PathTools.Normalize(srcPath);
|
srcPath = PathTools.Normalize(srcPath);
|
||||||
dstPath = PathTools.Normalize(dstPath);
|
dstPath = PathTools.Normalize(dstPath);
|
||||||
|
|
||||||
if (IsSplitFile(srcPath))
|
if (IsConcatenationFile(srcPath))
|
||||||
{
|
{
|
||||||
throw new DirectoryNotFoundException();
|
throw new DirectoryNotFoundException();
|
||||||
}
|
}
|
||||||
|
@ -156,7 +159,7 @@ namespace LibHac.IO
|
||||||
srcPath = PathTools.Normalize(srcPath);
|
srcPath = PathTools.Normalize(srcPath);
|
||||||
dstPath = PathTools.Normalize(dstPath);
|
dstPath = PathTools.Normalize(dstPath);
|
||||||
|
|
||||||
if (IsSplitFile(srcPath))
|
if (IsConcatenationFile(srcPath))
|
||||||
{
|
{
|
||||||
BaseFileSystem.RenameDirectory(srcPath, dstPath);
|
BaseFileSystem.RenameDirectory(srcPath, dstPath);
|
||||||
}
|
}
|
||||||
|
@ -170,21 +173,21 @@ namespace LibHac.IO
|
||||||
{
|
{
|
||||||
path = PathTools.Normalize(path);
|
path = PathTools.Normalize(path);
|
||||||
|
|
||||||
return BaseFileSystem.DirectoryExists(path) && !IsSplitFile(path);
|
return BaseFileSystem.DirectoryExists(path) && !IsConcatenationFile(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool FileExists(string path)
|
public bool FileExists(string path)
|
||||||
{
|
{
|
||||||
path = PathTools.Normalize(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)
|
public DirectoryEntryType GetEntryType(string path)
|
||||||
{
|
{
|
||||||
path = PathTools.Normalize(path);
|
path = PathTools.Normalize(path);
|
||||||
|
|
||||||
if (IsSplitFile(path)) return DirectoryEntryType.File;
|
if (IsConcatenationFile(path)) return DirectoryEntryType.File;
|
||||||
|
|
||||||
return BaseFileSystem.GetEntryType(path);
|
return BaseFileSystem.GetEntryType(path);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
namespace LibHac.IO
|
using System;
|
||||||
|
|
||||||
|
namespace LibHac.IO
|
||||||
{
|
{
|
||||||
public class DirectoryEntry
|
public class DirectoryEntry
|
||||||
{
|
{
|
||||||
public string Name { get; }
|
public string Name { get; set; }
|
||||||
public string FullPath { get; }
|
public string FullPath { get; set; }
|
||||||
public DirectoryEntryType Type { get; }
|
public NxFileAttributes Attributes { get; set; }
|
||||||
public long Size { get; }
|
public DirectoryEntryType Type { get; set; }
|
||||||
|
public long Size { get; set; }
|
||||||
|
|
||||||
public DirectoryEntry(string name, string fullPath, DirectoryEntryType type, long size)
|
public DirectoryEntry(string name, string fullPath, DirectoryEntryType type, long size)
|
||||||
{
|
{
|
||||||
|
@ -21,4 +24,12 @@
|
||||||
Directory,
|
Directory,
|
||||||
File
|
File
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
public enum NxFileAttributes
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
Directory = 1 << 0,
|
||||||
|
Archive = 1 << 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -166,6 +166,17 @@ namespace LibHac.IO
|
||||||
name.AsSpan(), ignoreCase);
|
name.AsSpan(), ignoreCase);
|
||||||
#endif
|
#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]
|
[Flags]
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
using System.IO;
|
namespace LibHac.IO
|
||||||
|
|
||||||
namespace LibHac.IO
|
|
||||||
{
|
{
|
||||||
public interface IAttributeFileSystem : IFileSystem
|
public interface IAttributeFileSystem : IFileSystem
|
||||||
{
|
{
|
||||||
FileAttributes GetFileAttributes(string path);
|
NxFileAttributes GetFileAttributes(string path);
|
||||||
void SetFileAttributes(string path, FileAttributes attributes);
|
void SetFileAttributes(string path, NxFileAttributes attributes);
|
||||||
long GetFileSize(string path);
|
long GetFileSize(string path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace LibHac.IO
|
namespace LibHac.IO
|
||||||
{
|
{
|
||||||
|
@ -25,20 +25,19 @@ namespace LibHac.IO
|
||||||
|
|
||||||
public IEnumerable<DirectoryEntry> Read()
|
public IEnumerable<DirectoryEntry> Read()
|
||||||
{
|
{
|
||||||
if (Mode.HasFlag(OpenDirectoryMode.Directories))
|
foreach (FileSystemInfo entry in DirInfo.EnumerateFileSystemInfos())
|
||||||
{
|
{
|
||||||
foreach (DirectoryInfo dir in DirInfo.EnumerateDirectories())
|
bool isDir = (entry.Attributes & FileAttributes.Directory) != 0;
|
||||||
{
|
|
||||||
yield return new DirectoryEntry(dir.Name, FullPath + '/' + dir.Name, DirectoryEntryType.Directory, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Mode.HasFlag(OpenDirectoryMode.Files))
|
if (!CanReturnEntry(isDir, Mode)) continue;
|
||||||
{
|
|
||||||
foreach (FileInfo file in DirInfo.EnumerateFiles())
|
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;
|
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))
|
if (CanReturnEntry(isDir, Mode)) count++;
|
||||||
{
|
|
||||||
count += DirInfo.EnumerateFiles().Count();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 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('/'));
|
return Path.Combine(BasePath, path.TrimStart('/'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public FileAttributes GetFileAttributes(string path)
|
public NxFileAttributes GetFileAttributes(string path)
|
||||||
{
|
{
|
||||||
path = PathTools.Normalize(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);
|
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)
|
public long GetFileSize(string path)
|
||||||
|
|
|
@ -10,7 +10,6 @@ namespace LibHac.IO
|
||||||
public class PartitionFileSystemBuilder
|
public class PartitionFileSystemBuilder
|
||||||
{
|
{
|
||||||
private const int HeaderSize = 0x10;
|
private const int HeaderSize = 0x10;
|
||||||
private const int MetaDataAlignment = 0x20;
|
|
||||||
|
|
||||||
private List<Entry> Entries { get; } = new List<Entry>();
|
private List<Entry> Entries { get; } = new List<Entry>();
|
||||||
private long CurrentOffset { get; set; }
|
private long CurrentOffset { get; set; }
|
||||||
|
|
Loading…
Reference in a new issue