protected override Result DoRenameFile(U8Span oldPath, U8Span newPath) { return(FsTable.RenameFile(new U8Span(oldPath), new U8Span(newPath))); }
// DeleteDirectoryRecursively(buffer<bytes<0x301>, 0x19, 0x301> path) public ResultCode DeleteDirectoryRecursively(ServiceCtx context) { U8Span name = ReadUtf8Span(context); return((ResultCode)_fileSystem.DeleteDirectoryRecursively(name).Value); }
private Result SetConcatenationFileAttribute(U8Span path) { return(BaseFileSystem.SetFileAttributes(path, NxFileAttributes.Archive)); }
protected override Result DoGetTotalSpaceSize(out long totalSpace, U8Span path) { return(BaseFileSystem.GetTotalSpaceSize(out totalSpace, path)); }
// DeleteFile(buffer<bytes<0x301>, 0x19, 0x301> path) public ResultCode DeleteFile(ServiceCtx context) { U8Span name = ReadUtf8Span(context); return((ResultCode)_fileSystem.DeleteFile(name).Value); }
protected override Result OpenFileImpl(out IFile file, U8Span path, OpenMode mode) { Result result = SaveDataFileSystemCore.OpenFile(out file, path, mode); return(SaveResults.ConvertToExternalResult(result).LogConverted(result)); }
protected override Result GetEntryTypeImpl(out DirectoryEntryType entryType, U8Span path) { Result result = SaveDataFileSystemCore.GetEntryType(out entryType, path); return(SaveResults.ConvertToExternalResult(result).LogConverted(result)); }
protected override Result DoDeleteFile(U8Span path) { return(FsTable.DeleteFile(new U8Span(path))); }
public Result OpenFileSystemWithPatch(out ReferenceCountedDisposable <IFileSystemSf> fileSystem, ProgramId programId, FileSystemProxyType fsType) { UnsafeHelpers.SkipParamInit(out fileSystem); const StorageType storageFlag = StorageType.All; using var scopedLayoutType = new ScopedStorageLayoutTypeSetter(storageFlag); // Get the program info for the caller and verify permissions Result rc = GetProgramInfo(out ProgramInfo callerProgramInfo); if (rc.IsFailure()) { return(rc); } if (fsType != FileSystemProxyType.Manual) { if (fsType == FileSystemProxyType.Logo || fsType == FileSystemProxyType.Control) { return(ResultFs.NotImplemented.Log()); } else { return(ResultFs.InvalidArgument.Log()); } } Accessibility accessibility = callerProgramInfo.AccessControl.GetAccessibilityFor(AccessibilityType.MountContentManual); if (!accessibility.CanRead) { return(ResultFs.PermissionDenied.Log()); } // Get the program info for the owner of the file system being opened rc = GetProgramInfoByProgramId(out ProgramInfo ownerProgramInfo, programId.Value); if (rc.IsFailure()) { return(rc); } // Try to find the path to the original version of the file system Result originalResult = ServiceImpl.ResolveApplicationHtmlDocumentPath(out Path originalPath, new Ncm.ApplicationId(programId.Value), ownerProgramInfo.StorageId); // The file system might have a patch version with no original version, so continue if not found if (originalResult.IsFailure() && !ResultLr.HtmlDocumentNotFound.Includes(originalResult)) { return(originalResult); } // Use a separate bool because ref structs can't be used as type parameters bool originalPathNormalizerHasValue = false; PathNormalizer originalPathNormalizer = default; // Normalize the original version path if found if (originalResult.IsSuccess()) { originalPathNormalizer = new PathNormalizer(originalPath, GetPathNormalizerOptions(originalPath)); if (originalPathNormalizer.Result.IsFailure()) { return(originalPathNormalizer.Result); } originalPathNormalizerHasValue = true; } // Try to find the path to the patch file system Result patchResult = ServiceImpl.ResolveRegisteredHtmlDocumentPath(out Path patchPath, programId.Value); ReferenceCountedDisposable <IFileSystem> tempFileSystem = null; ReferenceCountedDisposable <IRomFileSystemAccessFailureManager> accessFailureManager = null; try { if (ResultLr.HtmlDocumentNotFound.Includes(patchResult)) { // There must either be an original version or patch version of the file system being opened if (originalResult.IsFailure()) { return(originalResult); } Assert.True(originalPathNormalizerHasValue); // There is an original version and no patch version. Open the original directly rc = ServiceImpl.OpenFileSystem(out tempFileSystem, originalPathNormalizer.Path, fsType, programId.Value); if (rc.IsFailure()) { return(rc); } } else { // Get the normalized path to the original file system U8Span normalizedOriginalPath; if (originalPathNormalizerHasValue) { normalizedOriginalPath = originalPathNormalizer.Path; } else { normalizedOriginalPath = U8Span.Empty; } // Normalize the path to the patch file system var patchPathNormalizer = new PathNormalizer(patchPath, GetPathNormalizerOptions(patchPath)); if (patchPathNormalizer.Result.IsFailure()) { return(patchPathNormalizer.Result); } if (patchResult.IsFailure()) { return(patchResult); } U8Span normalizedPatchPath = patchPathNormalizer.Path; // Open the file system using both the original and patch versions rc = ServiceImpl.OpenFileSystemWithPatch(out tempFileSystem, normalizedOriginalPath, normalizedPatchPath, fsType, programId.Value); if (rc.IsFailure()) { return(rc); } } // Add all the file system wrappers tempFileSystem = StorageLayoutTypeSetFileSystem.CreateShared(ref tempFileSystem, storageFlag); tempFileSystem = AsynchronousAccessFileSystem.CreateShared(ref tempFileSystem); accessFailureManager = SelfReference.AddReference <IRomFileSystemAccessFailureManager>(); tempFileSystem = DeepRetryFileSystem.CreateShared(ref tempFileSystem, ref accessFailureManager); fileSystem = FileSystemInterfaceAdapter.CreateShared(ref tempFileSystem); return(Result.Success); } finally { tempFileSystem?.Dispose(); accessFailureManager?.Dispose(); } }
protected override Result DoDeleteDirectoryRecursively(U8Span path) { return(FsTable.DeleteDirectory(new U8Span(path), true)); }
protected override Result DoCleanDirectoryRecursively(U8Span path) { return(FsTable.CleanDirectory(new U8Span(path))); }
protected override Result DoDeleteDirectory(U8Span path) { return(FsTable.DeleteDirectory(new U8Span(path), false)); }
protected override Result DoCreateDirectory(U8Span path) { return(FsTable.AddDirectory(new U8Span(path))); }
protected override Result DoGetFileAttributes(out NxFileAttributes attributes, U8Span path) { if (FsTable.GetFile(path, out FileNode file).IsSuccess()) { attributes = file.Attributes; return(Result.Success); } if (FsTable.GetDirectory(path, out DirectoryNode dir).IsSuccess()) { attributes = dir.Attributes; return(Result.Success); } attributes = default; return(ResultFs.PathNotFound.Log()); }
protected override Result DeleteFileImpl(U8Span path) { Result result = SaveDataFileSystemCore.DeleteFile(path); return(SaveResults.ConvertToExternalResult(result).LogConverted(result)); }
// todo: Decide how to handle SetBisRootForHost since it allows mounting any directory on the user's computer public static Result SetBisRootForHost(this FileSystemClient fs, BisPartitionId partitionId, U8Span rootPath) { FsPath sfPath; unsafe { _ = &sfPath; } // workaround for CS0165 int pathLen = StringUtils.GetLength(rootPath, PathTools.MaxPathLength + 1); if (pathLen > PathTools.MaxPathLength) { return(ResultFs.TooLongPath.Log()); } if (pathLen > 0) { byte endingSeparator = PathTool.IsSeparator(rootPath[pathLen - 1]) ? StringTraits.NullTerminator : StringTraits.DirectorySeparator; var sb = new U8StringBuilder(sfPath.Str); Result rc = sb.Append(rootPath).Append(endingSeparator).ToSfPath(); if (rc.IsFailure()) { return(rc); } } else { sfPath.Str[0] = StringTraits.NullTerminator; } IFileSystemProxy fsProxy = fs.GetFileSystemProxyServiceObject(); return(fsProxy.SetBisRootForHost(partitionId, ref sfPath)); }
protected override Result OpenDirectoryImpl(out IDirectory directory, U8Span path, OpenDirectoryMode mode) { Result result = SaveDataFileSystemCore.OpenDirectory(out directory, path, mode); return(SaveResults.ConvertToExternalResult(result).LogConverted(result)); }
public static Result MountBis(this FileSystemClient fs, U8Span mountName, BisPartitionId partitionId) { return(MountBis(fs, mountName, partitionId, default)); }
protected override Result RenameFileImpl(U8Span oldPath, U8Span newPath) { Result result = SaveDataFileSystemCore.RenameFile(oldPath, newPath); return(SaveResults.ConvertToExternalResult(result).LogConverted(result)); }
public static Result MountBis(this FileSystemClient fs, BisPartitionId partitionId, U8Span rootPath) { return(MountBis(fs, GetBisMountName(partitionId), partitionId, rootPath)); }
protected override Result GetTotalSpaceSizeImpl(out long totalSpace, U8Span path) { Result result = SaveDataFileSystemCore.GetTotalSpaceSize(out totalSpace, path); return(SaveResults.ConvertToExternalResult(result).LogConverted(result)); }
// nn::fs::detail::MountBis private static Result MountBis(FileSystemClient fs, U8Span mountName, BisPartitionId partitionId, U8Span rootPath) { Result rc; if (fs.IsEnabledAccessLog(AccessLogTarget.System)) { TimeSpan startTime = fs.Time.GetCurrent(); rc = MountBisImpl(fs, mountName, partitionId, rootPath); TimeSpan endTime = fs.Time.GetCurrent(); string logMessage = $", name: \"{mountName.ToString()}\", bispartitionid: {partitionId}, path: \"{rootPath.ToString()}\""; fs.OutputAccessLog(rc, startTime, endTime, logMessage); } else { rc = MountBisImpl(fs, mountName, partitionId, rootPath); } if (rc.IsFailure()) { return(rc); } if (fs.IsEnabledAccessLog(AccessLogTarget.System)) { fs.EnableFileSystemAccessorAccessLog(mountName); } return(Result.Success); }
protected override Result DoGetFileTimeStampRaw(out FileTimeStampRaw timeStamp, U8Span path) { return(BaseFileSystem.GetFileTimeStampRaw(out timeStamp, path)); }
// ReSharper disable once UnusedParameter.Local private static Result MountBisImpl(FileSystemClient fs, U8Span mountName, BisPartitionId partitionId, U8Span rootPath) { Result rc = MountHelpers.CheckMountNameAcceptingReservedMountName(mountName); if (rc.IsFailure()) { return(rc); } FsPath sfPath; unsafe { _ = &sfPath; } // workaround for CS0165 IFileSystemProxy fsProxy = fs.GetFileSystemProxyServiceObject(); // Nintendo doesn't use the provided rootPath sfPath.Str[0] = 0; rc = fsProxy.OpenBisFileSystem(out IFileSystem fileSystem, ref sfPath, partitionId); if (rc.IsFailure()) { return(rc); } var nameGenerator = new BisCommonMountNameGenerator(partitionId); return(fs.Register(mountName, fileSystem, nameGenerator)); }
// CreateDirectory(buffer<bytes<0x301>, 0x19, 0x301> path) public ResultCode CreateDirectory(ServiceCtx context) { U8Span name = ReadUtf8Span(context); return((ResultCode)_fileSystem.CreateDirectory(name).Value); }
protected override Result CreateFileImpl(U8Span path, long size, CreateFileOptions options) { Result result = SaveDataFileSystemCore.CreateFile(path, size, options); return(SaveResults.ConvertToExternalResult(result).LogConverted(result)); }
private static bool Matches(FileSystemAccessor accessor, U8Span name) { return(StringUtils.Compare(accessor.GetName(), name, Unsafe.SizeOf <MountName>()) == 0); }
protected override Result CleanDirectoryRecursivelyImpl(U8Span path) { Result result = SaveDataFileSystemCore.CleanDirectoryRecursively(path); return(SaveResults.ConvertToExternalResult(result).LogConverted(result)); }
protected override Result DoGetFreeSpaceSize(out long freeSpace, U8Span path) { return(BaseFileSystem.GetFreeSpaceSize(out freeSpace, path)); }
public Result Register(U8Span mountName, IFileSystem fileSystem) { return(Register(mountName, fileSystem, null)); }