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);
        }
Example #5
0
        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());
        }
Example #6
0
        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);
        }
Example #10
0
        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);
        }
Example #11
0
        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);
        }