// 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)); }
// 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)); }
static Result Mount(FileSystemClientImpl fs, U8Span mountName, BisPartitionId partitionId) { Result rc = fs.CheckMountNameAcceptingReservedMountName(mountName); if (rc.IsFailure()) { return(rc); } using ReferenceCountedDisposable <IFileSystemProxy> fsProxy = fs.GetFileSystemProxyServiceObject(); // Nintendo doesn't use the provided rootPath FspPath.CreateEmpty(out FspPath sfPath); ReferenceCountedDisposable <IFileSystemSf> fileSystem = null; try { rc = fsProxy.Target.OpenBisFileSystem(out fileSystem, in sfPath, partitionId); if (rc.IsFailure()) { return(rc); } var nameGenerator = new BisCommonMountNameGenerator(partitionId); var fileSystemAdapter = new FileSystemServiceObjectAdapter(fileSystem); return(fs.Fs.Register(mountName, fileSystemAdapter, nameGenerator)); } finally { fileSystem?.Dispose(); } }
public static U8Span GetBisMountName(BisPartitionId partitionId) { switch (partitionId) { case BisPartitionId.BootPartition1Root: case BisPartitionId.BootPartition2Root: case BisPartitionId.UserDataRoot: case BisPartitionId.BootConfigAndPackage2Part1: case BisPartitionId.BootConfigAndPackage2Part2: case BisPartitionId.BootConfigAndPackage2Part3: case BisPartitionId.BootConfigAndPackage2Part4: case BisPartitionId.BootConfigAndPackage2Part5: case BisPartitionId.BootConfigAndPackage2Part6: case BisPartitionId.CalibrationBinary: throw new HorizonResultException(default, "The partition specified is not mountable."); case BisPartitionId.CalibrationFile: return(BisCalibrationFilePartitionMountName); case BisPartitionId.SafeMode: return(BisSafeModePartitionMountName); case BisPartitionId.User: return(BisUserPartitionMountName); case BisPartitionId.System: return(BisSystemPartitionMountName); default: throw new ArgumentOutOfRangeException(nameof(partitionId), partitionId, null); } }
// 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); }
private static Result GetAccessibilityForOpenBisPartition(out Accessibility accessibility, ProgramInfo programInfo, BisPartitionId partitionId) { UnsafeHelpers.SkipParamInit(out accessibility); AccessibilityType type = partitionId switch { BisPartitionId.BootPartition1Root => AccessibilityType.OpenBisPartitionBootPartition1Root, BisPartitionId.BootPartition2Root => AccessibilityType.OpenBisPartitionBootPartition2Root, BisPartitionId.UserDataRoot => AccessibilityType.OpenBisPartitionUserDataRoot, BisPartitionId.BootConfigAndPackage2Part1 => AccessibilityType.OpenBisPartitionBootConfigAndPackage2Part1, BisPartitionId.BootConfigAndPackage2Part2 => AccessibilityType.OpenBisPartitionBootConfigAndPackage2Part2, BisPartitionId.BootConfigAndPackage2Part3 => AccessibilityType.OpenBisPartitionBootConfigAndPackage2Part3, BisPartitionId.BootConfigAndPackage2Part4 => AccessibilityType.OpenBisPartitionBootConfigAndPackage2Part4, BisPartitionId.BootConfigAndPackage2Part5 => AccessibilityType.OpenBisPartitionBootConfigAndPackage2Part5, BisPartitionId.BootConfigAndPackage2Part6 => AccessibilityType.OpenBisPartitionBootConfigAndPackage2Part6, BisPartitionId.CalibrationBinary => AccessibilityType.OpenBisPartitionCalibrationBinary, BisPartitionId.CalibrationFile => AccessibilityType.OpenBisPartitionCalibrationFile, BisPartitionId.SafeMode => AccessibilityType.OpenBisPartitionSafeMode, BisPartitionId.User => AccessibilityType.OpenBisPartitionUser, BisPartitionId.System => AccessibilityType.OpenBisPartitionSystem, BisPartitionId.SystemProperEncryption => AccessibilityType.OpenBisPartitionSystemProperEncryption, BisPartitionId.SystemProperPartition => AccessibilityType.OpenBisPartitionSystemProperPartition, _ => (AccessibilityType)(-1) }; if (type == (AccessibilityType)(-1)) { return(ResultFs.InvalidArgument.Log()); } accessibility = programInfo.AccessControl.GetAccessibilityFor(type); return(Result.Success); } }
private string GetPartitionPath(BisPartitionId id) { if (Config.TryGetPartitionPath(out string path, id)) { return(path); } return(GetDefaultPartitionPath(id)); }
// Todo: Make case sensitive public Result Create(out ReferenceCountedDisposable <IFileSystem> fileSystem, U8Span rootPath, BisPartitionId partitionId, bool caseSensitive) { UnsafeHelpers.SkipParamInit(out fileSystem); if (!IsValidPartitionId(partitionId)) { return(ResultFs.InvalidArgument.Log()); } if (rootPath.IsNull()) { return(ResultFs.NullptrArgument.Log()); } if (Config.TryGetFileSystem(out IFileSystem fs, partitionId)) { fileSystem = new ReferenceCountedDisposable <IFileSystem>(fs); return(Result.Success); } if (Config.RootFileSystem == null) { return(ResultFs.PreconditionViolation.Log()); } var partitionPath = GetPartitionPath(partitionId).ToU8String(); ReferenceCountedDisposable <IFileSystem> partitionFileSystem = null; ReferenceCountedDisposable <IFileSystem> sharedRootFs = null; try { sharedRootFs = new ReferenceCountedDisposable <IFileSystem>(Config.RootFileSystem); Result rc = Utility.WrapSubDirectory(out partitionFileSystem, ref sharedRootFs, partitionPath, true); if (rc.IsFailure()) { return(rc); } if (rootPath.IsEmpty()) { Shared.Move(out fileSystem, ref partitionFileSystem); return(Result.Success); } return(Utility.CreateSubDirectoryFileSystem(out fileSystem, ref partitionFileSystem, rootPath)); } finally { partitionFileSystem?.Dispose(); sharedRootFs?.Dispose(); } }
public bool TryGetFileSystem(out IFileSystem fileSystem, BisPartitionId partitionId) { if (!IsValidPartitionId(partitionId)) { UnsafeHelpers.SkipParamInit(out fileSystem); return(false); } fileSystem = PartitionFileSystems[GetArrayIndex(partitionId)]; return(fileSystem != null); }
public bool TryGetFileSystem(out IFileSystem fileSystem, BisPartitionId partitionId) { if (!IsValidPartitionId(partitionId)) { fileSystem = default; return(false); } fileSystem = PartitionFileSystems[GetArrayIndex(partitionId)]; return(fileSystem != null); }
public bool TryGetPartitionPath(out string path, BisPartitionId partitionId) { if (!IsValidPartitionId(partitionId)) { path = default; return(false); } path = PartitionPaths[GetArrayIndex(partitionId)]; return(path != null); }
public bool TryGetPartitionPath(out string path, BisPartitionId partitionId) { if (!IsValidPartitionId(partitionId)) { UnsafeHelpers.SkipParamInit(out path); return(false); } path = PartitionPaths[GetArrayIndex(partitionId)]; return(path != null); }
public Result SetPath(string path, BisPartitionId partitionId) { if (path == null) { return(ResultFs.NullptrArgument.Log()); } if (!IsValidPartitionId(partitionId)) { return(ResultFs.InvalidArgument.Log()); } PartitionPaths[GetArrayIndex(partitionId)] = path; return(Result.Success); }
public Result SetFileSystem(IFileSystem fileSystem, BisPartitionId partitionId) { if (fileSystem == null) { return(ResultFs.NullptrArgument.Log()); } if (!IsValidPartitionId(partitionId)) { return(ResultFs.InvalidArgument.Log()); } PartitionFileSystems[GetArrayIndex(partitionId)] = fileSystem; return(Result.Success); }
public Result Create(out IFileSystem fileSystem, string rootPath, BisPartitionId partitionId) { fileSystem = default; if (!IsValidPartitionId(partitionId)) { return(ResultFs.InvalidArgument); } if (rootPath == null) { return(ResultFs.NullArgument); } if (Config.TryGetFileSystem(out fileSystem, partitionId)) { return(Result.Success); } if (Config.RootFileSystem == null) { return(ResultFs.PreconditionViolation); } string partitionPath = GetPartitionPath(partitionId); Result rc = Util.CreateSubFileSystem(out IFileSystem subFileSystem, Config.RootFileSystem, partitionPath, true); if (rc.IsFailure()) { return(rc); } if (rootPath == string.Empty) { fileSystem = subFileSystem; return(Result.Success); } return(Util.CreateSubFileSystemImpl(out fileSystem, subFileSystem, rootPath)); }
// OpenBisFileSystem(nn::fssrv::sf::Partition partitionID, buffer<bytes<0x301>, 0x19, 0x301>) -> object<nn::fssrv::sf::IFileSystem> Bis public ResultCode OpenBisFileSystem(ServiceCtx context) { BisPartitionId bisPartitionId = (BisPartitionId)context.RequestData.ReadInt32(); Result rc = FileSystemProxyHelper.ReadFsPath(out FsPath path, context); if (rc.IsFailure()) { return((ResultCode)rc.Value); } rc = _baseFileSystemProxy.OpenBisFileSystem(out LibHac.Fs.Fsa.IFileSystem fileSystem, ref path, bisPartitionId); if (rc.IsFailure()) { return((ResultCode)rc.Value); } MakeObject(context, new FileSystemProxy.IFileSystem(fileSystem)); return(ResultCode.Success); }
private string GetDefaultPartitionPath(BisPartitionId id) { Debug.Assert(IsValidPartitionId(id)); switch (id) { case BisPartitionId.CalibrationFile: return("/bis/cal"); case BisPartitionId.SafeMode: return("/bis/safe"); case BisPartitionId.User: return("/bis/user"); case BisPartitionId.System: return("/bis/system"); default: return(string.Empty); } }
public Result OpenBisStorage(out IStorage storage, BisPartitionId partitionId) { throw new NotImplementedException(); }
public Result OpenBisFileSystem(out IFileSystem fileSystem, ref FsPath rootPath, BisPartitionId partitionId) { fileSystem = default; // Missing permission check, speed emulation storage type wrapper, and FileSystemInterfaceAdapter Result rc = PathTools.Normalize(out U8Span normalizedPath, rootPath); if (rc.IsFailure()) { return(rc); } return(FsProxyCore.OpenBisFileSystem(out fileSystem, normalizedPath.ToString(), partitionId)); }
public Result SetBisRootForHost(BisPartitionId partitionId, ref FsPath path) { throw new NotImplementedException(); }
private static Result MountBis(this FileSystemClientImpl fs, U8Span mountName, BisPartitionId partitionId, U8Span rootPath) { Result rc; if (fs.IsEnabledAccessLog(AccessLogTarget.System)) { Tick start = fs.Hos.Os.GetSystemTick(); rc = Mount(fs, mountName, partitionId); Tick end = fs.Hos.Os.GetSystemTick(); Span <byte> logBuffer = stackalloc byte[0x300]; var idString = new IdString(); var sb = new U8StringBuilder(logBuffer, true); sb.Append(LogName).Append(mountName).Append(LogQuote) .Append(LogBisPartitionId).Append(idString.ToString(partitionId)) .Append(LogPath).Append(rootPath).Append(LogQuote); fs.OutputAccessLog(rc, start, end, null, new U8Span(sb.Buffer)); } else { rc = Mount(fs, mountName, partitionId); } fs.AbortIfNeeded(rc); if (rc.IsFailure()) { return(rc); } if (fs.IsEnabledAccessLog(AccessLogTarget.System)) { fs.EnableFileSystemAccessorAccessLog(mountName); } return(Result.Success);
private bool IsValidPartitionId(BisPartitionId id) { return(id >= BisPartitionId.CalibrationFile && id <= BisPartitionId.System); }
public Result CreateFatFileSystem(out IFileSystem fileSystem, BisPartitionId partitionId) { fileSystem = default; return(ResultFs.NotImplemented); }
private int GetArrayIndex(BisPartitionId id) { Debug.Assert(IsValidPartitionId(id)); return(id - BisPartitionId.CalibrationFile); }
public BisCommonMountNameGenerator(BisPartitionId partitionId) { PartitionId = partitionId; }
public static Result OpenBisPartition(this FileSystemClient fs, out IStorage partitionStorage, BisPartitionId partitionId) { partitionStorage = default; IFileSystemProxy fsProxy = fs.GetFileSystemProxyServiceObject(); Result rc = fsProxy.OpenBisStorage(out IStorage storage, partitionId); if (rc.IsFailure()) { return(rc); } partitionStorage = storage; return(Result.Success); }
public static Result MountBis(this FileSystemClient fs, U8Span mountName, BisPartitionId partitionId) { return(MountBis(fs, mountName, partitionId, default)); }
public Result SetBisRootForHost(BisPartitionId partitionId, string rootPath) { return(Config.SetPath(rootPath, partitionId)); }
public Result OpenBisFileSystem(out IFileSystem fileSystem, string rootPath, BisPartitionId partitionId) { return(FsCreators.BuiltInStorageFileSystemCreator.Create(out fileSystem, rootPath, partitionId)); }
public static Result MountBis(this FileSystemClient fs, BisPartitionId partitionId, U8Span rootPath) { return(MountBis(fs, GetBisMountName(partitionId), partitionId, rootPath)); }