コード例 #1
0
        protected override Result DoRenameDirectory(U8Span oldPath, U8Span newPath)
        {
            // todo: Return proper result codes

            // Official code procedure:
            // Make sure all file headers can be decrypted
            // Rename directory to the new path
            // Reencrypt file headers with new path
            // If no errors, return
            // Reencrypt any modified file headers with the old path
            // Rename directory to the old path

            Result rc = BaseFileSystem.RenameDirectory(oldPath, newPath);

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

            try
            {
                RenameDirectoryImpl(oldPath.ToString(), newPath.ToString(), false);
            }
            catch (Exception)
            {
                RenameDirectoryImpl(oldPath.ToString(), newPath.ToString(), true);
                BaseFileSystem.RenameDirectory(oldPath, newPath);

                throw;
            }

            return(Result.Success);
        }
コード例 #2
0
        protected override Result DoRenameFile(U8Span oldPath, U8Span newPath)
        {
            // todo: Return proper result codes

            AesXtsFileHeader header = ReadXtsHeader(oldPath.ToString(), oldPath.ToString());

            Result rc = BaseFileSystem.RenameFile(oldPath, newPath);

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

            try
            {
                WriteXtsHeader(header, newPath.ToString(), newPath.ToString());
            }
            catch (Exception)
            {
                BaseFileSystem.RenameFile(newPath, oldPath);
                WriteXtsHeader(header, oldPath.ToString(), oldPath.ToString());

                throw;
            }

            return(Result.Success);
        }
コード例 #3
0
ファイル: PartitionFileSystem.cs プロジェクト: garoxas/LibHac
        protected override Result DoOpenFile(out IFile file, U8Span path, OpenMode mode)
        {
            path = PathTools.Normalize(path.ToString()).TrimStart('/').ToU8Span();

            if (!FileDict.TryGetValue(path.ToString(), out PartitionFileEntry entry))
            {
                ThrowHelper.ThrowResult(ResultFs.PathNotFound.Value);
            }

            file = OpenFile(entry, mode);
            return(Result.Success);
        }
コード例 #4
0
        /// <summary>
        /// Creates a new <see cref="AesXtsFile"/> using the provided key.
        /// </summary>
        /// <param name="path">The full path of the file to create.</param>
        /// <param name="size">The initial size of the created file.</param>
        /// <param name="options">Flags to control how the file is created.
        /// Should usually be <see cref="CreateFileOptions.None"/></param>
        /// <param name="key">The 256-bit key containing a 128-bit data key followed by a 128-bit tweak key.</param>
        public Result CreateFile(U8Span path, long size, CreateFileOptions options, byte[] key)
        {
            long containerSize = AesXtsFile.HeaderLength + Utilities.AlignUp(size, 0x10);

            Result rc = BaseFileSystem.CreateFile(path, containerSize, options);

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

            var header = new AesXtsFileHeader(key, size, path.ToString(), KekSource, ValidationKey);

            rc = BaseFileSystem.OpenFile(out IFile baseFile, path, OpenMode.Write);
            if (rc.IsFailure())
            {
                return(rc);
            }

            using (baseFile)
            {
                rc = baseFile.Write(0, header.ToBytes(false));
                if (rc.IsFailure())
                {
                    return(rc);
                }
            }

            return(Result.Success);
        }
コード例 #5
0
        // 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);
        }
コード例 #6
0
        public Result OpenDirectory(out DirectoryHandle handle, U8Span path, OpenDirectoryMode mode)
        {
            handle = default;

            Result rc = FindFileSystem(out FileSystemAccessor fileSystem, out U8Span subPath, path);

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

            if (IsEnabledAccessLog() && fileSystem.IsAccessLogEnabled)
            {
                TimeSpan startTime = Time.GetCurrent();
                rc     = fileSystem.OpenDirectory(out DirectoryAccessor dir, subPath, mode);
                handle = new DirectoryHandle(dir);
                TimeSpan endTime = Time.GetCurrent();

                OutputAccessLog(rc, startTime, endTime, handle, $", path: \"{path.ToString()}\", open_mode: {mode}");
            }
            else
            {
                rc     = fileSystem.OpenDirectory(out DirectoryAccessor dir, subPath, mode);
                handle = new DirectoryHandle(dir);
            }

            return(rc);
        }
コード例 #7
0
        public Result GetEntryType(out DirectoryEntryType type, U8Span path)
        {
            type = default;

            Result rc = FindFileSystem(out FileSystemAccessor fileSystem, out U8Span subPath, path);

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

            if (IsEnabledAccessLog() && fileSystem.IsAccessLogEnabled)
            {
                TimeSpan startTime = Time.GetCurrent();
                rc = fileSystem.GetEntryType(out type, subPath);
                TimeSpan endTime = Time.GetCurrent();

                OutputAccessLog(rc, startTime, endTime, $", path: \"{path.ToString()}\"");
            }
            else
            {
                rc = fileSystem.GetEntryType(out type, subPath);
            }

            return(rc);
        }
コード例 #8
0
        public Result RenameFile(U8Span oldPath, U8Span newPath)
        {
            Result rc = FindFileSystem(out FileSystemAccessor oldFileSystem, out U8Span oldSubPath, oldPath);

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

            rc = FindFileSystem(out FileSystemAccessor newFileSystem, out U8Span newSubPath, newPath);
            if (rc.IsFailure())
            {
                return(rc);
            }

            if (oldFileSystem != newFileSystem)
            {
                return(ResultFs.DifferentDestFileSystem.Log());
            }

            if (IsEnabledAccessLog() && oldFileSystem.IsAccessLogEnabled)
            {
                TimeSpan startTime = Time.GetCurrent();
                rc = oldFileSystem.RenameFile(oldSubPath, newSubPath);
                TimeSpan endTime = Time.GetCurrent();

                OutputAccessLog(rc, startTime, endTime, $", path: \"{oldPath.ToString()}\", new_path: \"{newPath.ToString()}\"");
            }
            else
            {
                rc = oldFileSystem.RenameFile(oldSubPath, newSubPath);
            }

            return(rc);
        }
コード例 #9
0
ファイル: Code.cs プロジェクト: ckurtz22/LibHac
        public static Result MountCode(this FileSystemClient fs, out CodeVerificationData verificationData,
                                       U8Span mountName, U8Span path, ProgramId programId)
        {
            Result rc;

            if (fs.IsEnabledAccessLog(AccessLogTarget.System))
            {
                TimeSpan startTime = fs.Time.GetCurrent();
                rc = MountCodeImpl(fs, out verificationData, mountName, path, programId);
                TimeSpan endTime = fs.Time.GetCurrent();

                fs.OutputAccessLog(rc, startTime, endTime,
                                   $", name: \"{mountName.ToString()}\", name: \"{path.ToString()}\", programid: 0x{programId}");
            }
            else
            {
                rc = MountCodeImpl(fs, out verificationData, mountName, path, programId);
            }

            if (rc.IsSuccess() && fs.IsEnabledAccessLog(AccessLogTarget.System))
            {
                fs.EnableFileSystemAccessorAccessLog(mountName);
            }

            return(rc);
        }
コード例 #10
0
ファイル: BcatSaveData.cs プロジェクト: leo60228/LibHac
        public static Result MountBcatSaveData(this FileSystemClient fs, U8Span mountName, TitleId applicationId)
        {
            Result rc;

            if (fs.IsEnabledAccessLog(AccessLogTarget.System))
            {
                TimeSpan startTime = fs.Time.GetCurrent();
                rc = MountBcatSaveDataImpl(fs, mountName, applicationId);
                TimeSpan endTime = fs.Time.GetCurrent();

                string logMessage = $", name: \"{mountName.ToString()}\", applicationid: 0x{applicationId}\"";

                fs.OutputAccessLog(rc, startTime, endTime, logMessage);
            }
            else
            {
                rc = MountBcatSaveDataImpl(fs, mountName, applicationId);
            }

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

            if (fs.IsEnabledAccessLog(AccessLogTarget.System))
            {
                fs.EnableFileSystemAccessorAccessLog(mountName);
            }

            return(Result.Success);
        }
コード例 #11
0
        private static Result CopyDirectoryWithProgressInternal(FileSystemClient fs, U8Span sourcePath, U8Span destPath,
                                                                CreateFileOptions options, IProgressReport logger)
        {
            string sourcePathStr = sourcePath.ToString();
            string destPathStr   = destPath.ToString();

            Result rc = fs.OpenDirectory(out DirectoryHandle sourceHandle, sourcePath, OpenDirectoryMode.All);

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

            try
            {
                foreach (DirectoryEntryEx entry in fs.EnumerateEntries(sourcePathStr, "*", SearchOptions.Default))
                {
                    string subSrcPath = PathTools.Normalize(PathTools.Combine(sourcePathStr, entry.Name));
                    string subDstPath = PathTools.Normalize(PathTools.Combine(destPathStr, entry.Name));

                    if (entry.Type == DirectoryEntryType.Directory)
                    {
                        fs.EnsureDirectoryExists(subDstPath);

                        rc = CopyDirectoryWithProgressInternal(fs, subSrcPath.ToU8Span(), subDstPath.ToU8Span(), options, logger);
                        if (rc.IsFailure())
                        {
                            return(rc);
                        }
                    }

                    if (entry.Type == DirectoryEntryType.File)
                    {
                        logger?.LogMessage(subSrcPath);

                        rc = fs.CreateOrOverwriteFile(subDstPath, entry.Size, options);
                        if (rc.IsFailure())
                        {
                            return(rc);
                        }

                        rc = CopyFileWithProgress(fs, subSrcPath.ToU8Span(), subDstPath.ToU8Span(), logger);
                        if (rc.IsFailure())
                        {
                            return(rc);
                        }
                    }
                }
            }
            finally
            {
                if (sourceHandle.IsValid)
                {
                    fs.CloseDirectory(sourceHandle);
                }
            }

            return(Result.Success);
        }
コード例 #12
0
        internal bool IsEnabledFileSystemAccessorAccessLog(U8Span mountName)
        {
            if (MountTable.Find(mountName.ToString(), out FileSystemAccessor accessor).IsFailure())
            {
                return(true);
            }

            return(accessor.IsAccessLogEnabled);
        }
コード例 #13
0
        protected override Result GetEntryTypeImpl(out DirectoryEntryType entryType, U8Span path)
        {
            entryType = default;

            if (path.ToString() == "/")
            {
                entryType = DirectoryEntryType.Directory;
                return(Result.Success);
            }

            if (FileDict.ContainsKey(path.ToString().TrimStart('/')))
            {
                entryType = DirectoryEntryType.File;
                return(Result.Success);
            }

            return(ResultFs.PathNotFound.Log());
        }
コード例 #14
0
        public Result SetFileAttributes(U8Span spanpath, NxFileAttributes attributes)
        {
            string path = PathTools.Normalize(spanpath.ToString());
            Tuple <string, IAttributeFileSystem> t = FileDict[path];

            t.Item2.SetFileAttributes(t.Item1.ToU8Span(), attributes);

            return(Result.Success);
        }
コード例 #15
0
        protected override Result GetEntryTypeImpl(out DirectoryEntryType entryType, U8Span path)
        {
            entryType = default;

            if (FileTable.TryOpenFile(path.ToString(), out RomFileInfo _))
            {
                entryType = DirectoryEntryType.File;
                return(Result.Success);
            }

            if (FileTable.TryOpenDirectory(path.ToString(), out FindPosition _))
            {
                entryType = DirectoryEntryType.Directory;
                return(Result.Success);
            }

            return(ResultFs.PathNotFound.Log());
        }
コード例 #16
0
        internal void EnableFileSystemAccessorAccessLog(U8Span mountName)
        {
            if (MountTable.Find(mountName.ToString(), out FileSystemAccessor accessor).IsFailure())
            {
                throw new LibHacException("abort");
            }

            accessor.IsAccessLogEnabled = true;
        }
コード例 #17
0
ファイル: PartitionFileSystem.cs プロジェクト: garoxas/LibHac
        protected override Result DoGetEntryType(out DirectoryEntryType entryType, U8Span path)
        {
            UnsafeHelpers.SkipParamInit(out entryType);

            if (path.ToString() == "/")
            {
                entryType = DirectoryEntryType.Directory;
                return(Result.Success);
            }

            if (FileDict.ContainsKey(path.ToString().TrimStart('/')))
            {
                entryType = DirectoryEntryType.File;
                return(Result.Success);
            }

            return(ResultFs.PathNotFound.Log());
        }
コード例 #18
0
        protected override Result DoGetEntryType(out DirectoryEntryType entryType, U8Span path)
        {
            UnsafeHelpers.SkipParamInit(out entryType);

            if (FileTable.TryOpenFile(path.ToString(), out RomFileInfo _))
            {
                entryType = DirectoryEntryType.File;
                return(Result.Success);
            }

            if (FileTable.TryOpenDirectory(path.ToString(), out FindPosition _))
            {
                entryType = DirectoryEntryType.Directory;
                return(Result.Success);
            }

            return(ResultFs.PathNotFound.Log());
        }
コード例 #19
0
ファイル: FsUtils.cs プロジェクト: leo60228/LibHac
        public static long GetTotalSize(FileSystemClient fs, U8Span path, string searchPattern = "*")
        {
            long size = 0;

            foreach (DirectoryEntryEx entry in fs.EnumerateEntries(path.ToString(), searchPattern))
            {
                size += entry.Size;
            }

            return(size);
        }
コード例 #20
0
        protected override Result DoOpenDirectory(out IDirectory directory, U8Span path, OpenDirectoryMode mode)
        {
            UnsafeHelpers.SkipParamInit(out directory);

            if (!FileTable.TryOpenDirectory(path.ToString(), out FindPosition position))
            {
                return(ResultFs.PathNotFound.Log());
            }

            directory = new RomFsDirectory(this, position, mode);
            return(Result.Success);
        }
コード例 #21
0
        protected override Result OpenDirectoryImpl(out IDirectory directory, U8Span path, OpenDirectoryMode mode)
        {
            directory = default;

            if (!FileTable.TryOpenDirectory(path.ToString(), out FindPosition position))
            {
                return(ResultFs.PathNotFound.Log());
            }

            directory = new RomFsDirectory(this, position, mode);
            return(Result.Success);
        }
コード例 #22
0
        public static Result Normalize(out U8Span normalizedPath, U8Span path)
        {
            if (path.Length == 0)
            {
                normalizedPath = path;
                return(Result.Success);
            }

            // Todo: optimize
            normalizedPath = new U8Span(Normalize(path.ToString()));

            return(Result.Success);
        }
コード例 #23
0
        public Result Register(U8Span mountName, IFileSystem fileSystem, ICommonMountNameGenerator nameGenerator)
        {
            var accessor = new FileSystemAccessor(mountName.ToString(), fileSystem, this, nameGenerator);

            Result rc = MountTable.Mount(accessor);

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

            accessor.IsAccessLogEnabled = IsEnabledAccessLog();
            return(Result.Success);
        }
コード例 #24
0
        public Result Commit(U8Span mountName)
        {
            Result rc = MountTable.Find(mountName.ToString(), out FileSystemAccessor fileSystem);

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

            if (IsEnabledAccessLog() && fileSystem.IsAccessLogEnabled)
            {
                TimeSpan startTime = Time.GetCurrent();
                rc = fileSystem.Commit();
                TimeSpan endTime = Time.GetCurrent();

                OutputAccessLog(rc, startTime, endTime, $", name: \"{mountName.ToString()}\"");
            }
            else
            {
                rc = fileSystem.Commit();
            }

            return(rc);
        }
コード例 #25
0
        protected override Result OpenDirectoryImpl(out IDirectory directory, U8Span spanpath, OpenDirectoryMode mode)
        {
            string path = PathTools.Normalize(spanpath.ToString());

            if (path == "/")
            {
                directory = new PseudoRootDirectory(this);
            }
            else
            {
                throw new NotImplementedException();
            }

            return(Result.Success);
        }
コード例 #26
0
        public Result GetFileSize(out long size, U8Span spanpath)
        {
            string path = PathTools.Normalize(spanpath.ToString());

            if (FileDict.ContainsKey(path))
            {
                Tuple <string, IAttributeFileSystem> t = FileDict[path];
                return(t.Item2.GetFileSize(out size, t.Item1.ToU8Span()));
            }
            if (StorageDict.ContainsKey(path))
            {
                return(StorageDict[path].GetSize(out size));
            }
            size = 0;
            return(ResultFs.PathNotFound.Value);
        }
コード例 #27
0
        protected override Result DoOpenFile(out IFile file, U8Span path, OpenMode mode)
        {
            UnsafeHelpers.SkipParamInit(out file);

            if (!FileTable.TryOpenFile(path.ToString(), out RomFileInfo info))
            {
                return(ResultFs.PathNotFound.Log());
            }

            if (mode != OpenMode.Read)
            {
                // RomFs files must be opened read-only.
                return(ResultFs.InvalidArgument.Log());
            }

            file = new RomFsFile(BaseStorage, Header.DataOffset + info.Offset, info.Length);
            return(Result.Success);
        }
コード例 #28
0
        protected override Result OpenFileImpl(out IFile file, U8Span spanpath, OpenMode mode)
        {
            string path = PathTools.Normalize(spanpath.ToString());

            if (FileDict.ContainsKey(path))
            {
                Tuple <string, IAttributeFileSystem> t = FileDict[path];
                return(t.Item2.OpenFile(out file, t.Item1.ToU8Span(), mode));
            }
            if (StorageDict.ContainsKey(path))
            {
                file = StorageDict[path].AsFile(mode);
                return(Result.Success);
            }

            file = null;
            return(ResultFs.PathNotFound.Value);
        }
コード例 #29
0
        public void Unmount(U8Span mountName)
        {
            Result rc;
            string mountNameStr = mountName.ToString();

            if (IsEnabledAccessLog() && IsEnabledFileSystemAccessorAccessLog(mountName))
            {
                TimeSpan startTime = Time.GetCurrent();

                rc = MountTable.Unmount(mountNameStr);

                TimeSpan endTime = Time.GetCurrent();
                OutputAccessLog(rc, startTime, endTime, $", name: \"{mountNameStr}\"");
            }
            else
            {
                rc = MountTable.Unmount(mountNameStr);
            }

            rc.ThrowIfFailure();
        }
コード例 #30
0
ファイル: MountTable.cs プロジェクト: cualquiercosa327/LibHac
        public void Unmount(U8Span name)
        {
            using ScopedLock <SdkMutexType> lk = ScopedLock.Lock(ref _mutex);

            LinkedListNode <FileSystemAccessor> currentNode;

            for (currentNode = _fileSystemList.First; currentNode is not null; currentNode = currentNode.Next)
            {
                if (Matches(currentNode.Value, name))
                {
                    break;
                }
            }

            if (currentNode is null)
            {
                Abort.DoAbort(ResultFs.NotMounted.Log(), $"{name.ToString()} is not mounted.");
            }

            _fileSystemList.Remove(currentNode);
            currentNode.Value.Dispose();
        }