diff --git a/src/LibHac/Fs/Accessors/FileSystemAccessor.cs b/src/LibHac/Fs/Accessors/FileSystemAccessor.cs
index a51f1e6e..e6202b58 100644
--- a/src/LibHac/Fs/Accessors/FileSystemAccessor.cs
+++ b/src/LibHac/Fs/Accessors/FileSystemAccessor.cs
@@ -176,7 +176,9 @@ namespace LibHac.Fs.Accessors
{
// Todo: Possibly check for open files and directories
// Nintendo checks for them in DumpUnclosedAccessorList in
- // FileSystemAccessor's destructor, but doesn't do anything with it
+ // FileSystemAccessor's destructor
+
+ FileSystem?.Dispose();
}
}
}
diff --git a/src/LibHac/Fs/AttributeFileSystemBase.cs b/src/LibHac/Fs/AttributeFileSystemBase.cs
new file mode 100644
index 00000000..c7011cf5
--- /dev/null
+++ b/src/LibHac/Fs/AttributeFileSystemBase.cs
@@ -0,0 +1,46 @@
+namespace LibHac.Fs
+{
+ public abstract class AttributeFileSystemBase : FileSystemBase, IAttributeFileSystem
+ {
+ protected abstract Result CreateDirectoryImpl(string path, NxFileAttributes archiveAttribute);
+ protected abstract Result GetFileAttributesImpl(string path, out NxFileAttributes attributes);
+ protected abstract Result SetFileAttributesImpl(string path, NxFileAttributes attributes);
+ protected abstract Result GetFileSizeImpl(out long fileSize, string path);
+
+ public Result CreateDirectory(string path, NxFileAttributes archiveAttribute)
+ {
+ if (IsDisposed) return ResultFs.PreconditionViolation.Log();
+
+ return CreateDirectoryImpl(path, archiveAttribute);
+ }
+
+ public Result GetFileAttributes(string path, out NxFileAttributes attributes)
+ {
+ if (IsDisposed)
+ {
+ attributes = default;
+ return ResultFs.PreconditionViolation.Log();
+ }
+
+ return GetFileAttributesImpl(path, out attributes);
+ }
+
+ public Result SetFileAttributes(string path, NxFileAttributes attributes)
+ {
+ if (IsDisposed) return ResultFs.PreconditionViolation.Log();
+
+ return SetFileAttributesImpl(path, attributes);
+ }
+
+ public Result GetFileSize(out long fileSize, string path)
+ {
+ if (IsDisposed)
+ {
+ fileSize = default;
+ return ResultFs.PreconditionViolation.Log();
+ }
+
+ return GetFileSizeImpl(out fileSize, path);
+ }
+ }
+}
diff --git a/src/LibHac/Fs/FileSystemBase.cs b/src/LibHac/Fs/FileSystemBase.cs
index 889cad2e..f87cd1d9 100644
--- a/src/LibHac/Fs/FileSystemBase.cs
+++ b/src/LibHac/Fs/FileSystemBase.cs
@@ -7,7 +7,7 @@ namespace LibHac.Fs
{
// 0 = not disposed; 1 = disposed
private int _disposedState;
- private bool IsDisposed => _disposedState != 0;
+ protected bool IsDisposed => _disposedState != 0;
protected abstract Result CreateDirectoryImpl(string path);
protected abstract Result CreateFileImpl(string path, long size, CreateFileOptions options);
diff --git a/src/LibHac/Fs/FileSystemClient.AccessLog.cs b/src/LibHac/Fs/FileSystemClient.AccessLog.cs
index f7e89383..b60a5ce1 100644
--- a/src/LibHac/Fs/FileSystemClient.AccessLog.cs
+++ b/src/LibHac/Fs/FileSystemClient.AccessLog.cs
@@ -115,6 +115,16 @@ namespace LibHac.Fs
return accessor.IsAccessLogEnabled;
}
+ internal void EnableFileSystemAccessorAccessLog(U8Span mountName)
+ {
+ if (MountTable.Find(mountName.ToString(), out FileSystemAccessor accessor).IsFailure())
+ {
+ throw new LibHacException("abort");
+ }
+
+ accessor.IsAccessLogEnabled = true;
+ }
+
internal bool IsEnabledHandleAccessLog(FileHandle handle)
{
return handle.File.Parent.IsAccessLogEnabled;
diff --git a/src/LibHac/Fs/IFileSystem.cs b/src/LibHac/Fs/IFileSystem.cs
index 91721465..09c3b16d 100644
--- a/src/LibHac/Fs/IFileSystem.cs
+++ b/src/LibHac/Fs/IFileSystem.cs
@@ -6,7 +6,7 @@ namespace LibHac.Fs
///
/// Provides an interface for accessing a file system. / is used as the path delimiter.
///
- public interface IFileSystem
+ public interface IFileSystem : IDisposable
{
///
/// Creates or overwrites a file at the specified path.
diff --git a/src/LibHac/FsService/Creators/SaveDataFileSystemCreator.cs b/src/LibHac/FsService/Creators/SaveDataFileSystemCreator.cs
index b5b4934f..ca5ccd43 100644
--- a/src/LibHac/FsService/Creators/SaveDataFileSystemCreator.cs
+++ b/src/LibHac/FsService/Creators/SaveDataFileSystemCreator.cs
@@ -55,8 +55,8 @@ namespace LibHac.FsService.Creators
rc = sourceFileSystem.OpenFile(out IFile saveDataFile, saveDataPath, OpenMode.ReadWrite);
if (rc.IsFailure()) return rc;
- var saveDataStorage = new FileStorage(saveDataFile);
- fileSystem = new SaveDataFileSystem(Keyset, saveDataStorage, IntegrityCheckLevel.ErrorOnInvalid, true);
+ var saveDataStorage = new DisposingFileStorage(saveDataFile);
+ fileSystem = new SaveDataFileSystem(Keyset, saveDataStorage, IntegrityCheckLevel.ErrorOnInvalid, false);
// Todo: ISaveDataExtraDataAccessor
diff --git a/src/LibHac/FsService/FileSystemProxy.cs b/src/LibHac/FsService/FileSystemProxy.cs
index 9a1c4995..170d1a6b 100644
--- a/src/LibHac/FsService/FileSystemProxy.cs
+++ b/src/LibHac/FsService/FileSystemProxy.cs
@@ -24,8 +24,6 @@ namespace LibHac.FsService
public FsPath SaveDataRootPath { get; } = default;
public bool AutoCreateSaveData { get; private set; }
- private const ulong SaveIndexerId = 0x8000000000000000;
-
internal FileSystemProxy(FileSystemProxyCore fsProxyCore, FileSystemClient fsClient, FileSystemServer fsServer)
{
FsProxyCore = fsProxyCore;
@@ -189,7 +187,7 @@ namespace LibHac.FsService
if (saveFsResult != ResultFs.PathNotFound && saveFsResult != ResultFs.TargetNotFound) return saveFsResult;
- if (saveDataId != SaveIndexerId)
+ if (saveDataId != FileSystemServer.SaveIndexerId)
{
if (hasFixedId)
{
diff --git a/src/LibHac/FsService/FileSystemServer.cs b/src/LibHac/FsService/FileSystemServer.cs
index fee81bb5..6b248f96 100644
--- a/src/LibHac/FsService/FileSystemServer.cs
+++ b/src/LibHac/FsService/FileSystemServer.cs
@@ -6,12 +6,12 @@ namespace LibHac.FsService
{
public class FileSystemServer
{
- internal const ulong SaveDataIndexerSaveId = 0x8000000000000000;
+ internal const ulong SaveIndexerId = 0x8000000000000000;
private FileSystemProxyCore FsProxyCore { get; }
/// The client instance to be used for internal operations like save indexer access.
- private FileSystemClient FsClient { get; }
+ public FileSystemClient FsClient { get; }
private ITimeSpanGenerator Timer { get; }
internal SaveDataIndexerManager SaveDataIndexerManager { get; }
@@ -35,7 +35,7 @@ namespace LibHac.FsService
FsClient = new FileSystemClient(this, timer);
Timer = timer;
- SaveDataIndexerManager = new SaveDataIndexerManager(FsClient, SaveDataIndexerSaveId);
+ SaveDataIndexerManager = new SaveDataIndexerManager(FsClient, SaveIndexerId);
}
///
diff --git a/src/LibHac/FsSystem/FileStorage.cs b/src/LibHac/FsSystem/FileStorage.cs
index d9cc1f88..29c5d240 100644
--- a/src/LibHac/FsSystem/FileStorage.cs
+++ b/src/LibHac/FsSystem/FileStorage.cs
@@ -5,7 +5,7 @@ namespace LibHac.FsSystem
{
public class FileStorage : StorageBase
{
- private IFile BaseFile { get; }
+ protected IFile BaseFile { get; }
public FileStorage(IFile baseFile)
{
@@ -37,4 +37,17 @@ namespace LibHac.FsSystem
return BaseFile.SetSize(size);
}
}
+
+ public class DisposingFileStorage : FileStorage
+ {
+ public DisposingFileStorage(IFile baseFile) : base(baseFile) { }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ BaseFile?.Dispose();
+ }
+ }
+ }
}
diff --git a/src/LibHac/FsSystem/LocalFileSystem.cs b/src/LibHac/FsSystem/LocalFileSystem.cs
index 69425b06..a6372069 100644
--- a/src/LibHac/FsSystem/LocalFileSystem.cs
+++ b/src/LibHac/FsSystem/LocalFileSystem.cs
@@ -6,7 +6,7 @@ using LibHac.Fs;
namespace LibHac.FsSystem
{
- public class LocalFileSystem : IAttributeFileSystem
+ public class LocalFileSystem : AttributeFileSystemBase
{
private string BasePath { get; }
@@ -30,7 +30,7 @@ namespace LibHac.FsSystem
return PathTools.Combine(BasePath, path);
}
- public Result GetFileAttributes(string path, out NxFileAttributes attributes)
+ protected override Result GetFileAttributesImpl(string path, out NxFileAttributes attributes)
{
attributes = default;
@@ -49,7 +49,7 @@ namespace LibHac.FsSystem
return Result.Success;
}
- public Result SetFileAttributes(string path, NxFileAttributes attributes)
+ protected override Result SetFileAttributesImpl(string path, NxFileAttributes attributes)
{
string localPath = ResolveLocalPath(PathTools.Normalize(path));
@@ -76,7 +76,7 @@ namespace LibHac.FsSystem
return Result.Success;
}
- public Result GetFileSize(out long fileSize, string path)
+ protected override Result GetFileSizeImpl(out long fileSize, string path)
{
fileSize = default;
string localPath = ResolveLocalPath(PathTools.Normalize(path));
@@ -87,12 +87,12 @@ namespace LibHac.FsSystem
return GetSizeInternal(out fileSize, info);
}
- public Result CreateDirectory(string path)
+ protected override Result CreateDirectoryImpl(string path)
{
return CreateDirectory(path, NxFileAttributes.None);
}
- public Result CreateDirectory(string path, NxFileAttributes archiveAttribute)
+ protected override Result CreateDirectoryImpl(string path, NxFileAttributes archiveAttribute)
{
string localPath = ResolveLocalPath(PathTools.Normalize(path));
@@ -112,7 +112,7 @@ namespace LibHac.FsSystem
return CreateDirInternal(dir, archiveAttribute);
}
- public Result CreateFile(string path, long size, CreateFileOptions options)
+ protected override Result CreateFileImpl(string path, long size, CreateFileOptions options)
{
string localPath = ResolveLocalPath(PathTools.Normalize(path));
@@ -139,7 +139,7 @@ namespace LibHac.FsSystem
}
}
- public Result DeleteDirectory(string path)
+ protected override Result DeleteDirectoryImpl(string path)
{
string localPath = ResolveLocalPath(PathTools.Normalize(path));
@@ -149,7 +149,7 @@ namespace LibHac.FsSystem
return DeleteDirectoryInternal(dir, false);
}
- public Result DeleteDirectoryRecursively(string path)
+ protected override Result DeleteDirectoryRecursivelyImpl(string path)
{
string localPath = ResolveLocalPath(PathTools.Normalize(path));
@@ -159,7 +159,7 @@ namespace LibHac.FsSystem
return DeleteDirectoryInternal(dir, true);
}
- public Result CleanDirectoryRecursively(string path)
+ protected override Result CleanDirectoryRecursivelyImpl(string path)
{
string localPath = ResolveLocalPath(PathTools.Normalize(path));
@@ -184,7 +184,7 @@ namespace LibHac.FsSystem
return Result.Success;
}
- public Result DeleteFile(string path)
+ protected override Result DeleteFileImpl(string path)
{
string localPath = ResolveLocalPath(PathTools.Normalize(path));
@@ -194,7 +194,7 @@ namespace LibHac.FsSystem
return DeleteFileInternal(file);
}
- public Result OpenDirectory(out IDirectory directory, string path, OpenDirectoryMode mode)
+ protected override Result OpenDirectoryImpl(out IDirectory directory, string path, OpenDirectoryMode mode)
{
directory = default;
string localPath = ResolveLocalPath(PathTools.Normalize(path));
@@ -220,7 +220,7 @@ namespace LibHac.FsSystem
}
}
- public Result OpenFile(out IFile file, string path, OpenMode mode)
+ protected override Result OpenFileImpl(out IFile file, string path, OpenMode mode)
{
file = default;
string localPath = ResolveLocalPath(PathTools.Normalize(path));
@@ -240,7 +240,7 @@ namespace LibHac.FsSystem
return Result.Success;
}
- public Result RenameDirectory(string oldPath, string newPath)
+ protected override Result RenameDirectoryImpl(string oldPath, string newPath)
{
oldPath = PathTools.Normalize(oldPath);
newPath = PathTools.Normalize(newPath);
@@ -263,7 +263,7 @@ namespace LibHac.FsSystem
return RenameDirInternal(srcDir, dstDir);
}
- public Result RenameFile(string oldPath, string newPath)
+ protected override Result RenameFileImpl(string oldPath, string newPath)
{
string srcLocalPath = ResolveLocalPath(PathTools.Normalize(oldPath));
string dstLocalPath = ResolveLocalPath(PathTools.Normalize(newPath));
@@ -280,7 +280,7 @@ namespace LibHac.FsSystem
return RenameFileInternal(srcFile, dstFile);
}
- public Result GetEntryType(out DirectoryEntryType entryType, string path)
+ protected override Result GetEntryTypeImpl(out DirectoryEntryType entryType, string path)
{
entryType = default;
string localPath = ResolveLocalPath(PathTools.Normalize(path));
@@ -307,7 +307,7 @@ namespace LibHac.FsSystem
return ResultFs.PathNotFound.Log();
}
- public Result GetFileTimeStampRaw(out FileTimeStampRaw timeStamp, string path)
+ protected override Result GetFileTimeStampRawImpl(out FileTimeStampRaw timeStamp, string path)
{
timeStamp = default;
string localPath = ResolveLocalPath(PathTools.Normalize(path));
@@ -324,24 +324,24 @@ namespace LibHac.FsSystem
return Result.Success;
}
- public Result GetFreeSpaceSize(out long freeSpace, string path)
+ protected override Result GetFreeSpaceSizeImpl(out long freeSpace, string path)
{
freeSpace = new DriveInfo(BasePath).AvailableFreeSpace;
return Result.Success;
}
- public Result GetTotalSpaceSize(out long totalSpace, string path)
+ protected override Result GetTotalSpaceSizeImpl(out long totalSpace, string path)
{
totalSpace = new DriveInfo(BasePath).TotalSize;
return Result.Success;
}
- public Result Commit()
+ protected override Result CommitImpl()
{
return Result.Success;
}
- public Result QueryEntry(Span outBuffer, ReadOnlySpan inBuffer, QueryId queryId, string path)
+ protected override Result QueryEntryImpl(Span outBuffer, ReadOnlySpan inBuffer, QueryId queryId, string path)
{
return ResultFs.UnsupportedOperation.Log();
}
diff --git a/src/LibHac/FsSystem/Save/SaveDataFileSystem.cs b/src/LibHac/FsSystem/Save/SaveDataFileSystem.cs
index e0a01582..51e8a827 100644
--- a/src/LibHac/FsSystem/Save/SaveDataFileSystem.cs
+++ b/src/LibHac/FsSystem/Save/SaveDataFileSystem.cs
@@ -302,5 +302,16 @@ namespace LibHac.FsSystem.Save
return journalValidity;
}
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ if (!LeaveOpen)
+ {
+ BaseStorage?.Dispose();
+ }
+ }
+ }
}
}