protected override Result DoDeleteFile(U8Span path) { FsPath normalizedPath; unsafe { _ = &normalizedPath; } // workaround for CS0165 Result rc = PathTool.Normalize(normalizedPath.Str, out _, path, false, false); if (rc.IsFailure()) { return(rc); } if (!FileTable.TryOpenFile(normalizedPath, out SaveFileInfo fileInfo)) { return(ResultFs.PathNotFound.Log()); } if (fileInfo.StartBlock != int.MinValue) { AllocationTable.Free(fileInfo.StartBlock); } FileTable.DeleteFile(normalizedPath); return(Result.Success); }
public void FsTrim() { AllocationTable.FsTrim(); foreach (DirectoryEntryEx file in this.EnumerateEntries("*", SearchOptions.RecurseSubdirectories)) { if (FileTable.TryOpenFile(file.FullPath.ToU8Span(), out SaveFileInfo fileInfo) && fileInfo.StartBlock >= 0) { AllocationTable.FsTrimList(fileInfo.StartBlock); OpenFatStorage(fileInfo.StartBlock).Slice(fileInfo.Length).Fill(SaveDataFileSystem.TrimFillValue); } } int freeIndex = AllocationTable.GetFreeListBlockIndex(); if (freeIndex == 0) { return; } AllocationTable.FsTrimList(freeIndex); OpenFatStorage(freeIndex).Fill(SaveDataFileSystem.TrimFillValue); FileTable.TrimFreeEntries(); }
protected override Result CreateFileImpl(string path, long size, CreateFileOptions options) { path = PathTools.Normalize(path); if (size == 0) { var emptyFileEntry = new SaveFileInfo { StartBlock = int.MinValue, Length = size }; FileTable.AddFile(path, ref emptyFileEntry); return(Result.Success); } int blockCount = (int)Util.DivideByRoundUp(size, AllocationTable.Header.BlockSize); int startBlock = AllocationTable.Allocate(blockCount); if (startBlock == -1) { return(ResultFs.AllocationTableInsufficientFreeBlocks.Log()); } var fileEntry = new SaveFileInfo { StartBlock = startBlock, Length = size }; FileTable.AddFile(path, ref fileEntry); return(Result.Success); }
protected override Result DoGetFreeSpaceSize(out long freeSpace, U8Span path) { int freeBlockCount = AllocationTable.GetFreeListLength(); freeSpace = Header.BlockSize * freeBlockCount; return(Result.Success); }
public static IEnumerable <(int block, int length)> DumpChain(this AllocationTable table, int startBlock) { var iterator = new AllocationTableIterator(table, startBlock); do { yield return(iterator.PhysicalBlock, iterator.CurrentSegmentSize); } while (iterator.MoveNext()); }
public AllocationTableStorage(IStorage data, AllocationTable table, int blockSize, int initialBlock) { BaseStorage = data; BlockSize = blockSize; Fat = table; InitialBlock = initialBlock; _length = initialBlock == -1 ? 0 : table.GetListLength(initialBlock) * blockSize; }
public AllocationTableIterator(AllocationTable table, int initialBlock) { Fat = table; if (!BeginIteration(initialBlock)) { throw new ArgumentException($"Attempted to start FAT iteration from an invalid block. ({initialBlock})"); } }
public SaveDataFileSystemCore(IStorage storage, IStorage allocationTable, IStorage header) { HeaderStorage = header; BaseStorage = storage; AllocationTable = new AllocationTable(allocationTable, header.Slice(0x18, 0x30)); Header = new SaveHeader(HeaderStorage); AllocationTableStorage dirTableStorage = OpenFatStorage(AllocationTable.Header.DirectoryTableBlock); AllocationTableStorage fileTableStorage = OpenFatStorage(AllocationTable.Header.FileTableBlock); FileTable = new HierarchicalSaveFileTable(dirTableStorage, fileTableStorage); }
protected override Result DeleteFileImpl(string path) { path = PathTools.Normalize(path); if (!FileTable.TryOpenFile(path, out SaveFileInfo fileInfo)) { return(ResultFs.PathNotFound.Log()); } if (fileInfo.StartBlock != int.MinValue) { AllocationTable.Free(fileInfo.StartBlock); } FileTable.DeleteFile(path); return(Result.Success); }
protected override Result DoCreateFile(U8Span path, long size, CreateFileOptions options) { FsPath normalizedPath; unsafe { _ = &normalizedPath; } // workaround for CS0165 Result rc = PathTool.Normalize(normalizedPath.Str, out _, path, false, false); if (rc.IsFailure()) { return(rc); } if (size == 0) { var emptyFileEntry = new SaveFileInfo { StartBlock = int.MinValue, Length = size }; FileTable.AddFile(normalizedPath, ref emptyFileEntry); return(Result.Success); } int blockCount = (int)Utilities.DivideByRoundUp(size, AllocationTable.Header.BlockSize); int startBlock = AllocationTable.Allocate(blockCount); if (startBlock == -1) { return(ResultFs.AllocationTableInsufficientFreeBlocks.Log()); } var fileEntry = new SaveFileInfo { StartBlock = startBlock, Length = size }; FileTable.AddFile(normalizedPath, ref fileEntry); return(Result.Success); }
protected override Result DoCreateFile(U8Span path, long size, CreateFileOptions options) { Unsafe.SkipInit(out FsPath normalizedPath); Result rc = PathNormalizer.Normalize(normalizedPath.Str, out _, path, false, false); if (rc.IsFailure()) { return(rc); } if (size == 0) { var emptyFileEntry = new SaveFileInfo { StartBlock = int.MinValue, Length = size }; FileTable.AddFile(normalizedPath, ref emptyFileEntry); return(Result.Success); } int blockCount = (int)BitUtil.DivideUp(size, AllocationTable.Header.BlockSize); int startBlock = AllocationTable.Allocate(blockCount); if (startBlock == -1) { return(ResultFs.AllocationTableFull.Log()); } var fileEntry = new SaveFileInfo { StartBlock = startBlock, Length = size }; FileTable.AddFile(normalizedPath, ref fileEntry); return(Result.Success); }