/// <summary> /// Create a file entry for a given content /// </summary> /// <param name="filePath">The full file path of the file (eg : /FOO/BAR/FILE.EXT)</param> /// <param name="lba">The LBA of the file's content</param> /// <param name="size">The size of the file's content</param> public void CreateFileEntry(string filePath, uint lba, uint size) { if (_index.GetEntry(filePath) != null) { throw new FrameworkException("Error while creating file \"{0}\" : entry already exists", filePath); } var parent = _index.FindAParent(filePath); if (parent == null) { throw new FrameworkException("Error while creating file \"{0}\" : parent directory does not exists", filePath); } var entry = new DirectoryEntry(_isXa); entry.Name = _regFileName.Match(filePath).Groups[1].Value + (_appendVersionToFileName ? ";1" : ""); entry.Length += (byte)(entry.Name.Length - 1); entry.Length += (byte)(entry.Name.Length % 2 == 0 ? 1 : 0); entry.ExtentSize = size; entry.ExtentLba = lba; if (_isXa) { entry.XaEntry.IsForm1 = true; } var indexEntry = new DataTrackIndexEntry(parent, entry); _index.AddToIndex(indexEntry); }
// Constructors internal DataTrackIndex(DirectoryEntry root) { _root = new DataTrackIndexEntry(null, root); _entries = new List <DataTrackIndexEntry>(); _mappedEntries = new Dictionary <string, DataTrackIndexEntry>(); _entriesCount = 0; _directoryEntriesCount = 0; _fileEntriesCount = 0; }
/// <summary> /// Write out the directory entry /// </summary> private void WriteDirectoryEntry(DataTrackIndexEntry entry) { SeekSector(entry.Lba); int size = (int)entry.Size; int sectorSize = GetSectorDataSize(_defaultSectorMode); byte[] data = new byte[size]; using (var stream = new CBinaryWriter(data)) { // First directory entry of a directory entry is the directory itself stream.Write(GetDirectoryEntryBuffer(entry.DirectoryEntry, true, false)); // Second directory entry is the parent directory entry. if (entry.ParentEntry != null) { stream.Write(GetDirectoryEntryBuffer(entry.ParentEntry.DirectoryEntry, false, true)); } else { stream.Write(GetDirectoryEntryBuffer(entry.DirectoryEntry, false, true)); } foreach (var subEntry in entry.SubEntries) { // DirectoryEntry cannot be "splitted" on two sectors if ((stream.Position - (stream.Position / sectorSize) * sectorSize) + subEntry.Length >= sectorSize) { stream.Position = ((stream.Position / sectorSize) + 1) * sectorSize; } if (stream.Position + subEntry.DirectoryEntry.Length < size) { stream.Write(GetDirectoryEntryBuffer(subEntry.DirectoryEntry)); } else { throw new FrameworkException("Error while finalizing disk : directory \"{0}\" is too small", entry.FullPath); } } } for (int i = 0; i < size; i += sectorSize) { WriteSector ( CBuffer.Create(data, i, sectorSize), _defaultSectorMode, (i + sectorSize >= size) ? XaSubHeader.EndOfFile : XaSubHeader.Basic ); } }
/// <summary> /// Fetch a directory to build the internal index (recursive) /// </summary> private void AddDirectoryToIndex(DataTrackIndexEntry indexDirectoryEntry) { DirectoryEntry entry; DataTrackIndexEntry indexEntry; long lba = indexDirectoryEntry.DirectoryEntry.ExtentLba; long size = indexDirectoryEntry.DirectoryEntry.ExtentSize; int sectorsCount = (int)(size / GetSectorDataSize(_defaultSectorMode)); var stream = new CBinaryReader(ReadSectors(lba, sectorsCount, _defaultSectorMode)); // First directory entry of a directory entry is the directory itself, so let's skip it ReadDirectoryEntry(stream); // Second directory entry is the parent directory entry. // As we parse the data from root to children, it has already been handled, so let's skip it too ReadDirectoryEntry(stream); while (stream.Position < size) { short b = stream.TestByte(); if (b == 0) { // DirectoryEntry cannot be "splitted" on two sectors int dataSize = GetSectorDataSize(_defaultSectorMode); stream.Position = (((stream.Position / dataSize) + 1) * dataSize); b = stream.TestByte(); } if (b <= 0) { break; } else { entry = ReadDirectoryEntry(stream); indexEntry = new DataTrackIndexEntry(indexDirectoryEntry, entry); _index.AddToIndex(indexEntry); if (indexEntry.IsDirectory) { AddDirectoryToIndex(indexEntry); } } } stream.CloseAndDispose(); }
// Methods /// <summary> /// Add sub entry to this entry (add file / folder to folder) /// </summary> /// <param name="subEntry">The entry to add</param> private void Add(DataTrackIndexEntry subEntry) { if (!IsDirectory) { throw new FrameworkException("Error while adding entry to directory : entry \"{0}\" is not a directory", _fullPath); } if (subEntry.DirectoryEntry.Length > _directoryAvailableSpace) { throw new FrameworkException("Error while adding entry to directory : directory \"{0}\" is too small", _fullPath); } _subEntries.Add(subEntry); _directoryAvailableSpace -= subEntry.DirectoryEntry.Length; }
// Constructors /// <summary> /// TreeEntry /// </summary> /// <param name="directoryEntry">The directory entry that this tree entry refers to</param> internal DataTrackIndexEntry(DataTrackIndexEntry parent, DirectoryEntry directoryEntry) { _parentEntry = parent; _isRoot = (parent == null); _directoryEntry = directoryEntry; if (!_isRoot) { _fullPath = parent.FullPath + (parent.FullPath != "/" ? "/" : "") + directoryEntry.Name; } else { _fullPath = "/"; } if (IsDirectory) { _subEntries = new List <DataTrackIndexEntry>(); if (!_isRoot) { _directoryAvailableSpace = directoryEntry.ExtentSize - parent.DirectoryEntry.Length - parent.DirectoryEntry.ExtendedAttributeRecordlength - directoryEntry.Length; } else { _directoryAvailableSpace = directoryEntry.ExtentSize - directoryEntry.Length - directoryEntry.ExtendedAttributeRecordlength - directoryEntry.Length; } } if (parent != null) { parent.Add(this); } }
// Methods /// <summary> /// Add entry to index /// </summary> /// <param name="entry"></param> internal void AddToIndex(DataTrackIndexEntry entry) { if (_mappedEntries.ContainsKey(entry.FullPath)) { throw new FrameworkException("Error while adding entry to index : entry \"{0}\" already exists", entry.FullPath); } _entriesCount++; if (entry.IsDirectory) { _directoryEntriesCount++; } else { _fileEntriesCount++; } _entries.Add(entry); _mappedEntries.Add(entry.FullPath, entry); }
/// <summary> /// Copy a stream (XA sound, str video, etc) /// </summary> /// <param name="filePath">The full file path of the file to write (eg : /FOO/BAR/FILE.EXT)</param> /// <param name="diskIn">The disk to copy stream's sectors from</param> /// <param name="entry">The entry of the reading disk</param> public void CopyStream(string filePath, DataTrackReader diskIn, DataTrackIndexEntry inEntry) { if (_index.GetEntry(filePath) != null) { throw new FrameworkException("Error while creating file \"{0}\" : entry already exists", filePath); } var parent = _index.FindAParent(filePath); if (parent == null) { throw new FrameworkException("Error while creating file \"{0}\" : parent directory does not exists", filePath); } var entry = new DirectoryEntry(_isXa); entry.Name = _regFileName.Match(filePath).Groups[1].Value + (_appendVersionToFileName ? ";1" : ""); entry.Length += (byte)(entry.Name.Length - 1); entry.Length += (byte)(entry.Name.Length % 2 == 0 ? 1 : 0); entry.ExtentSize = (uint)inEntry.Size; entry.ExtentLba = (uint)SectorCount; var indexEntry = new DataTrackIndexEntry(parent, entry); _index.AddToIndex(indexEntry); CopySectors ( diskIn, _defaultSectorMode == SectorMode.XA_FORM1 ? SectorMode.XA_FORM2 : _defaultSectorMode, entry.ExtentLba, inEntry.Lba, (int)(inEntry.Size / GetSectorDataSize(diskIn.DefautSectorMode)) ); }
/// <summary> /// Create a directory /// </summary> /// <param name="path">Full path of the directory to create</param> /// <param name="size">Size of the directory in sectors (default 1)</param> public void CreateDirectory(string path, int size = 1) { if (_index.GetEntry(path) != null) { throw new FrameworkException("Error while creating directory \"{0}\" : entry already exists", path); } var parent = _index.FindAParent(path); if (parent == null) { throw new FrameworkException("Error while creating directory \"{0}\" : parent directory does not exists", path); } var entry = new DirectoryEntry(_isXa); entry.IsDirectory = true; entry.Name = _regDirectoryName.Match(path).Groups[1].Value; entry.Length += (byte)(entry.Name.Length - 1); entry.Length += (byte)(entry.Name.Length % 2 == 0 ? 1 : 0); entry.ExtentSize = (uint)(size * GetSectorDataSize(_defaultSectorMode)); entry.ExtentLba = (uint)SectorCount; if (_isXa) { entry.XaEntry.IsDirectory = true; entry.XaEntry.IsForm1 = true; } var indexEntry = new DataTrackIndexEntry(parent, entry); _index.AddToIndex(indexEntry); SeekSector(SectorCount); WriteEmptySectors(size); }