public Result OpenBisStorage(out ReferenceCountedDisposable <IStorageSf> storage, BisPartitionId id) { UnsafeHelpers.SkipParamInit(out storage); var storageFlag = StorageType.Bis; using var scopedLayoutType = new ScopedStorageLayoutTypeSetter(storageFlag); Result rc = GetProgramInfo(out ProgramInfo programInfo); if (rc.IsFailure()) { return(rc); } rc = GetAccessibilityForOpenBisPartition(out Accessibility accessibility, programInfo, id); if (rc.IsFailure()) { return(rc); } bool canAccess = accessibility.CanRead && accessibility.CanWrite; if (!canAccess) { return(ResultFs.PermissionDenied.Log()); } ReferenceCountedDisposable <IStorage> tempStorage = null; try { rc = _serviceImpl.OpenBisStorage(out tempStorage, id); if (rc.IsFailure()) { return(rc); } tempStorage = StorageLayoutTypeSetStorage.CreateShared(ref tempStorage, storageFlag); // Todo: Async storage storage = StorageInterfaceAdapter.CreateShared(ref tempStorage); return(Result.Success); } finally { tempStorage?.Dispose(); } }
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(); } }