private DfsDirectoryEntry FindDirectory(DfsDirectoryEntry baseDir, string name, uint flags) { if (baseDir.FilePointer == 0) { return(null); } DfsDirectoryEntry currentDir = new DfsDirectoryEntry(FindSector(baseDir.FilePointer)); do { // check flags and path if (((currentDir.Flags & DfsDirectoryEntry.FLAG_MASK) == flags) && (currentDir.Path.Equals(name))) { return(currentDir); } // no next enty? -> done if (currentDir.NextEntry == 0) { break; } currentDir = new DfsDirectoryEntry(FindSector(currentDir.NextEntry)); } while (true); // not found return(null); }
private void WalkDirectory(DfsDirectoryEntry dir, List <DfsSector> sectors) { do { var sector = FindSector(dir.Offset); sectors.Remove(sector); if (dir.FilePointer != 0) { sector = FindSector(dir.FilePointer); var entry = new DfsDirectoryEntry(sector); if ((entry.Flags & DfsDirectoryEntry.FLAG_DIR) != 0) { WalkDirectory(entry, sectors); } else //if ((entry.Flags & DfsDirectoryEntry.FLAG_FILE) != 0) { sectors.Remove(sector); WalkFile(entry, sectors); } } if (dir.NextEntry == 0) { break; } dir = new DfsDirectoryEntry(FindSector(dir.NextEntry)); } while (true); }
public DfsFileStream(DragonFs fs, DfsDirectoryEntry root, FileAccess access) { _Fs = fs; _Root = root; if (root.FilePointer != 0) { if ((access == FileAccess.Write) || (access == FileAccess.ReadWrite)) { throw new NotSupportedException("Writing an existing file is not supported"); } // Create MemoryStream from existing data _MemStream = new MemoryStream((int)(_Root.Flags & ~DfsDirectoryEntry.FLAG_MASK)); int remainingBytes = (int)Length; uint offset = root.FilePointer; while (remainingBytes > 0) { // Fetch a sector and write to the stream DfsSector sector = _Fs.FindSector(offset); int sectorBytes = (int)DfsSector.SECTOR_SIZE; if (sectorBytes >= remainingBytes) { sectorBytes = remainingBytes; } _MemStream.Write(sector.Buffer, 0, sectorBytes); remainingBytes -= sectorBytes; offset += DfsSector.SECTOR_SIZE; } _MemStream.Seek(0, SeekOrigin.Begin); } else { if (access == FileAccess.Read) { throw new NotSupportedException("Cannot read file without content"); } // Create MemoryStream for all file operations _MemStream = new MemoryStream(); } switch (access) { case FileAccess.Read: _CanRead = true; break; case FileAccess.ReadWrite: _CanRead = true; _CanWrite = true; break; case FileAccess.Write: _CanWrite = true; break; } }
void AppendDirectoryEntry(DfsDirectoryEntry directoryEntry, uint offset) { while (directoryEntry.NextEntry != 0) { directoryEntry = new DfsDirectoryEntry(FindSector(directoryEntry.NextEntry)); } directoryEntry.NextEntry = offset; }
private DfsDirectoryEntry CreateFileEntry(string path) { DfsDirectoryEntry currentDir; if (path[0] == '/') { currentDir = _RootDirectory; } else { currentDir = _CurrentDirectory; } string[] dirs = path.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < dirs.Length; i++) { string searchDir = dirs[i]; DfsDirectoryEntry foundDir; if (i == dirs.Length - 1) { foundDir = FindDirectory(currentDir, searchDir, DfsDirectoryEntry.FLAG_FILE); } else { foundDir = FindDirectory(currentDir, searchDir, DfsDirectoryEntry.FLAG_DIR); } if (foundDir == null) { // Create the new Directory and put it at the end foundDir = NewDirectoryEntry(); if (i == dirs.Length - 1) { foundDir.Flags = DfsDirectoryEntry.FLAG_FILE; } else { foundDir.Flags = DfsDirectoryEntry.FLAG_DIR; } foundDir.Path = searchDir; if (currentDir.FilePointer == 0) { currentDir.FilePointer = foundDir.Offset; } else { currentDir = new DfsDirectoryEntry(FindSector(currentDir.FilePointer)); AppendDirectoryEntry(currentDir, foundDir.Offset); } } currentDir = foundDir; } return(currentDir); }
private void WalkFile(DfsDirectoryEntry fileEntry, List <DfsSector> sectors) { int fileSize = (int)(fileEntry.Flags & ~DfsDirectoryEntry.FLAG_MASK); uint offset = 0; do { var sector = FindSector(fileEntry.FilePointer + offset); sectors.Remove(sector); offset += DfsSector.SECTOR_SIZE; } while (offset < fileSize); }
public DragonFs() { DfsDirectoryEntry fsRoot = new DfsDirectoryEntry(NewSector()) { Flags = ROOT_FLAGS, NextEntry = ROOT_NEXTENTRY, Path = ROOT_PATH }; // build a dummy root with a valid file pointer // the real first sectors file pointer is always 0 // but this one can be modified _RootDirectory = new DfsDirectoryEntry(new DfsSector(0)); _RootDirectory.Flags = DfsDirectoryEntry.FLAG_DIR; _CurrentDirectory = _RootDirectory; }
public DfsFileStream OpenFile(string path, FileAccess access) { DfsDirectoryEntry directoryEntry = FindDirectory(path, DfsDirectoryEntry.FLAG_FILE); if (directoryEntry == null) { if (access == FileAccess.Read) { throw new FileNotFoundException(); } else { directoryEntry = CreateFileEntry(path); } } return(new DfsFileStream(this, directoryEntry, access)); }
public static DragonFs CreateFromStream(Stream source) { DragonFs newFs = new DragonFs(); DfsSector sector = new DfsSector(0); source.Read(sector.Buffer, 0, (int)DfsSector.SECTOR_SIZE); DfsDirectoryEntry root = new DfsDirectoryEntry(sector); bool checkValid = true; if ((root.Flags != ROOT_FLAGS) || (root.NextEntry != ROOT_NEXTENTRY)) { checkValid = false; } else { // Check DFS version string if (!root.Path.Equals(DragonFs.ROOT_PATH)) { checkValid = false; } } if (checkValid == false) { throw new ArgumentException("source", "The stream does not contain a valid DFS 2.0 image"); } while (source.Position != source.Length) { sector = newFs.NewSector(); source.Read(sector.Buffer, 0, (int)DfsSector.SECTOR_SIZE); } // The virtual root directory entry needs to point to the first sector // TODO: Can this be done better? newFs._RootDirectory.FilePointer = DfsSector.SECTOR_SIZE; return(newFs); }
public void CreateDirectory(string path) { DfsDirectoryEntry currentDir; if (path[0] == '/') { currentDir = _RootDirectory; } else { currentDir = _CurrentDirectory; } string[] dirs = path.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries); foreach (string searchDir in dirs) { DfsDirectoryEntry foundDir = FindDirectory(currentDir, searchDir, DfsDirectoryEntry.FLAG_DIR); if (foundDir == null) { // Create the new Directory and put it at the end foundDir = NewDirectoryEntry(); foundDir.Flags = DfsDirectoryEntry.FLAG_DIR; foundDir.Path = searchDir; if (currentDir.FilePointer == 0) { currentDir.FilePointer = foundDir.Offset; } else { currentDir = new DfsDirectoryEntry(FindSector(currentDir.FilePointer)); AppendDirectoryEntry(currentDir, foundDir.Offset); } } currentDir = foundDir; } }