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); }
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); }
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); }
/// <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); }
// 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); }
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); }
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); }
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); }
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); }
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); }
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); }
internal bool IsEnabledFileSystemAccessorAccessLog(U8Span mountName) { if (MountTable.Find(mountName.ToString(), out FileSystemAccessor accessor).IsFailure()) { return(true); } return(accessor.IsAccessLogEnabled); }
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()); }
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); }
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()); }
internal void EnableFileSystemAccessorAccessLog(U8Span mountName) { if (MountTable.Find(mountName.ToString(), out FileSystemAccessor accessor).IsFailure()) { throw new LibHacException("abort"); } accessor.IsAccessLogEnabled = true; }
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()); }
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()); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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(); }
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(); }