mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Add U8String class and some FileSystemClient functions
This commit is contained in:
parent
2f49021405
commit
4bbfa057d2
23 changed files with 455 additions and 31 deletions
|
@ -66,20 +66,18 @@ namespace LibHac.Common
|
|||
return iDest;
|
||||
}
|
||||
|
||||
public static string FromUtf8Z(this Span<byte> value) => FromUtf8Z((ReadOnlySpan<byte>)value);
|
||||
|
||||
public static string FromUtf8Z(this ReadOnlySpan<byte> value)
|
||||
public static string Utf8ToString(ReadOnlySpan<byte> value)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < value.Length && value[i] != 0; i++) { }
|
||||
|
||||
value = value.Slice(0, i);
|
||||
|
||||
#if STRING_SPAN
|
||||
return Encoding.UTF8.GetString(value);
|
||||
#else
|
||||
return Encoding.UTF8.GetString(value.ToArray());
|
||||
#endif
|
||||
}
|
||||
|
||||
public static string Utf8ZToString(ReadOnlySpan<byte> value)
|
||||
{
|
||||
return Utf8ToString(value.Slice(0, GetLength(value)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
42
src/LibHac/Common/U8Span.cs
Normal file
42
src/LibHac/Common/U8Span.cs
Normal file
|
@ -0,0 +1,42 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
|
||||
namespace LibHac.Common
|
||||
{
|
||||
[DebuggerDisplay("{ToString()}")]
|
||||
public ref struct U8Span
|
||||
{
|
||||
private readonly ReadOnlySpan<byte> _buffer;
|
||||
|
||||
public ReadOnlySpan<byte> Value => _buffer;
|
||||
public int Length => _buffer.Length;
|
||||
|
||||
public byte this[int i]
|
||||
{
|
||||
get => _buffer[i];
|
||||
}
|
||||
|
||||
public U8Span(ReadOnlySpan<byte> value)
|
||||
{
|
||||
_buffer = value;
|
||||
}
|
||||
|
||||
public U8Span(string value)
|
||||
{
|
||||
_buffer = Encoding.UTF8.GetBytes(value);
|
||||
}
|
||||
|
||||
public static implicit operator ReadOnlySpan<byte>(U8Span value) => value.Value;
|
||||
|
||||
public static explicit operator string(U8Span value) => value.ToString();
|
||||
public static explicit operator U8Span(string value) => new U8Span(value);
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return StringUtils.Utf8ToString(_buffer);
|
||||
}
|
||||
|
||||
public bool IsNull() => _buffer == default;
|
||||
}
|
||||
}
|
46
src/LibHac/Common/U8SpanMutable.cs
Normal file
46
src/LibHac/Common/U8SpanMutable.cs
Normal file
|
@ -0,0 +1,46 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
|
||||
namespace LibHac.Common
|
||||
{
|
||||
[DebuggerDisplay("{ToString()}")]
|
||||
public ref struct U8SpanMutable
|
||||
{
|
||||
private readonly Span<byte> _buffer;
|
||||
|
||||
public Span<byte> Value => _buffer;
|
||||
public int Length => _buffer.Length;
|
||||
|
||||
public byte this[int i]
|
||||
{
|
||||
get => _buffer[i];
|
||||
set => _buffer[i] = value;
|
||||
}
|
||||
|
||||
public U8SpanMutable(Span<byte> value)
|
||||
{
|
||||
_buffer = value;
|
||||
}
|
||||
|
||||
public U8SpanMutable(string value)
|
||||
{
|
||||
_buffer = Encoding.UTF8.GetBytes(value);
|
||||
}
|
||||
|
||||
public static implicit operator U8Span(U8SpanMutable value) => new U8Span(value._buffer);
|
||||
|
||||
public static implicit operator ReadOnlySpan<byte>(U8SpanMutable value) => value.Value;
|
||||
public static implicit operator Span<byte>(U8SpanMutable value) => value.Value;
|
||||
|
||||
public static explicit operator string(U8SpanMutable value) => value.ToString();
|
||||
public static explicit operator U8SpanMutable(string value) => new U8SpanMutable(value);
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return StringUtils.Utf8ZToString(_buffer);
|
||||
}
|
||||
|
||||
public bool IsNull() => _buffer == default;
|
||||
}
|
||||
}
|
41
src/LibHac/Common/U8String.cs
Normal file
41
src/LibHac/Common/U8String.cs
Normal file
|
@ -0,0 +1,41 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
|
||||
namespace LibHac.Common
|
||||
{
|
||||
[DebuggerDisplay("{ToString()}")]
|
||||
public struct U8String
|
||||
{
|
||||
private readonly byte[] _buffer;
|
||||
|
||||
public ReadOnlySpan<byte> Value => _buffer;
|
||||
public int Length => _buffer.Length;
|
||||
|
||||
public byte this[int i] => _buffer[i];
|
||||
|
||||
public U8String(byte[] value)
|
||||
{
|
||||
_buffer = value;
|
||||
}
|
||||
|
||||
public U8String(string value)
|
||||
{
|
||||
_buffer = Encoding.UTF8.GetBytes(value);
|
||||
}
|
||||
|
||||
public static implicit operator U8Span(U8String value) => new U8Span(value._buffer);
|
||||
|
||||
public static implicit operator ReadOnlySpan<byte>(U8String value) => value.Value;
|
||||
|
||||
public static explicit operator string(U8String value) => value.ToString();
|
||||
public static explicit operator U8String(string value) => new U8String(value);
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return StringUtils.Utf8ToString(_buffer);
|
||||
}
|
||||
|
||||
public bool IsNull() => _buffer == null;
|
||||
}
|
||||
}
|
15
src/LibHac/Common/U8StringHelpers.cs
Normal file
15
src/LibHac/Common/U8StringHelpers.cs
Normal file
|
@ -0,0 +1,15 @@
|
|||
namespace LibHac.Common
|
||||
{
|
||||
public static class U8StringHelpers
|
||||
{
|
||||
public static U8String AsU8String(this string value)
|
||||
{
|
||||
return new U8String(value);
|
||||
}
|
||||
|
||||
public static U8Span AsU8Span(this string value)
|
||||
{
|
||||
return new U8Span(value);
|
||||
}
|
||||
}
|
||||
}
|
48
src/LibHac/Common/U8StringMutable.cs
Normal file
48
src/LibHac/Common/U8StringMutable.cs
Normal file
|
@ -0,0 +1,48 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
|
||||
namespace LibHac.Common
|
||||
{
|
||||
[DebuggerDisplay("{ToString()}")]
|
||||
public struct U8StringMutable
|
||||
{
|
||||
private readonly byte[] _buffer;
|
||||
|
||||
public Span<byte> Value => _buffer;
|
||||
public int Length => _buffer.Length;
|
||||
|
||||
public byte this[int i]
|
||||
{
|
||||
get => _buffer[i];
|
||||
set => _buffer[i] = value;
|
||||
}
|
||||
|
||||
public U8StringMutable(byte[] value)
|
||||
{
|
||||
_buffer = value;
|
||||
}
|
||||
|
||||
public U8StringMutable(string value)
|
||||
{
|
||||
_buffer = Encoding.UTF8.GetBytes(value);
|
||||
}
|
||||
|
||||
public static implicit operator U8String(U8StringMutable value) => new U8String(value._buffer);
|
||||
public static implicit operator U8SpanMutable(U8StringMutable value) => new U8SpanMutable(value._buffer);
|
||||
public static implicit operator U8Span(U8StringMutable value) => new U8Span(value._buffer);
|
||||
|
||||
public static implicit operator ReadOnlySpan<byte>(U8StringMutable value) => value.Value;
|
||||
public static implicit operator Span<byte>(U8StringMutable value) => value.Value;
|
||||
|
||||
public static explicit operator string(U8StringMutable value) => value.ToString();
|
||||
public static explicit operator U8StringMutable(string value) => new U8StringMutable(value);
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return StringUtils.Utf8ZToString(_buffer);
|
||||
}
|
||||
|
||||
public bool IsNull() => _buffer == null;
|
||||
}
|
||||
}
|
|
@ -39,7 +39,7 @@ namespace LibHac.Fs
|
|||
|
||||
try
|
||||
{
|
||||
Result rc = sourceFs.OpenFile(out srcFile, sourcePath.FromUtf8Z(), OpenMode.Read);
|
||||
Result rc = sourceFs.OpenFile(out srcFile, StringUtils.Utf8ZToString(sourcePath), OpenMode.Read);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
FsPath dstPath = default;
|
||||
|
@ -51,7 +51,7 @@ namespace LibHac.Fs
|
|||
throw new ArgumentException();
|
||||
}
|
||||
|
||||
string dstPathStr = dstPath.Str.FromUtf8Z();
|
||||
string dstPathStr = StringUtils.Utf8ZToString(dstPath.Str);
|
||||
|
||||
rc = destFs.CreateFile(dstPathStr, dirEntry.Size, CreateFileOptions.None);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
|
|
@ -109,7 +109,7 @@ namespace LibHac.Fs
|
|||
|
||||
internal static DirectoryEntryEx GetDirectoryEntryEx(ref DirectoryEntry entry, string parentPath)
|
||||
{
|
||||
string name = entry.Name.FromUtf8Z();
|
||||
string name = StringUtils.Utf8ZToString(entry.Name);
|
||||
string path = PathTools.Combine(parentPath, name);
|
||||
|
||||
var entryEx = new DirectoryEntryEx(name, path, entry.Type, entry.Size);
|
||||
|
|
|
@ -53,4 +53,10 @@
|
|||
ProperSystem = 100,
|
||||
Safe = 101
|
||||
}
|
||||
|
||||
public enum CustomStorageId
|
||||
{
|
||||
User = 0,
|
||||
SdCard = 1
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ namespace LibHac.FsClient.Accessors
|
|||
|
||||
private IFileSystem FileSystem { get; }
|
||||
internal FileSystemManager FsManager { get; }
|
||||
private ICommonMountNameGenerator MountNameGenerator { get; }
|
||||
|
||||
private HashSet<FileAccessor> OpenFiles { get; } = new HashSet<FileAccessor>();
|
||||
private HashSet<DirectoryAccessor> OpenDirectories { get; } = new HashSet<DirectoryAccessor>();
|
||||
|
@ -19,11 +20,12 @@ namespace LibHac.FsClient.Accessors
|
|||
|
||||
internal bool IsAccessLogEnabled { get; set; }
|
||||
|
||||
public FileSystemAccessor(string name, IFileSystem baseFileSystem, FileSystemManager fsManager)
|
||||
public FileSystemAccessor(string name, IFileSystem baseFileSystem, FileSystemManager fsManager, ICommonMountNameGenerator nameGenerator)
|
||||
{
|
||||
Name = name;
|
||||
FileSystem = baseFileSystem;
|
||||
FsManager = fsManager;
|
||||
MountNameGenerator = nameGenerator;
|
||||
}
|
||||
|
||||
public Result CreateDirectory(string path)
|
||||
|
@ -147,6 +149,13 @@ namespace LibHac.FsClient.Accessors
|
|||
return FileSystem.QueryEntry(outBuffer, inBuffer, queryId, path);
|
||||
}
|
||||
|
||||
public Result GetCommonMountName(Span<byte> nameBuffer)
|
||||
{
|
||||
if (MountNameGenerator == null) return ResultFs.PreconditionViolation;
|
||||
|
||||
return MountNameGenerator.Generate(nameBuffer);
|
||||
}
|
||||
|
||||
internal void NotifyCloseFile(FileAccessor file)
|
||||
{
|
||||
lock (_locker)
|
||||
|
|
70
src/LibHac/FsClient/ContentStorage.cs
Normal file
70
src/LibHac/FsClient/ContentStorage.cs
Normal file
|
@ -0,0 +1,70 @@
|
|||
using System;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.FsService;
|
||||
|
||||
namespace LibHac.FsClient
|
||||
{
|
||||
public static class ContentStorage
|
||||
{
|
||||
private static readonly U8String ContentStorageMountNameSystem = new U8String("@SystemContent");
|
||||
private static readonly U8String ContentStorageMountNameUser = new U8String("@UserContent");
|
||||
private static readonly U8String ContentStorageMountNameSdCard = new U8String("@SdCardContent");
|
||||
|
||||
public static Result MountContentStorage(this FileSystemClient fs, ContentStorageId storageId)
|
||||
{
|
||||
return MountContentStorage(fs, GetContentStorageMountName(storageId), storageId);
|
||||
}
|
||||
|
||||
public static Result MountContentStorage(this FileSystemClient fs, U8Span mountName, ContentStorageId storageId)
|
||||
{
|
||||
Result rc = MountHelpers.CheckMountNameAcceptingReservedMountName(mountName);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
FileSystemProxy fsProxy = fs.GetFileSystemProxyServiceObject();
|
||||
|
||||
rc = fsProxy.OpenContentStorageFileSystem(out IFileSystem contentFs, storageId);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
var mountNameGenerator = new ContentStorageCommonMountNameGenerator(storageId);
|
||||
|
||||
return fs.Register(mountName, contentFs, mountNameGenerator);
|
||||
}
|
||||
|
||||
public static U8String GetContentStorageMountName(ContentStorageId storageId)
|
||||
{
|
||||
switch (storageId)
|
||||
{
|
||||
case ContentStorageId.System:
|
||||
return ContentStorageMountNameSystem;
|
||||
case ContentStorageId.User:
|
||||
return ContentStorageMountNameUser;
|
||||
case ContentStorageId.SdCard:
|
||||
return ContentStorageMountNameSdCard;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(storageId), storageId, null);
|
||||
}
|
||||
}
|
||||
|
||||
private class ContentStorageCommonMountNameGenerator : ICommonMountNameGenerator
|
||||
{
|
||||
private ContentStorageId StorageId { get; }
|
||||
|
||||
public ContentStorageCommonMountNameGenerator(ContentStorageId storageId)
|
||||
{
|
||||
StorageId = storageId;
|
||||
}
|
||||
|
||||
public Result Generate(Span<byte> nameBuffer)
|
||||
{
|
||||
U8String mountName = GetContentStorageMountName(StorageId);
|
||||
|
||||
int length = StringUtils.Copy(nameBuffer, mountName);
|
||||
nameBuffer[length] = (byte)':';
|
||||
nameBuffer[length + 1] = 0;
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
22
src/LibHac/FsClient/FileSystemClient.Mount.cs
Normal file
22
src/LibHac/FsClient/FileSystemClient.Mount.cs
Normal file
|
@ -0,0 +1,22 @@
|
|||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.FsService;
|
||||
|
||||
namespace LibHac.FsClient
|
||||
{
|
||||
public partial class FileSystemClient
|
||||
{
|
||||
public Result MountCustomStorage(U8Span mountName, CustomStorageId storageId)
|
||||
{
|
||||
Result rc = MountHelpers.CheckMountName(mountName);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
FileSystemProxy fsProxy = GetFileSystemProxyServiceObject();
|
||||
|
||||
rc = fsProxy.OpenCustomStorageFileSystem(out IFileSystem customFs, storageId);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return FsManager.Register(mountName, customFs);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,6 @@
|
|||
using LibHac.FsService;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.FsService;
|
||||
|
||||
namespace LibHac.FsClient
|
||||
{
|
||||
|
@ -16,7 +18,7 @@ namespace LibHac.FsClient
|
|||
FsManager = new FileSystemManager(timer);
|
||||
}
|
||||
|
||||
private FileSystemProxy GetFileSystemProxyServiceObject()
|
||||
public FileSystemProxy GetFileSystemProxyServiceObject()
|
||||
{
|
||||
if (FsProxy != null) return FsProxy;
|
||||
|
||||
|
@ -29,5 +31,15 @@ namespace LibHac.FsClient
|
|||
return FsProxy;
|
||||
}
|
||||
}
|
||||
|
||||
public Result Register(U8Span mountName, IFileSystem fileSystem)
|
||||
{
|
||||
return FsManager.Register(mountName, fileSystem);
|
||||
}
|
||||
|
||||
public Result Register(U8Span mountName, IFileSystem fileSystem, ICommonMountNameGenerator nameGenerator)
|
||||
{
|
||||
return FsManager.Register(mountName, fileSystem, nameGenerator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.FsClient.Accessors;
|
||||
|
||||
|
@ -32,13 +33,20 @@ namespace LibHac.FsClient
|
|||
Time = timer;
|
||||
}
|
||||
|
||||
public void Register(string mountName, IFileSystem fileSystem)
|
||||
public Result Register(U8Span mountName, IFileSystem fileSystem)
|
||||
{
|
||||
var accessor = new FileSystemAccessor(mountName, fileSystem, this);
|
||||
return Register(mountName, fileSystem, null);
|
||||
}
|
||||
|
||||
MountTable.Mount(accessor).ThrowIfFailure();
|
||||
public Result Register(U8Span mountName, IFileSystem fileSystem, ICommonMountNameGenerator nameGenerator)
|
||||
{
|
||||
var accessor = new FileSystemAccessor(mountName.ToString(), fileSystem, this, nameGenerator);
|
||||
|
||||
Result rc = MountTable.Mount(accessor);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
accessor.IsAccessLogEnabled = IsEnabledAccessLog();
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public void Unmount(string mountName)
|
||||
|
|
|
@ -131,12 +131,10 @@ namespace LibHac.FsClient
|
|||
if (entry.Type != DirectoryEntryType.Directory || !recurse) continue;
|
||||
|
||||
IEnumerable<DirectoryEntryEx> subEntries =
|
||||
fs.EnumerateEntries(PathTools.Combine(path, entry.Name), searchPattern,
|
||||
searchOptions);
|
||||
fs.EnumerateEntries(PathTools.Combine(path, entry.Name), searchPattern, searchOptions);
|
||||
|
||||
foreach (DirectoryEntryEx subEntry in subEntries)
|
||||
{
|
||||
subEntry.FullPath = PathTools.Combine(path, subEntry.Name);
|
||||
yield return subEntry;
|
||||
}
|
||||
}
|
||||
|
|
9
src/LibHac/FsClient/ICommonMountNameGenerator.cs
Normal file
9
src/LibHac/FsClient/ICommonMountNameGenerator.cs
Normal file
|
@ -0,0 +1,9 @@
|
|||
using System;
|
||||
|
||||
namespace LibHac.FsClient
|
||||
{
|
||||
public interface ICommonMountNameGenerator
|
||||
{
|
||||
Result Generate(Span<byte> nameBuffer);
|
||||
}
|
||||
}
|
33
src/LibHac/FsClient/MountHelpers.cs
Normal file
33
src/LibHac/FsClient/MountHelpers.cs
Normal file
|
@ -0,0 +1,33 @@
|
|||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
|
||||
namespace LibHac.FsClient
|
||||
{
|
||||
internal static class MountHelpers
|
||||
{
|
||||
public static Result CheckMountName(U8Span name)
|
||||
{
|
||||
if (name.IsNull()) return ResultFs.NullArgument.Log();
|
||||
|
||||
if (name.Length > 0 && name[0] == '@') return ResultFs.InvalidMountName.Log();
|
||||
if (!CheckMountNameImpl(name)) return ResultFs.InvalidMountName.Log();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public static Result CheckMountNameAcceptingReservedMountName(U8Span name)
|
||||
{
|
||||
if (name.IsNull()) return ResultFs.NullArgument.Log();
|
||||
|
||||
if (!CheckMountNameImpl(name)) return ResultFs.InvalidMountName.Log();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
private static bool CheckMountNameImpl(U8Span name)
|
||||
{
|
||||
// Todo
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -95,6 +95,13 @@ namespace LibHac.FsService
|
|||
return FsProxyCore.OpenContentStorageFileSystem(out fileSystem, storageId);
|
||||
}
|
||||
|
||||
public Result OpenCustomStorageFileSystem(out IFileSystem fileSystem, CustomStorageId storageId)
|
||||
{
|
||||
// Missing permission check, speed emulation storage type wrapper, and FileSystemInterfaceAdapter
|
||||
|
||||
return FsProxyCore.OpenCustomStorageFileSystem(out fileSystem, storageId);
|
||||
}
|
||||
|
||||
public Result OpenSaveDataFileSystemBySystemSaveDataId(out IFileSystem fileSystem, SaveDataSpaceId spaceId,
|
||||
SaveDataAttribute attribute)
|
||||
{
|
||||
|
|
|
@ -75,6 +75,50 @@ namespace LibHac.FsService
|
|||
EncryptedFsKeyId.Content, SdEncryptionSeed);
|
||||
}
|
||||
|
||||
public Result OpenCustomStorageFileSystem(out IFileSystem fileSystem, CustomStorageId storageId)
|
||||
{
|
||||
fileSystem = default;
|
||||
|
||||
switch (storageId)
|
||||
{
|
||||
case CustomStorageId.SdCard:
|
||||
{
|
||||
Result rc = FsCreators.SdFileSystemCreator.Create(out IFileSystem sdFs);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
string customStorageDir = Util.GetCustomStorageDirectoryName(CustomStorageId.SdCard);
|
||||
string subDirName = $"/{NintendoDirectoryName}/{customStorageDir}";
|
||||
|
||||
rc = Util.CreateSubFileSystem(out IFileSystem subFs, sdFs, subDirName, true);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
rc = FsCreators.EncryptedFileSystemCreator.Create(out IFileSystem encryptedFs, subFs,
|
||||
EncryptedFsKeyId.CustomStorage, SdEncryptionSeed);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
fileSystem = encryptedFs;
|
||||
return Result.Success;
|
||||
}
|
||||
case CustomStorageId.User:
|
||||
{
|
||||
Result rc = FsCreators.BuiltInStorageFileSystemCreator.Create(out IFileSystem userFs, string.Empty,
|
||||
BisPartitionId.User);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
string customStorageDir = Util.GetCustomStorageDirectoryName(CustomStorageId.User);
|
||||
string subDirName = $"/{customStorageDir}";
|
||||
|
||||
rc = Util.CreateSubFileSystem(out IFileSystem subFs, userFs, subDirName, true);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
fileSystem = subFs;
|
||||
return Result.Success;
|
||||
}
|
||||
default:
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
}
|
||||
}
|
||||
|
||||
public Result SetSdCardEncryptionSeed(ReadOnlySpan<byte> seed)
|
||||
{
|
||||
seed.CopyTo(SdEncryptionSeed);
|
||||
|
|
|
@ -12,6 +12,7 @@ namespace LibHac.FsService
|
|||
Result OpenSaveDataFileSystem(out IFileSystem fileSystem, SaveDataSpaceId spaceId, SaveDataAttribute attribute);
|
||||
Result OpenSaveDataFileSystemBySystemSaveDataId(out IFileSystem fileSystem, SaveDataSpaceId spaceId, SaveDataAttribute attribute);
|
||||
Result OpenContentStorageFileSystem(out IFileSystem fileSystem, ContentStorageId storageId);
|
||||
Result OpenCustomStorageFileSystem(out IFileSystem fileSystem, CustomStorageId storageId);
|
||||
Result SetSdCardEncryptionSeed(ReadOnlySpan<byte> seed);
|
||||
Result SetSaveDataSize(long saveDataSize, long saveDataJournalSize);
|
||||
Result SetSaveDataRootPath(string path);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using LibHac.Fs;
|
||||
using System;
|
||||
using LibHac.Fs;
|
||||
|
||||
namespace LibHac.FsService
|
||||
{
|
||||
|
@ -48,5 +49,17 @@ namespace LibHac.FsService
|
|||
spaceId == SaveDataSpaceId.ProperSystem ||
|
||||
spaceId == SaveDataSpaceId.Safe;
|
||||
}
|
||||
|
||||
public static string GetCustomStorageDirectoryName(CustomStorageId storageId)
|
||||
{
|
||||
switch (storageId)
|
||||
{
|
||||
case CustomStorageId.User:
|
||||
case CustomStorageId.SdCard:
|
||||
return "CustomStorage0";
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(storageId), storageId, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System.IO;
|
||||
using System.Text;
|
||||
using LibHac;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.NcaUtils;
|
||||
using LibHac.FsClient;
|
||||
|
@ -47,8 +48,8 @@ namespace hactoolnet
|
|||
|
||||
string mountName = $"section{i}";
|
||||
|
||||
fs.Register(mountName, OpenFileSystem(i));
|
||||
fs.Register("output", new LocalFileSystem(ctx.Options.SectionOutDir[i]));
|
||||
fs.Register(mountName.AsU8Span(), OpenFileSystem(i));
|
||||
fs.Register("output".AsU8Span(), new LocalFileSystem(ctx.Options.SectionOutDir[i]));
|
||||
|
||||
FsUtils.CopyDirectoryWithProgress(fs, mountName + ":/", "output:/", logger: ctx.Logger);
|
||||
|
||||
|
@ -96,8 +97,8 @@ namespace hactoolnet
|
|||
{
|
||||
FileSystemManager fs = ctx.Horizon.Fs;
|
||||
|
||||
fs.Register("rom", OpenFileSystemByType(NcaSectionType.Data));
|
||||
fs.Register("output", new LocalFileSystem(ctx.Options.RomfsOutDir));
|
||||
fs.Register("rom".AsU8Span(), OpenFileSystemByType(NcaSectionType.Data));
|
||||
fs.Register("output".AsU8Span(), new LocalFileSystem(ctx.Options.RomfsOutDir));
|
||||
|
||||
FsUtils.CopyDirectoryWithProgress(fs, "rom:/", "output:/", logger: ctx.Logger);
|
||||
|
||||
|
@ -153,8 +154,8 @@ namespace hactoolnet
|
|||
{
|
||||
FileSystemManager fs = ctx.Horizon.Fs;
|
||||
|
||||
fs.Register("code", OpenFileSystemByType(NcaSectionType.Code));
|
||||
fs.Register("output", new LocalFileSystem(ctx.Options.ExefsOutDir));
|
||||
fs.Register("code".AsU8Span(), OpenFileSystemByType(NcaSectionType.Code));
|
||||
fs.Register("output".AsU8Span(), new LocalFileSystem(ctx.Options.ExefsOutDir));
|
||||
|
||||
FsUtils.CopyDirectoryWithProgress(fs, "code:/", "output:/", logger: ctx.Logger);
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ using System.IO;
|
|||
using System.Linq;
|
||||
using System.Text;
|
||||
using LibHac;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Save;
|
||||
using LibHac.FsClient;
|
||||
|
@ -30,7 +31,7 @@ namespace hactoolnet
|
|||
var save = new SaveDataFileSystem(ctx.Keyset, file, ctx.Options.IntegrityLevel, true);
|
||||
FileSystemManager fs = ctx.Horizon.Fs;
|
||||
|
||||
fs.Register("save", save);
|
||||
fs.Register("save".AsU8Span(), save);
|
||||
|
||||
if (ctx.Options.Validate)
|
||||
{
|
||||
|
@ -39,7 +40,7 @@ namespace hactoolnet
|
|||
|
||||
if (ctx.Options.OutDir != null)
|
||||
{
|
||||
fs.Register("output", new LocalFileSystem(ctx.Options.OutDir));
|
||||
fs.Register("output".AsU8Span(), new LocalFileSystem(ctx.Options.OutDir));
|
||||
|
||||
FsUtils.CopyDirectoryWithProgress(fs, "save:/", "output:/", logger: ctx.Logger);
|
||||
|
||||
|
@ -85,7 +86,7 @@ namespace hactoolnet
|
|||
|
||||
if (ctx.Options.RepackSource != null)
|
||||
{
|
||||
fs.Register("input", new LocalFileSystem(ctx.Options.RepackSource));
|
||||
fs.Register("input".AsU8Span(), new LocalFileSystem(ctx.Options.RepackSource));
|
||||
|
||||
fs.CleanDirectoryRecursively("save:/");
|
||||
fs.Commit("save");
|
||||
|
|
Loading…
Reference in a new issue