public Result OpenBaseFileSystem(out ReferenceCountedDisposable <IFileSystemSf> fileSystem,
                                         BaseFileSystemId fileSystemId)
        {
            UnsafeHelpers.SkipParamInit(out fileSystem);

            Result rc = CheckCapabilityById(fileSystemId, _processId);

            if (rc.IsFailure())
            {
                return(rc);
            }

            ReferenceCountedDisposable <IFileSystem> fs = null;

            try
            {
                // Open the file system
                rc = _serviceImpl.OpenBaseFileSystem(out fs, fileSystemId);
                if (rc.IsFailure())
                {
                    return(rc);
                }

                // Create an SF adapter for the file system
                fileSystem = FileSystemInterfaceAdapter.CreateShared(ref fs);

                return(Result.Success);
            }
            finally
            {
                fs?.Dispose();
            }
        }
        public static ResultCode OpenNcaFs(ServiceCtx context, string ncaPath, LibHac.Fs.IStorage ncaStorage, out IFileSystem openedFileSystem)
        {
            openedFileSystem = null;

            try
            {
                Nca nca = new Nca(context.Device.System.KeySet, ncaStorage);

                if (!nca.SectionExists(NcaSectionType.Data))
                {
                    return(ResultCode.PartitionNotFound);
                }

                LibHac.Fs.Fsa.IFileSystem fileSystem = nca.OpenFileSystem(NcaSectionType.Data, context.Device.System.FsIntegrityCheckLevel);
                using var sharedFs = new SharedRef <LibHac.Fs.Fsa.IFileSystem>(fileSystem);

                using SharedRef <LibHac.FsSrv.Sf.IFileSystem> adapter = FileSystemInterfaceAdapter.CreateShared(ref sharedFs.Ref(), true);

                openedFileSystem = new IFileSystem(ref adapter.Ref());
            }
            catch (HorizonResultException ex)
            {
                return((ResultCode)ex.ResultValue.Value);
            }

            return(ResultCode.Success);
        }
Beispiel #3
0
        public static ResultCode OpenNsp(ServiceCtx context, string pfsPath, out IFileSystem openedFileSystem)
        {
            openedFileSystem = null;

            try
            {
                LocalStorage storage = new LocalStorage(pfsPath, FileAccess.Read, FileMode.Open);
                ReferenceCountedDisposable <LibHac.Fs.Fsa.IFileSystem> nsp = new(new PartitionFileSystem(storage));

                ImportTitleKeysFromNsp(nsp.Target, context.Device.System.KeySet);

                openedFileSystem = new IFileSystem(FileSystemInterfaceAdapter.CreateShared(ref nsp));
            }
            catch (HorizonResultException ex)
            {
                return((ResultCode)ex.ResultValue.Value);
            }

            return(ResultCode.Success);
        }
Beispiel #4
0
        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();
            }
        }