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(); + } + } + } } }