diff --git a/src/LibHac/Common/U8String.cs b/src/LibHac/Common/U8String.cs index e995298e..c41083bb 100644 --- a/src/LibHac/Common/U8String.cs +++ b/src/LibHac/Common/U8String.cs @@ -46,6 +46,18 @@ namespace LibHac.Common return StringUtils.Utf8ZToString(_buffer); } - public bool IsEmpty() => _buffer == null || _buffer.Length == 0; + /// + /// Checks if the has no buffer. + /// + /// if the string has no buffer. + /// Otherwise, . + public bool IsNull() => _buffer == null; + + /// + /// Checks if the has no buffer or begins with a null terminator. + /// + /// if the string has no buffer or begins with a null terminator. + /// Otherwise, . + public bool IsEmpty() => _buffer == null || _buffer.Length < 1 || _buffer[0] == 0; } } diff --git a/src/LibHac/Fs/FileSystemClient.AccessLog.cs b/src/LibHac/Fs/FileSystemClient.AccessLog.cs index f42231f0..bc1b988f 100644 --- a/src/LibHac/Fs/FileSystemClient.AccessLog.cs +++ b/src/LibHac/Fs/FileSystemClient.AccessLog.cs @@ -105,9 +105,9 @@ namespace LibHac.Fs return IsEnabledAccessLog(AccessLogTarget.All); } - internal bool IsEnabledFileSystemAccessorAccessLog(string mountName) + internal bool IsEnabledFileSystemAccessorAccessLog(U8Span mountName) { - if (MountTable.Find(mountName, out FileSystemAccessor accessor).IsFailure()) + if (MountTable.Find(mountName.ToString(), out FileSystemAccessor accessor).IsFailure()) { return true; } diff --git a/src/LibHac/Fs/FileSystemClient.FileSystem.cs b/src/LibHac/Fs/FileSystemClient.FileSystem.cs index 1b152b8f..73e40b0b 100644 --- a/src/LibHac/Fs/FileSystemClient.FileSystem.cs +++ b/src/LibHac/Fs/FileSystemClient.FileSystem.cs @@ -6,9 +6,9 @@ namespace LibHac.Fs { public partial class FileSystemClient { - public Result CreateDirectory(string path) + public Result CreateDirectory(U8Span path) { - Result rc = FindFileSystem(out FileSystemAccessor fileSystem, out U8Span subPath, path.ToU8Span()); + Result rc = FindFileSystem(out FileSystemAccessor fileSystem, out U8Span subPath, path); if (rc.IsFailure()) return rc; if (IsEnabledAccessLog() && fileSystem.IsAccessLogEnabled) @@ -17,7 +17,7 @@ namespace LibHac.Fs rc = fileSystem.CreateDirectory(subPath); TimeSpan endTime = Time.GetCurrent(); - OutputAccessLog(rc, startTime, endTime, $", path: \"{path}\""); + OutputAccessLog(rc, startTime, endTime, $", path: \"{path.ToString()}\""); } else { @@ -27,14 +27,14 @@ namespace LibHac.Fs return rc; } - public Result CreateFile(string path, long size) + public Result CreateFile(U8Span path, long size) { return CreateFile(path, size, CreateFileOptions.None); } - public Result CreateFile(string path, long size, CreateFileOptions options) + public Result CreateFile(U8Span path, long size, CreateFileOptions options) { - Result rc = FindFileSystem(out FileSystemAccessor fileSystem, out U8Span subPath, path.ToU8Span()); + Result rc = FindFileSystem(out FileSystemAccessor fileSystem, out U8Span subPath, path); if (rc.IsFailure()) return rc; if (IsEnabledAccessLog() && fileSystem.IsAccessLogEnabled) @@ -43,7 +43,7 @@ namespace LibHac.Fs rc = fileSystem.CreateFile(subPath, size, options); TimeSpan endTime = Time.GetCurrent(); - OutputAccessLog(rc, startTime, endTime, $", path: \"{path}\", size: {size}"); + OutputAccessLog(rc, startTime, endTime, $", path: \"{path.ToString()}\", size: {size}"); } else { @@ -53,9 +53,9 @@ namespace LibHac.Fs return rc; } - public Result DeleteDirectory(string path) + public Result DeleteDirectory(U8Span path) { - Result rc = FindFileSystem(out FileSystemAccessor fileSystem, out U8Span subPath, path.ToU8Span()); + Result rc = FindFileSystem(out FileSystemAccessor fileSystem, out U8Span subPath, path); if (rc.IsFailure()) return rc; if (IsEnabledAccessLog() && fileSystem.IsAccessLogEnabled) @@ -64,7 +64,7 @@ namespace LibHac.Fs rc = fileSystem.DeleteDirectory(subPath); TimeSpan endTime = Time.GetCurrent(); - OutputAccessLog(rc, startTime, endTime, $", path: \"{path}\""); + OutputAccessLog(rc, startTime, endTime, $", path: \"{path.ToString()}\""); } else { @@ -74,9 +74,9 @@ namespace LibHac.Fs return rc; } - public Result DeleteDirectoryRecursively(string path) + public Result DeleteDirectoryRecursively(U8Span path) { - Result rc = FindFileSystem(out FileSystemAccessor fileSystem, out U8Span subPath, path.ToU8Span()); + Result rc = FindFileSystem(out FileSystemAccessor fileSystem, out U8Span subPath, path); if (rc.IsFailure()) return rc; if (IsEnabledAccessLog() && fileSystem.IsAccessLogEnabled) @@ -85,7 +85,7 @@ namespace LibHac.Fs rc = fileSystem.DeleteDirectoryRecursively(subPath); TimeSpan endTime = Time.GetCurrent(); - OutputAccessLog(rc, startTime, endTime, $", path: \"{path}\""); + OutputAccessLog(rc, startTime, endTime, $", path: \"{path.ToString()}\""); } else { @@ -95,9 +95,9 @@ namespace LibHac.Fs return rc; } - public Result CleanDirectoryRecursively(string path) + public Result CleanDirectoryRecursively(U8Span path) { - Result rc = FindFileSystem(out FileSystemAccessor fileSystem, out U8Span subPath, path.ToU8Span()); + Result rc = FindFileSystem(out FileSystemAccessor fileSystem, out U8Span subPath, path); if (rc.IsFailure()) return rc; if (IsEnabledAccessLog() && fileSystem.IsAccessLogEnabled) @@ -106,7 +106,7 @@ namespace LibHac.Fs rc = fileSystem.CleanDirectoryRecursively(subPath); TimeSpan endTime = Time.GetCurrent(); - OutputAccessLog(rc, startTime, endTime, $", path: \"{path}\""); + OutputAccessLog(rc, startTime, endTime, $", path: \"{path.ToString()}\""); } else { @@ -116,9 +116,9 @@ namespace LibHac.Fs return rc; } - public Result DeleteFile(string path) + public Result DeleteFile(U8Span path) { - Result rc = FindFileSystem(out FileSystemAccessor fileSystem, out U8Span subPath, path.ToU8Span()); + Result rc = FindFileSystem(out FileSystemAccessor fileSystem, out U8Span subPath, path); if (rc.IsFailure()) return rc; if (IsEnabledAccessLog() && fileSystem.IsAccessLogEnabled) @@ -127,7 +127,7 @@ namespace LibHac.Fs rc = fileSystem.DeleteFile(subPath); TimeSpan endTime = Time.GetCurrent(); - OutputAccessLog(rc, startTime, endTime, $", path: \"{path}\""); + OutputAccessLog(rc, startTime, endTime, $", path: \"{path.ToString()}\""); } else { @@ -137,12 +137,12 @@ namespace LibHac.Fs return rc; } - public Result RenameDirectory(string oldPath, string newPath) + public Result RenameDirectory(U8Span oldPath, U8Span newPath) { - Result rc = FindFileSystem(out FileSystemAccessor oldFileSystem, out U8Span oldSubPath, oldPath.ToU8Span()); + Result rc = FindFileSystem(out FileSystemAccessor oldFileSystem, out U8Span oldSubPath, oldPath); if (rc.IsFailure()) return rc; - rc = FindFileSystem(out FileSystemAccessor newFileSystem, out U8Span newSubPath, newPath.ToU8Span()); + rc = FindFileSystem(out FileSystemAccessor newFileSystem, out U8Span newSubPath, newPath); if (rc.IsFailure()) return rc; if (oldFileSystem != newFileSystem) @@ -156,7 +156,7 @@ namespace LibHac.Fs rc = oldFileSystem.RenameDirectory(oldSubPath, newSubPath); TimeSpan endTime = Time.GetCurrent(); - OutputAccessLog(rc, startTime, endTime, $", path: \"{oldPath}\", new_path: \"{newPath}\""); + OutputAccessLog(rc, startTime, endTime, $", path: \"{oldPath.ToString()}\", new_path: \"{newPath.ToString()}\""); } else { @@ -166,12 +166,12 @@ namespace LibHac.Fs return rc; } - public Result RenameFile(string oldPath, string newPath) + public Result RenameFile(U8Span oldPath, U8Span newPath) { - Result rc = FindFileSystem(out FileSystemAccessor oldFileSystem, out U8Span oldSubPath, oldPath.ToU8Span()); + Result rc = FindFileSystem(out FileSystemAccessor oldFileSystem, out U8Span oldSubPath, oldPath); if (rc.IsFailure()) return rc; - rc = FindFileSystem(out FileSystemAccessor newFileSystem, out U8Span newSubPath, newPath.ToU8Span()); + rc = FindFileSystem(out FileSystemAccessor newFileSystem, out U8Span newSubPath, newPath); if (rc.IsFailure()) return rc; if (oldFileSystem != newFileSystem) @@ -185,7 +185,7 @@ namespace LibHac.Fs rc = oldFileSystem.RenameFile(oldSubPath, newSubPath); TimeSpan endTime = Time.GetCurrent(); - OutputAccessLog(rc, startTime, endTime, $", path: \"{oldPath}\", new_path: \"{newPath}\""); + OutputAccessLog(rc, startTime, endTime, $", path: \"{oldPath.ToString()}\", new_path: \"{newPath.ToString()}\""); } else { @@ -195,11 +195,11 @@ namespace LibHac.Fs return rc; } - public Result GetEntryType(out DirectoryEntryType type, string path) + public Result GetEntryType(out DirectoryEntryType type, U8Span path) { type = default; - Result rc = FindFileSystem(out FileSystemAccessor fileSystem, out U8Span subPath, path.ToU8Span()); + Result rc = FindFileSystem(out FileSystemAccessor fileSystem, out U8Span subPath, path); if (rc.IsFailure()) return rc; if (IsEnabledAccessLog() && fileSystem.IsAccessLogEnabled) @@ -208,7 +208,7 @@ namespace LibHac.Fs rc = fileSystem.GetEntryType(out type, subPath); TimeSpan endTime = Time.GetCurrent(); - OutputAccessLog(rc, startTime, endTime, $", path: \"{path}\""); + OutputAccessLog(rc, startTime, endTime, $", path: \"{path.ToString()}\""); } else { @@ -218,11 +218,11 @@ namespace LibHac.Fs return rc; } - public Result OpenFile(out FileHandle handle, string path, OpenMode mode) + public Result OpenFile(out FileHandle handle, U8Span path, OpenMode mode) { handle = default; - Result rc = FindFileSystem(out FileSystemAccessor fileSystem, out U8Span subPath, path.ToU8Span()); + Result rc = FindFileSystem(out FileSystemAccessor fileSystem, out U8Span subPath, path); if (rc.IsFailure()) return rc; if (IsEnabledAccessLog() && fileSystem.IsAccessLogEnabled) @@ -232,7 +232,7 @@ namespace LibHac.Fs handle = new FileHandle(file); TimeSpan endTime = Time.GetCurrent(); - OutputAccessLog(rc, startTime, endTime, handle, $", path: \"{path}\", open_mode: {mode}"); + OutputAccessLog(rc, startTime, endTime, handle, $", path: \"{path.ToString()}\", open_mode: {mode}"); } else { @@ -243,11 +243,11 @@ namespace LibHac.Fs return rc; } - public Result OpenDirectory(out DirectoryHandle handle, string path, OpenDirectoryMode mode) + public Result OpenDirectory(out DirectoryHandle handle, U8Span path, OpenDirectoryMode mode) { handle = default; - Result rc = FindFileSystem(out FileSystemAccessor fileSystem, out U8Span subPath, path.ToU8Span()); + Result rc = FindFileSystem(out FileSystemAccessor fileSystem, out U8Span subPath, path); if (rc.IsFailure()) return rc; if (IsEnabledAccessLog() && fileSystem.IsAccessLogEnabled) @@ -257,7 +257,7 @@ namespace LibHac.Fs handle = new DirectoryHandle(dir); TimeSpan endTime = Time.GetCurrent(); - OutputAccessLog(rc, startTime, endTime, handle, $", path: \"{path}\", open_mode: {mode}"); + OutputAccessLog(rc, startTime, endTime, handle, $", path: \"{path.ToString()}\", open_mode: {mode}"); } else { @@ -268,39 +268,39 @@ namespace LibHac.Fs return rc; } - public Result GetFreeSpaceSize(out long freeSpace, string path) + public Result GetFreeSpaceSize(out long freeSpace, U8Span path) { freeSpace = default; - Result rc = FindFileSystem(out FileSystemAccessor fileSystem, out U8Span subPath, path.ToU8Span()); + Result rc = FindFileSystem(out FileSystemAccessor fileSystem, out U8Span subPath, path); if (rc.IsFailure()) return rc; return fileSystem.GetFreeSpaceSize(out freeSpace, subPath); } - public Result GetTotalSpaceSize(out long totalSpace, string path) + public Result GetTotalSpaceSize(out long totalSpace, U8Span path) { totalSpace = default; - Result rc = FindFileSystem(out FileSystemAccessor fileSystem, out U8Span subPath, path.ToU8Span()); + Result rc = FindFileSystem(out FileSystemAccessor fileSystem, out U8Span subPath, path); if (rc.IsFailure()) return rc; return fileSystem.GetTotalSpaceSize(out totalSpace, subPath); } - public Result GetFileTimeStamp(out FileTimeStampRaw timeStamp, string path) + public Result GetFileTimeStamp(out FileTimeStampRaw timeStamp, U8Span path) { timeStamp = default; - Result rc = FindFileSystem(out FileSystemAccessor fileSystem, out U8Span subPath, path.ToU8Span()); + Result rc = FindFileSystem(out FileSystemAccessor fileSystem, out U8Span subPath, path); if (rc.IsFailure()) return rc; return fileSystem.GetFileTimeStampRaw(out timeStamp, subPath); } - public Result Commit(string mountName) + public Result Commit(U8Span mountName) { - Result rc = MountTable.Find(mountName, out FileSystemAccessor fileSystem); + Result rc = MountTable.Find(mountName.ToString(), out FileSystemAccessor fileSystem); if (rc.IsFailure()) return rc; if (IsEnabledAccessLog() && fileSystem.IsAccessLogEnabled) @@ -309,7 +309,7 @@ namespace LibHac.Fs rc = fileSystem.Commit(); TimeSpan endTime = Time.GetCurrent(); - OutputAccessLog(rc, startTime, endTime, $", name: \"{mountName}\""); + OutputAccessLog(rc, startTime, endTime, $", name: \"{mountName.ToString()}\""); } else { diff --git a/src/LibHac/Fs/FileSystemClient.cs b/src/LibHac/Fs/FileSystemClient.cs index a13cc49f..bb7e0c71 100644 --- a/src/LibHac/Fs/FileSystemClient.cs +++ b/src/LibHac/Fs/FileSystemClient.cs @@ -78,22 +78,23 @@ namespace LibHac.Fs return Result.Success; } - public void Unmount(string mountName) + public void Unmount(U8Span mountName) { Result rc; + string mountNameStr = mountName.ToString(); if (IsEnabledAccessLog() && IsEnabledFileSystemAccessorAccessLog(mountName)) { TimeSpan startTime = Time.GetCurrent(); - rc = MountTable.Unmount(mountName); + rc = MountTable.Unmount(mountNameStr); TimeSpan endTime = Time.GetCurrent(); - OutputAccessLog(rc, startTime, endTime, $", name: \"{mountName}\""); + OutputAccessLog(rc, startTime, endTime, $", name: \"{mountNameStr}\""); } else { - rc = MountTable.Unmount(mountName); + rc = MountTable.Unmount(mountNameStr); } rc.ThrowIfFailure(); diff --git a/src/LibHac/Fs/FileSystemClientUtils.cs b/src/LibHac/Fs/FileSystemClientUtils.cs index 3a26c0df..b104af69 100644 --- a/src/LibHac/Fs/FileSystemClientUtils.cs +++ b/src/LibHac/Fs/FileSystemClientUtils.cs @@ -12,7 +12,7 @@ namespace LibHac.Fs public static Result CopyDirectory(this FileSystemClient fs, string sourcePath, string destPath, CreateFileOptions options = CreateFileOptions.None, IProgressReport logger = null) { - Result rc = fs.OpenDirectory(out DirectoryHandle sourceHandle, sourcePath, OpenDirectoryMode.All); + Result rc = fs.OpenDirectory(out DirectoryHandle sourceHandle, sourcePath.ToU8Span(), OpenDirectoryMode.All); if (rc.IsFailure()) return rc; using (sourceHandle) @@ -46,12 +46,12 @@ namespace LibHac.Fs public static Result CopyFile(this FileSystemClient fs, string sourcePath, string destPath, IProgressReport logger = null) { - Result rc = fs.OpenFile(out FileHandle sourceHandle, sourcePath, OpenMode.Read); + Result rc = fs.OpenFile(out FileHandle sourceHandle, sourcePath.ToU8Span(), OpenMode.Read); if (rc.IsFailure()) return rc; using (sourceHandle) { - rc = fs.OpenFile(out FileHandle destHandle, destPath, OpenMode.Write | OpenMode.AllowAppend); + rc = fs.OpenFile(out FileHandle destHandle, destPath.ToU8Span(), OpenMode.Write | OpenMode.AllowAppend); if (rc.IsFailure()) return rc; using (destHandle) @@ -111,7 +111,7 @@ namespace LibHac.Fs bool ignoreCase = searchOptions.HasFlag(SearchOptions.CaseInsensitive); bool recurse = searchOptions.HasFlag(SearchOptions.RecurseSubdirectories); - fs.OpenDirectory(out DirectoryHandle sourceHandle, path, OpenDirectoryMode.All).ThrowIfFailure(); + fs.OpenDirectory(out DirectoryHandle sourceHandle, path.ToU8Span(), OpenDirectoryMode.All).ThrowIfFailure(); using (sourceHandle) { @@ -144,14 +144,14 @@ namespace LibHac.Fs public static bool DirectoryExists(this FileSystemClient fs, string path) { - Result rc = fs.GetEntryType(out DirectoryEntryType type, path); + Result rc = fs.GetEntryType(out DirectoryEntryType type, path.ToU8Span()); return (rc.IsSuccess() && type == DirectoryEntryType.Directory); } public static bool FileExists(this FileSystemClient fs, string path) { - Result rc = fs.GetEntryType(out DirectoryEntryType type, path); + Result rc = fs.GetEntryType(out DirectoryEntryType type, path.ToU8Span()); return (rc.IsSuccess() && type == DirectoryEntryType.File); } @@ -189,25 +189,30 @@ namespace LibHac.Fs { string subPath = path.Substring(0, i); - fs.CreateDirectory(subPath); + fs.CreateDirectory(subPath.ToU8Span()); } } - fs.CreateDirectory(path); + fs.CreateDirectory(path.ToU8Span()); } - public static void CreateOrOverwriteFile(this FileSystemClient fs, string path, long size) + public static Result CreateOrOverwriteFile(this FileSystemClient fs, string path, long size) { - fs.CreateOrOverwriteFile(path, size, CreateFileOptions.None); + return fs.CreateOrOverwriteFile(path, size, CreateFileOptions.None); } - public static void CreateOrOverwriteFile(this FileSystemClient fs, string path, long size, CreateFileOptions options) + public static Result CreateOrOverwriteFile(this FileSystemClient fs, string path, long size, CreateFileOptions options) { path = PathTools.Normalize(path); + var u8Path = path.ToU8Span(); - if (fs.FileExists(path)) fs.DeleteFile(path); + if (fs.FileExists(path)) + { + Result rc = fs.DeleteFile(u8Path); + if (rc.IsFailure()) return rc; + } - fs.CreateFile(path, size, CreateFileOptions.None); + return fs.CreateFile(u8Path, size, CreateFileOptions.None); } internal static bool IsEnabledFileSystemAccessorAccessLog(this FileSystemClient fs, string mountName) diff --git a/src/LibHac/FsService/SaveDataIndexer.cs b/src/LibHac/FsService/SaveDataIndexer.cs index c1fa4383..42ac4f8b 100644 --- a/src/LibHac/FsService/SaveDataIndexer.cs +++ b/src/LibHac/FsService/SaveDataIndexer.cs @@ -18,7 +18,7 @@ namespace LibHac.FsService private const long LastIdFileSize = 8; private FileSystemClient FsClient { get; } - private string MountName { get; } + private U8String MountName { get; } private ulong SaveDataId { get; } private SaveDataSpaceId SpaceId { get; } private KeyValueDatabase KvDatabase { get; set; } @@ -29,10 +29,10 @@ namespace LibHac.FsService private int Version { get; set; } private List OpenedReaders { get; } = new List(); - public SaveDataIndexer(FileSystemClient fsClient, string mountName, SaveDataSpaceId spaceId, ulong saveDataId) + public SaveDataIndexer(FileSystemClient fsClient, U8Span mountName, SaveDataSpaceId spaceId, ulong saveDataId) { FsClient = fsClient; - MountName = mountName; + MountName = mountName.ToU8String(); SaveDataId = saveDataId; SpaceId = spaceId; Version = 1; @@ -77,7 +77,7 @@ namespace LibHac.FsService string idFilePath = $"{MountName}:/{LastIdFileName}"; - rc = FsClient.OpenFile(out FileHandle handle, idFilePath, OpenMode.Write); + rc = FsClient.OpenFile(out FileHandle handle, idFilePath.ToU8Span(), OpenMode.Write); if (rc.IsFailure()) return rc; bool fileAlreadyClosed = false; @@ -423,7 +423,7 @@ namespace LibHac.FsService string dbDirectory = $"{MountName}:/"; - rc = FsClient.GetEntryType(out DirectoryEntryType entryType, dbDirectory); + rc = FsClient.GetEntryType(out DirectoryEntryType entryType, dbDirectory.ToU8Span()); if (rc.IsFailure()) return rc; if (entryType == DirectoryEntryType.File) @@ -431,7 +431,7 @@ namespace LibHac.FsService string dbArchiveFile = $"{dbDirectory}imkvdb.arc"; - KvDatabase = new KeyValueDatabase(FsClient, dbArchiveFile); + KvDatabase = new KeyValueDatabase(FsClient, dbArchiveFile.ToU8Span()); IsInitialized = true; return Result.Success; @@ -466,7 +466,7 @@ namespace LibHac.FsService if (rc.IsFailure()) return rc; bool createdNewFile = false; - string idFilePath = $"{MountName}:/{LastIdFileName}"; + var idFilePath = $"{MountName}:/{LastIdFileName}".ToU8String(); rc = FsClient.OpenFile(out FileHandle handle, idFilePath, OpenMode.Read); @@ -572,10 +572,10 @@ namespace LibHac.FsService private ref struct Mounter { private FileSystemClient FsClient { get; set; } - private string MountName { get; set; } + private U8String MountName { get; set; } private bool IsMounted { get; set; } - public Result Initialize(FileSystemClient fsClient, string mountName, SaveDataSpaceId spaceId, + public Result Initialize(FileSystemClient fsClient, U8String mountName, SaveDataSpaceId spaceId, ulong saveDataId) { FsClient = fsClient; @@ -583,7 +583,7 @@ namespace LibHac.FsService FsClient.DisableAutoSaveDataCreation(); - Result rc = FsClient.MountSystemSaveData(MountName.ToU8Span(), spaceId, saveDataId); + Result rc = FsClient.MountSystemSaveData(MountName, spaceId, saveDataId); if (rc.IsFailure()) { @@ -592,7 +592,7 @@ namespace LibHac.FsService rc = FsClient.CreateSystemSaveData(spaceId, saveDataId, TitleId.Zero, 0xC0000, 0xC0000, 0); if (rc.IsFailure()) return rc; - rc = FsClient.MountSystemSaveData(MountName.ToU8Span(), spaceId, saveDataId); + rc = FsClient.MountSystemSaveData(MountName, spaceId, saveDataId); if (rc.IsFailure()) return rc; } else @@ -608,7 +608,7 @@ namespace LibHac.FsService rc = FsClient.CreateSystemSaveData(spaceId, saveDataId, TitleId.Zero, 0xC0000, 0xC0000, 0); if (rc.IsFailure()) return rc; - rc = FsClient.MountSystemSaveData(MountName.ToU8Span(), spaceId, saveDataId); + rc = FsClient.MountSystemSaveData(MountName, spaceId, saveDataId); if (rc.IsFailure()) return rc; } } diff --git a/src/LibHac/FsService/SaveDataIndexerManager.cs b/src/LibHac/FsService/SaveDataIndexerManager.cs index 1e6a18c2..ee6722da 100644 --- a/src/LibHac/FsService/SaveDataIndexerManager.cs +++ b/src/LibHac/FsService/SaveDataIndexerManager.cs @@ -1,4 +1,5 @@ using System.Threading; +using LibHac.Common; using LibHac.Fs; namespace LibHac.FsService @@ -30,7 +31,7 @@ namespace LibHac.FsService if (!_bisIndexer.IsInitialized) { - _bisIndexer.Indexer = new SaveDataIndexer(FsClient, "saveDataIxrDb", SaveDataSpaceId.System, SaveDataId); + _bisIndexer.Indexer = new SaveDataIndexer(FsClient, "saveDataIxrDb".ToU8Span(), SaveDataSpaceId.System, SaveDataId); } reader = new SaveDataIndexerReader(_bisIndexer.Indexer, _bisIndexer.Locker); @@ -44,7 +45,7 @@ namespace LibHac.FsService if (!_sdCardIndexer.IsInitialized) { - _sdCardIndexer.Indexer = new SaveDataIndexer(FsClient, "saveDataIxrDbSd", SaveDataSpaceId.SdSystem, SaveDataId); + _sdCardIndexer.Indexer = new SaveDataIndexer(FsClient, "saveDataIxrDbSd".ToU8Span(), SaveDataSpaceId.SdSystem, SaveDataId); } reader = new SaveDataIndexerReader(_sdCardIndexer.Indexer, _sdCardIndexer.Locker); @@ -66,7 +67,7 @@ namespace LibHac.FsService if (!_safeIndexer.IsInitialized) { - _safeIndexer.Indexer = new SaveDataIndexer(FsClient, "saveDataIxrDbPr", SaveDataSpaceId.ProperSystem, SaveDataId); + _safeIndexer.Indexer = new SaveDataIndexer(FsClient, "saveDataIxrDbPr".ToU8Span(), SaveDataSpaceId.ProperSystem, SaveDataId); } reader = new SaveDataIndexerReader(_safeIndexer.Indexer, _safeIndexer.Locker); @@ -77,7 +78,7 @@ namespace LibHac.FsService if (!_properSystemIndexer.IsInitialized) { - _properSystemIndexer.Indexer = new SaveDataIndexer(FsClient, "saveDataIxrDbSf", SaveDataSpaceId.SafeMode, SaveDataId); + _properSystemIndexer.Indexer = new SaveDataIndexer(FsClient, "saveDataIxrDbSf".ToU8Span(), SaveDataSpaceId.SafeMode, SaveDataId); } reader = new SaveDataIndexerReader(_properSystemIndexer.Indexer, _properSystemIndexer.Locker); diff --git a/src/LibHac/Kvdb/KeyValueDatabase.cs b/src/LibHac/Kvdb/KeyValueDatabase.cs index cfa79254..1ea5680d 100644 --- a/src/LibHac/Kvdb/KeyValueDatabase.cs +++ b/src/LibHac/Kvdb/KeyValueDatabase.cs @@ -13,16 +13,16 @@ namespace LibHac.Kvdb private Dictionary KvDict { get; } = new Dictionary(); private FileSystemClient FsClient { get; } - private string FileName { get; } + private U8String FileName { get; } public int Count => KvDict.Count; public KeyValueDatabase() { } - public KeyValueDatabase(FileSystemClient fsClient, string fileName) + public KeyValueDatabase(FileSystemClient fsClient, U8Span fileName) { FsClient = fsClient; - FileName = fileName; + FileName = fileName.ToU8String(); } public Result Get(ref TKey key, Span valueBuffer) @@ -109,7 +109,7 @@ namespace LibHac.Kvdb public Result ReadDatabaseFromFile() { - if (FsClient == null || FileName == null) + if (FsClient == null || FileName.IsNull()) return ResultFs.PreconditionViolation.Log(); Result rc = ReadFile(out byte[] data); @@ -124,7 +124,7 @@ namespace LibHac.Kvdb public Result WriteDatabaseToFile() { - if (FsClient == null || FileName == null) + if (FsClient == null || FileName.IsNull()) return ResultFs.PreconditionViolation.Log(); var buffer = new byte[GetExportedSize()]; @@ -157,7 +157,7 @@ namespace LibHac.Kvdb private Result ReadFile(out byte[] data) { Debug.Assert(FsClient != null); - Debug.Assert(!string.IsNullOrWhiteSpace(FileName)); + Debug.Assert(!FileName.IsEmpty()); data = default; @@ -180,7 +180,7 @@ namespace LibHac.Kvdb private Result WriteFile(ReadOnlySpan data) { Debug.Assert(FsClient != null); - Debug.Assert(!string.IsNullOrWhiteSpace(FileName)); + Debug.Assert(!FileName.IsEmpty()); FsClient.DeleteFile(FileName); diff --git a/src/hactoolnet/FsUtils.cs b/src/hactoolnet/FsUtils.cs index e7d06748..8dfff38e 100644 --- a/src/hactoolnet/FsUtils.cs +++ b/src/hactoolnet/FsUtils.cs @@ -1,6 +1,7 @@ using System; using System.Buffers; using LibHac; +using LibHac.Common; using LibHac.Fs; using LibHac.FsSystem; @@ -8,14 +9,14 @@ namespace hactoolnet { public static class FsUtils { - public static void CopyDirectoryWithProgress(FileSystemClient fs, string sourcePath, string destPath, + public static Result CopyDirectoryWithProgress(FileSystemClient fs, U8Span sourcePath, U8Span destPath, CreateFileOptions options = CreateFileOptions.None, IProgressReport logger = null) { try { logger?.SetTotal(GetTotalSize(fs, sourcePath)); - CopyDirectoryWithProgressInternal(fs, sourcePath, destPath, options, logger); + return CopyDirectoryWithProgressInternal(fs, sourcePath, destPath, options, logger); } finally { @@ -23,41 +24,51 @@ namespace hactoolnet } } - private static void CopyDirectoryWithProgressInternal(FileSystemClient fs, string sourcePath, string destPath, + private static Result CopyDirectoryWithProgressInternal(FileSystemClient fs, U8Span sourcePath, U8Span destPath, CreateFileOptions options, IProgressReport logger) { - fs.OpenDirectory(out DirectoryHandle sourceHandle, sourcePath, OpenDirectoryMode.All).ThrowIfFailure(); + string sourcePathStr = sourcePath.ToString(); + string destPathStr = destPath.ToString(); + + Result rc = fs.OpenDirectory(out DirectoryHandle sourceHandle, sourcePath, OpenDirectoryMode.All); + if (rc.IsFailure()) return rc; using (sourceHandle) { - foreach (DirectoryEntryEx entry in fs.EnumerateEntries(sourcePath, "*", SearchOptions.Default)) + foreach (DirectoryEntryEx entry in fs.EnumerateEntries(sourcePathStr, "*", SearchOptions.Default)) { - string subSrcPath = PathTools.Normalize(PathTools.Combine(sourcePath, entry.Name)); - string subDstPath = PathTools.Normalize(PathTools.Combine(destPath, entry.Name)); + string subSrcPath = PathTools.Normalize(PathTools.Combine(sourcePathStr, entry.Name)); + string subDstPath = PathTools.Normalize(PathTools.Combine(destPathStr, entry.Name)); if (entry.Type == DirectoryEntryType.Directory) { fs.EnsureDirectoryExists(subDstPath); - CopyDirectoryWithProgressInternal(fs, subSrcPath, subDstPath, options, logger); + rc = CopyDirectoryWithProgressInternal(fs, subSrcPath.ToU8Span(), subDstPath.ToU8Span(), options, logger); + if (rc.IsFailure()) return rc; } if (entry.Type == DirectoryEntryType.File) { logger?.LogMessage(subSrcPath); - fs.CreateOrOverwriteFile(subDstPath, entry.Size, options); - CopyFileWithProgress(fs, subSrcPath, subDstPath, logger); + rc = fs.CreateOrOverwriteFile(subDstPath, entry.Size, options); + if (rc.IsFailure()) return rc; + + rc = CopyFileWithProgress(fs, subSrcPath.ToU8Span(), subDstPath.ToU8Span(), logger); + if (rc.IsFailure()) return rc; } } } + + return Result.Success; } - public static long GetTotalSize(FileSystemClient fs, string path, string searchPattern = "*") + public static long GetTotalSize(FileSystemClient fs, U8Span path, string searchPattern = "*") { long size = 0; - foreach (DirectoryEntryEx entry in fs.EnumerateEntries(path, searchPattern)) + foreach (DirectoryEntryEx entry in fs.EnumerateEntries(path.ToString(), searchPattern)) { size += entry.Size; } @@ -65,7 +76,7 @@ namespace hactoolnet return size; } - public static Result CopyFileWithProgress(FileSystemClient fs, string sourcePath, string destPath, IProgressReport logger = null) + public static Result CopyFileWithProgress(FileSystemClient fs, U8Span sourcePath, U8Span destPath, IProgressReport logger = null) { Result rc = fs.OpenFile(out FileHandle sourceHandle, sourcePath, OpenMode.Read); if (rc.IsFailure()) return rc; diff --git a/src/hactoolnet/ProcessNca.cs b/src/hactoolnet/ProcessNca.cs index f3bacfc2..47697630 100644 --- a/src/hactoolnet/ProcessNca.cs +++ b/src/hactoolnet/ProcessNca.cs @@ -51,10 +51,10 @@ namespace hactoolnet fs.Register(mountName.ToU8Span(), OpenFileSystem(i)); fs.Register("output".ToU8Span(), new LocalFileSystem(ctx.Options.SectionOutDir[i])); - FsUtils.CopyDirectoryWithProgress(fs, mountName + ":/", "output:/", logger: ctx.Logger); + FsUtils.CopyDirectoryWithProgress(fs, (mountName + ":/").ToU8Span(), "output:/".ToU8Span(), logger: ctx.Logger).ThrowIfFailure(); - fs.Unmount(mountName); - fs.Unmount("output"); + fs.Unmount(mountName.ToU8Span()); + fs.Unmount("output".ToU8Span()); } if (ctx.Options.Validate && nca.SectionExists(i)) @@ -100,10 +100,10 @@ namespace hactoolnet fs.Register("rom".ToU8Span(), OpenFileSystemByType(NcaSectionType.Data)); fs.Register("output".ToU8Span(), new LocalFileSystem(ctx.Options.RomfsOutDir)); - FsUtils.CopyDirectoryWithProgress(fs, "rom:/", "output:/", logger: ctx.Logger); + FsUtils.CopyDirectoryWithProgress(fs, "rom:/".ToU8Span(), "output:/".ToU8Span(), logger: ctx.Logger).ThrowIfFailure(); - fs.Unmount("rom"); - fs.Unmount("output"); + fs.Unmount("rom".ToU8Span()); + fs.Unmount("output".ToU8Span()); } if (ctx.Options.ReadBench) @@ -157,10 +157,10 @@ namespace hactoolnet fs.Register("code".ToU8Span(), OpenFileSystemByType(NcaSectionType.Code)); fs.Register("output".ToU8Span(), new LocalFileSystem(ctx.Options.ExefsOutDir)); - FsUtils.CopyDirectoryWithProgress(fs, "code:/", "output:/", logger: ctx.Logger); + FsUtils.CopyDirectoryWithProgress(fs, "code:/".ToU8Span(), "output:/".ToU8Span(), logger: ctx.Logger).ThrowIfFailure(); - fs.Unmount("code"); - fs.Unmount("output"); + fs.Unmount("code".ToU8Span()); + fs.Unmount("output".ToU8Span()); } } diff --git a/src/hactoolnet/ProcessSave.cs b/src/hactoolnet/ProcessSave.cs index 79ba504a..170b0b55 100644 --- a/src/hactoolnet/ProcessSave.cs +++ b/src/hactoolnet/ProcessSave.cs @@ -42,9 +42,9 @@ namespace hactoolnet { fs.Register("output".ToU8Span(), new LocalFileSystem(ctx.Options.OutDir)); - FsUtils.CopyDirectoryWithProgress(fs, "save:/", "output:/", logger: ctx.Logger); + FsUtils.CopyDirectoryWithProgress(fs, "save:/".ToU8Span(), "output:/".ToU8Span(), logger: ctx.Logger).ThrowIfFailure(); - fs.Unmount("output"); + fs.Unmount("output".ToU8Span()); } if (ctx.Options.DebugOutDir != null) @@ -88,13 +88,13 @@ namespace hactoolnet { fs.Register("input".ToU8Span(), new LocalFileSystem(ctx.Options.RepackSource)); - fs.CleanDirectoryRecursively("save:/"); - fs.Commit("save"); + fs.CleanDirectoryRecursively("save:/".ToU8Span()); + fs.Commit("save".ToU8Span()); - FsUtils.CopyDirectoryWithProgress(fs, "input:/", "save:/", logger: ctx.Logger); + FsUtils.CopyDirectoryWithProgress(fs, "input:/".ToU8Span(), "save:/".ToU8Span(), logger: ctx.Logger).ThrowIfFailure(); - fs.Commit("save"); - fs.Unmount("input"); + fs.Commit("save".ToU8Span()); + fs.Unmount("input".ToU8Span()); signNeeded = true; } @@ -134,7 +134,7 @@ namespace hactoolnet ctx.Logger.LogMessage("Unable to sign save file. Do you have all the required keys?"); } - fs.Unmount("save"); + fs.Unmount("save".ToU8Span()); return; } @@ -149,7 +149,7 @@ namespace hactoolnet ctx.Logger.LogMessage(save.Print(ctx.Keyset)); //ctx.Logger.LogMessage(PrintFatLayout(save.SaveDataFileSystemCore)); - fs.Unmount("save"); + fs.Unmount("save".ToU8Span()); } } diff --git a/tests/LibHac.Tests/Fs/FileSystemClientTests/ShimTests/SaveData.cs b/tests/LibHac.Tests/Fs/FileSystemClientTests/ShimTests/SaveData.cs index 61c5fd5a..3f4fbeda 100644 --- a/tests/LibHac.Tests/Fs/FileSystemClientTests/ShimTests/SaveData.cs +++ b/tests/LibHac.Tests/Fs/FileSystemClientTests/ShimTests/SaveData.cs @@ -16,7 +16,7 @@ namespace LibHac.Tests.Fs.FileSystemClientTests.ShimTests fs.CreateCacheStorage(applicationId, SaveDataSpaceId.User, applicationId, 0, 0, SaveDataFlags.None); - Assert.Success(fs.MountCacheStorage("cache".ToU8String(), applicationId)); + Assert.Success(fs.MountCacheStorage("cache".ToU8Span(), applicationId)); } [Fact] @@ -26,14 +26,14 @@ namespace LibHac.Tests.Fs.FileSystemClientTests.ShimTests FileSystemClient fs = FileSystemServerFactory.CreateClient(true); fs.CreateCacheStorage(applicationId, SaveDataSpaceId.SdCache, applicationId, 0, 0, SaveDataFlags.None); - fs.MountCacheStorage("cache".ToU8String(), applicationId); + fs.MountCacheStorage("cache".ToU8Span(), applicationId); - fs.CreateFile("cache:/file", 0); - fs.Commit("cache"); - fs.Unmount("cache"); + fs.CreateFile("cache:/file".ToU8Span(), 0); + fs.Commit("cache".ToU8Span()); + fs.Unmount("cache".ToU8Span()); - Assert.Success(fs.MountCacheStorage("cache".ToU8String(), applicationId)); - Assert.Success(fs.GetEntryType(out DirectoryEntryType type, "cache:/file")); + Assert.Success(fs.MountCacheStorage("cache".ToU8Span(), applicationId)); + Assert.Success(fs.GetEntryType(out DirectoryEntryType type, "cache:/file".ToU8Span())); Assert.Equal(DirectoryEntryType.File, type); } [Fact] @@ -43,25 +43,25 @@ namespace LibHac.Tests.Fs.FileSystemClientTests.ShimTests FileSystemClient fs = FileSystemServerFactory.CreateClient(true); fs.CreateCacheStorage(applicationId, SaveDataSpaceId.SdCache, applicationId, 0, 0, SaveDataFlags.None); - fs.MountCacheStorage("cache".ToU8String(), applicationId); - fs.CreateFile("cache:/sd", 0); - fs.Commit("cache"); - fs.Unmount("cache"); + fs.MountCacheStorage("cache".ToU8Span(), applicationId); + fs.CreateFile("cache:/sd".ToU8Span(), 0); + fs.Commit("cache".ToU8Span()); + fs.Unmount("cache".ToU8Span()); // Turn off the SD card so the User save is mounted fs.SetSdCardAccessibility(false); fs.CreateCacheStorage(applicationId, SaveDataSpaceId.User, applicationId, 0, 0, SaveDataFlags.None); - fs.MountCacheStorage("cache".ToU8String(), applicationId); - fs.CreateFile("cache:/bis", 0); - fs.Commit("cache"); - fs.Unmount("cache"); + fs.MountCacheStorage("cache".ToU8Span(), applicationId); + fs.CreateFile("cache:/bis".ToU8Span(), 0); + fs.Commit("cache".ToU8Span()); + fs.Unmount("cache".ToU8Span()); fs.SetSdCardAccessibility(true); Assert.Success(fs.MountCacheStorage("cache".ToU8String(), applicationId)); - Assert.Success(fs.GetEntryType(out _, "cache:/sd")); - Assert.Failure(fs.GetEntryType(out _, "cache:/bis")); + Assert.Success(fs.GetEntryType(out _, "cache:/sd".ToU8Span())); + Assert.Failure(fs.GetEntryType(out _, "cache:/bis".ToU8Span())); } } } diff --git a/tests/LibHac.Tests/Fs/FileSystemClientTests/ShimTests/SdCard.cs b/tests/LibHac.Tests/Fs/FileSystemClientTests/ShimTests/SdCard.cs index 86000580..f4742175 100644 --- a/tests/LibHac.Tests/Fs/FileSystemClientTests/ShimTests/SdCard.cs +++ b/tests/LibHac.Tests/Fs/FileSystemClientTests/ShimTests/SdCard.cs @@ -12,7 +12,7 @@ namespace LibHac.Tests.Fs.FileSystemClientTests.ShimTests { FileSystemClient fs = FileSystemServerFactory.CreateClient(true); - Assert.Success(fs.MountSdCard("sdcard".ToU8String())); + Assert.Success(fs.MountSdCard("sdcard".ToU8Span())); } [Fact] @@ -20,7 +20,7 @@ namespace LibHac.Tests.Fs.FileSystemClientTests.ShimTests { FileSystemClient fs = FileSystemServerFactory.CreateClient(false); - Assert.Result(ResultFs.SdCardNotFound, fs.MountSdCard("sdcard".ToU8String())); + Assert.Result(ResultFs.SdCardNotFound, fs.MountSdCard("sdcard".ToU8Span())); } [Fact] @@ -30,7 +30,7 @@ namespace LibHac.Tests.Fs.FileSystemClientTests.ShimTests fs.MountSdCard("sdcard".ToU8String()); - Assert.Success(fs.CreateFile("sdcard:/file", 100, CreateFileOptions.None)); + Assert.Success(fs.CreateFile("sdcard:/file".ToU8Span(), 100, CreateFileOptions.None)); } [Fact]