private void ReadEntry(UInt32 currentBlock, UInt32 offset, String currentPath) { m_br.BaseStream.Seek((currentBlock * m_rootHeader.blockSize) + offset, SeekOrigin.Begin); // Check creation of directory. if (Directory.Exists(currentPath) == false) { Directory.CreateDirectory(currentPath); } int entrycount = 0; bool lastEntry = false; while (lastEntry == false) { // Entry. //Console.Write(Environment.NewLine); //Console.WriteLine("Entry: "); EntryHeader eh = new EntryHeader(); // Flags. eh.flags = Util.ArrayToUint32(m_br.ReadBytes(sizeof(UInt32))); // Convert flags. EntryFlags entryFlags = EntryFlags.None; if ((eh.flags & 0x80000000) == 0x80000000) { entryFlags |= EntryFlags.LastEntryInDir; } if ((eh.flags & 0x40000000) == 0x40000000) { entryFlags |= EntryFlags.LastEntryInBlock; } if ((eh.flags & 0x07) == 0x07) { entryFlags |= EntryFlags.Directory; } else if ((eh.flags & 0x06) == 0x06) { entryFlags |= EntryFlags.SpecialFile; } else if ((eh.flags & 0x02) == 0x02) { entryFlags |= EntryFlags.File; } if (entryFlags.HasFlag(EntryFlags.LastEntryInDir) == true) { lastEntry = true; } // Identifier. eh.id = Util.ArrayToUint32(m_br.ReadBytes(sizeof(UInt32))); // Type. eh.type = m_br.ReadBytes(m_entryTypeSize); //Console.Write("Type: "); //for (int i = 0; i < m_entryTypeSize; i++) // Console.Write((Char)eh.type[i]); //Console.Write(Environment.NewLine); // Block size. eh.blockSize = Util.ArrayToUint32(m_br.ReadBytes(sizeof(UInt32))); // failsafe: Read error, return immediately. if (eh.blockSize != m_rootHeader.blockSize) { break; } entrycount++; // Length of the entry in bytes. eh.byteCount = Util.ArrayToUint32(m_br.ReadBytes(sizeof(UInt32))); // Length of the entry in blocks. eh.blockCount = Util.ArrayToUint32(m_br.ReadBytes(sizeof(UInt32))); //Console.WriteLine("BlockCount: " + eh.blockCount); // Burst. eh.burst = Util.ArrayToUint32(m_br.ReadBytes(sizeof(UInt32))); // Gap. eh.gap = Util.ArrayToUint32(m_br.ReadBytes(sizeof(UInt32))); // Filename. eh.filename = m_br.ReadBytes(m_filenameSize); //Console.Write("Filename: "); //for (int i = 0; i < m_filenameSize; i++) // Console.Write((Char)eh.filename[i]); //Console.Write(Environment.NewLine); // Number of avatars. eh.avatarsCount = Util.ArrayToUint32(m_br.ReadBytes(sizeof(UInt32))); // Offset to the avatars, from the beginning of the disk, in blocks. eh.avatars = new UInt32[eh.avatarsCount + 1]; //Console.Write("Locations of the avatars: "); for (int i = 0; i < eh.avatarsCount + 1; i++) { eh.avatars[i] = Util.ArrayToUint32(m_br.ReadBytes(sizeof(UInt32))); //Console.Write(eh.avatars[i] + " "); } //Console.Write(Environment.NewLine); // Add entry header to the list. m_entryHeaderList.Add(eh); //-- if (m_blocks.ContainsKey(currentBlock) == false) { m_blocks[currentBlock] = new BlockInfo(); } BlockInfo block = m_blocks[currentBlock]; if (block.entryHeaders == null) { block.entryHeaders = new List <EntryHeader>(); } block.entryHeaders.Add(eh); m_blocks[currentBlock] = block; //-- //if (entryFlags.HasFlag(EntryFlags.SpecialFile) == true) //{ // Console.Write("Special File: "); // for (int i = 0; i < m_filenameSize; i++) // Console.Write((Char)eh.filename[i]); // Console.Write(Environment.NewLine); //} // Create directory. if (entryFlags.HasFlag(EntryFlags.Directory) == true) { // Store the current position. long currentPosition = m_br.BaseStream.Position; // For the filename we need to convert from Byte ASCII to Unicode string and trim the padding ('\0'). Byte[] bytes = Encoding.Convert(Encoding.ASCII, Encoding.Unicode, eh.filename); String unicode = Encoding.Unicode.GetString(bytes).Trim('\0'); String dirPath = currentPath + m_separator + unicode; ReadDirectory(eh.avatars[0], 0, dirPath); // Return to previous position. m_br.BaseStream.Seek(currentPosition, SeekOrigin.Begin); } else // Write file. { // [CRIS] special case: Disc label is the header of the FileSystem referenced as a file. Do not create this file. if (Encoding.ASCII.GetString(eh.filename).Contains("Disc label") == false && Encoding.ASCII.GetString(eh.type).Equals("*lbl") == false) { // Store the current position. long currentPosition = m_br.BaseStream.Position; // For the filename we need to convert from Byte ASCII to Unicode string and trim the padding ('\0'). Byte[] bytes = Encoding.Convert(Encoding.ASCII, Encoding.Unicode, eh.filename); String unicode = Encoding.Unicode.GetString(bytes).Trim('\0'); String filePath = currentPath + m_separator + unicode; //Console.WriteLine("Writing '" + unicode + "'..."); ReadFile(eh.avatars[0], filePath, eh.byteCount); // Return to previous position. m_br.BaseStream.Seek(currentPosition, SeekOrigin.Begin); } } } }
// -first free byte // -root header // -write to file // -profit private void SaveBlocks(String filename) { try { FileStream fs = new FileStream(filename, FileMode.Create); m_bw = new BinaryWriter(fs); //----------------------------- // The first block is special. m_volumeHeader.recordType = 1; m_volumeHeader.syncBytes = new Byte[] { 0x5A, 0x5A, 0x5A, 0x5A, 0x5A }; m_volumeHeader.structureVersion = 1; m_volumeHeader.flags = 0; m_volumeHeader.comment = new Byte[m_volumeCommentSize]; m_volumeHeader.label = new Byte[m_volumeLabelSize]; m_volumeHeader.label[0] = (Byte)'C'; m_volumeHeader.label[1] = (Byte)'D'; m_volumeHeader.label[2] = (Byte)'-'; m_volumeHeader.label[3] = (Byte)'R'; m_volumeHeader.label[4] = (Byte)'O'; m_volumeHeader.label[5] = (Byte)'M'; m_volumeHeader.identifier = 1366613; // TODO? m_volumeHeader.blockSize = m_blockSize; m_volumeHeader.blockCount = 1 + (UInt32)m_headerBlocks.Keys.Last() + (UInt32)m_dataBlocks.Keys.Last(); m_rootHeader.id = 666; // TODO? m_rootHeader.blockCount = 1; // TODO!!! m_rootHeader.blockSize = m_blockSize; m_rootHeader.avatarsCount = 7; // TODO? m_rootHeader.avatars = new UInt32[] { 1, 1, 1, 1, 1, 1, 1, 1 }; // TODO? // Volume header. m_bw.Write(m_volumeHeader.recordType); m_bw.Write(m_volumeHeader.syncBytes); m_bw.Write(m_volumeHeader.structureVersion); m_bw.Write(m_volumeHeader.flags); m_bw.Write(m_volumeHeader.comment); m_bw.Write(m_volumeHeader.label); m_bw.Write(Util.UInt32ToArray(m_volumeHeader.identifier)); m_bw.Write(Util.UInt32ToArray(m_volumeHeader.blockSize)); m_bw.Write(Util.UInt32ToArray(m_volumeHeader.blockCount)); // Root header. m_bw.Write(Util.UInt32ToArray(m_rootHeader.id)); m_bw.Write(Util.UInt32ToArray(m_rootHeader.blockCount)); m_bw.Write(Util.UInt32ToArray(m_rootHeader.blockSize)); m_bw.Write(Util.UInt32ToArray(m_rootHeader.avatarsCount)); for (int i = 0; i < m_rootHeader.avatarsCount + 1; i++) { m_bw.Write(Util.UInt32ToArray(m_rootHeader.avatars[i])); } // Null ended. m_bw.Write(0); // Duck this block. WriteDuck(); //Console.WriteLine("Blocks: " + m_volumeHeader.blockCount); //Console.WriteLine("Block " + 0 + ": Volume and Root Header"); //----------------------------- // Write standard blocks. foreach (KeyValuePair <uint, BlockInfo> headerBlock in m_headerBlocks) { BlockInfo block = headerBlock.Value; // Directory header. m_bw.Write(Util.UInt32ToArray(block.directoryHeader.nextBlock)); m_bw.Write(Util.UInt32ToArray(block.directoryHeader.prevBlock)); m_bw.Write(Util.UInt32ToArray(block.directoryHeader.flags)); m_bw.Write(Util.UInt32ToArray(block.directoryHeader.firstFreeByte)); m_bw.Write(Util.UInt32ToArray(block.directoryHeader.firstEntryOffset)); // Entry headers. for (int j = 0; j < block.entryHeaders.Count; j++) { m_bw.Write(Util.UInt32ToArray(block.entryHeaders[j].flags)); m_bw.Write(Util.UInt32ToArray(block.entryHeaders[j].id)); m_bw.Write(block.entryHeaders[j].type); m_bw.Write(Util.UInt32ToArray(block.entryHeaders[j].blockSize)); m_bw.Write(Util.UInt32ToArray(block.entryHeaders[j].byteCount)); m_bw.Write(Util.UInt32ToArray(block.entryHeaders[j].blockCount)); m_bw.Write(Util.UInt32ToArray(block.entryHeaders[j].burst)); m_bw.Write(Util.UInt32ToArray(block.entryHeaders[j].gap)); for (int k = 0; k < block.entryHeaders[j].filename.Length; k++) { m_bw.Write(block.entryHeaders[j].filename[k]); } //for (int k = 0; k < block.entryHeaders[j].filename.Length; k++) // Console.Write((char)block.entryHeaders[j].filename[k]); //Console.WriteLine(""); m_bw.Write(Util.UInt32ToArray(block.entryHeaders[j].avatarsCount)); for (int k = 0; k < block.entryHeaders[j].avatars.Length; k++) { m_bw.Write(Util.UInt32ToArray(block.entryHeaders[j].avatars[k])); } } // Duck this block. WriteDuck(); } foreach (KeyValuePair <uint, BlockInfo> dataBlock in m_dataBlocks) { BlockInfo block = dataBlock.Value; // Write file data. m_bw.Write(block.data); // Duck final block. WriteDuck(); } //---------- m_bw.Close(); fs.Close(); } catch (Exception ex) { Console.Error.WriteLine(ex); } }
private void ConvertFilesToBlocks(String path) { m_currentFSIndex = 413666134; // Starting index. UInt32 currentHBlock = 1; // Header block. UInt32 currentDBlock = 0; // Data block. bool isFirstBlock = true; //------------------------------------------------- // Special file: Disc label. CreateNewHeaderBlock(currentHBlock, 0xffffffff, 0xffffffff); EntryHeader ehLabel = new EntryHeader(); ehLabel.flags = 0x06; // Special file. ehLabel.id = GetNewFSIndex(); ehLabel.type = GetEntryTypeAsArray("*lbl"); ehLabel.blockSize = m_blockSize; ehLabel.byteCount = m_discLabelByteCount; ehLabel.blockCount = 1; ehLabel.burst = 1; ehLabel.gap = 0; ehLabel.filename = GetFilenameAsArray("Disc label"); ehLabel.avatarsCount = 0; ehLabel.avatars = new UInt32[] { 0 }; // Add to current block. AddEntryToHeaderBlock(ehLabel, currentHBlock); //------------------------------------------------- // Headers. int dirCountTotal = 0; int fileCountTotal = 0; UInt32 avatarPosition = 2; Queue <String> queue = new Queue <String>(); queue.Enqueue(path); while (queue.Count > 0) { path = queue.Dequeue(); try { int totalEntriesCount = Directory.GetDirectories(path).Length + Directory.GetFiles(path).Length; UInt32 blockOffset = 0; int indexEntry = 1; int totalIndexEntry = 1; // Create new header block (only after block, because of Disc label). if (isFirstBlock == false) { currentHBlock++; CreateNewHeaderBlock(currentHBlock, 0xffffffff, 0xffffffff); } else { isFirstBlock = false; } UInt32 blockCountAvatarOffset = (UInt32)((totalEntriesCount + m_maxEntryHeadersPerBlock - 1) / m_maxEntryHeadersPerBlock); String lastIndexDir = String.Empty; // Directories. foreach (String subDir in Directory.GetDirectories(path)) { queue.Enqueue(subDir); //Console.WriteLine(subDir); dirCountTotal++; int currentEntriesCount = Directory.GetDirectories(subDir).Length + Directory.GetFiles(subDir).Length; // Create entry. EntryHeader eh = new EntryHeader(); eh.flags = 0x07; eh.id = GetNewFSIndex(); eh.type = GetEntryTypeAsArray("*dir"); eh.blockSize = m_blockSize; eh.blockCount = (UInt32)((currentEntriesCount + m_maxEntryHeadersPerBlock - 1) / m_maxEntryHeadersPerBlock); eh.byteCount = (UInt32)(eh.blockCount * m_blockSize); eh.burst = 1; eh.gap = 0; eh.filename = GetFilenameAsArray(Path.GetFileName(subDir)); eh.avatarsCount = 0; // Remember: must add actual avatar array later. //eh.avatars = // Remember: must add actual avatar array later. eh.avatars = new UInt32[1]; //---------------------------- // Calculate avatar position. eh.avatars[0] = avatarPosition; avatarPosition += eh.blockCount; if (eh.blockCount * m_maxEntryHeadersPerBlock == currentEntriesCount) { avatarPosition++; } //---------------------------- // Check if this is the last dir entry of the dir. if (totalIndexEntry == totalEntriesCount) { eh.flags |= 0x80000000; eh.flags |= 0x40000000; //avatarPosition += eh.blockCount; } // Check if this is the last dir entry in the block. else if (indexEntry + 1 == m_maxEntryHeadersPerBlock) { eh.flags |= 0x40000000; } if (indexEntry == m_maxEntryHeadersPerBlock) { indexEntry = 1; blockOffset++; // Set the info about the new block in the older one. BlockInfo oldBlock = m_headerBlocks[currentHBlock]; oldBlock.directoryHeader.nextBlock = blockOffset; m_headerBlocks[currentHBlock] = oldBlock; // Create a new block and add it. currentHBlock++; CreateNewHeaderBlock(currentHBlock, 0xffffffff, blockOffset - 1); } // Add to current block. AddEntryToHeaderBlock(eh, currentHBlock); totalIndexEntry++; indexEntry++; } // Files. foreach (String file in Directory.GetFiles(path)) { fileCountTotal++; //Console.WriteLine(file); // Create data block. BlockInfo dataBlock = new BlockInfo(); dataBlock.data = File.ReadAllBytes(file); m_dataBlocks[currentDBlock] = dataBlock; currentDBlock += (UInt32)(dataBlock.data.Length / m_blockSize) + 1; // Create entry. EntryHeader eh = new EntryHeader(); eh.flags = 0x02; eh.id = GetNewFSIndex(); eh.type = GetEntryTypeAsArray(Path.GetExtension(file)); eh.blockSize = m_blockSize; eh.byteCount = (UInt32)dataBlock.data.Length; eh.blockCount = (UInt32)((dataBlock.data.Length + m_blockSize - 1) / m_blockSize); eh.burst = 1; eh.gap = 0; eh.filename = GetFilenameAsArray(Path.GetFileName(file)); eh.avatarsCount = 0; // Remember: must add actual avatar array later. //eh.avatars = // Remember: must add actual avatar array later. // TODO... // Check if this is the last dir entry of the dir. if (totalIndexEntry == totalEntriesCount) { eh.flags |= 0x80000000; eh.flags |= 0x40000000; } // Check if this is the last dir entry in the block. else if (indexEntry + 1 == m_maxEntryHeadersPerBlock) { eh.flags |= 0x40000000; } if (indexEntry == m_maxEntryHeadersPerBlock) { indexEntry = 1; blockOffset++; //avatarPosition++; // Set the info about the new block in the older one. BlockInfo oldBlock = m_headerBlocks[currentHBlock]; oldBlock.directoryHeader.nextBlock = blockOffset; m_headerBlocks[currentHBlock] = oldBlock; // Create a new block and add it. currentHBlock++; CreateNewHeaderBlock(currentHBlock, 0xffffffff, blockOffset - 1); } // Add to current block. AddEntryToHeaderBlock(eh, currentHBlock); totalIndexEntry++; indexEntry++; } } catch (Exception ex) { Console.Error.WriteLine(ex); } } Console.WriteLine("dirCountTotal: " + dirCountTotal); Console.WriteLine("fileCountTotal: " + fileCountTotal); }
public void CompileFSFromMemory(String filename) { try { FileStream fs = new FileStream(filename, FileMode.Create); m_bw = new BinaryWriter(fs); //----------------------------- // The first block is special. // Volume header. m_bw.Write(m_volumeHeader.recordType); m_bw.Write(m_volumeHeader.syncBytes); m_bw.Write(m_volumeHeader.structureVersion); m_bw.Write(m_volumeHeader.flags); m_bw.Write(m_volumeHeader.comment); m_bw.Write(m_volumeHeader.label); m_bw.Write(Util.UInt32ToArray(m_volumeHeader.identifier)); m_bw.Write(Util.UInt32ToArray(m_volumeHeader.blockSize)); m_bw.Write(Util.UInt32ToArray(m_volumeHeader.blockCount)); // Root header. m_bw.Write(Util.UInt32ToArray(m_rootHeader.id)); m_bw.Write(Util.UInt32ToArray(m_rootHeader.blockCount)); m_bw.Write(Util.UInt32ToArray(m_rootHeader.blockSize)); m_bw.Write(Util.UInt32ToArray(m_rootHeader.avatarsCount)); for (int i = 0; i < m_rootHeader.avatarsCount + 1; i++) { m_bw.Write(Util.UInt32ToArray(m_rootHeader.avatars[i])); } // Null ended. m_bw.Write(0); // Duck this block. WriteDuck(); //----------------------------- // Write standard blocks. for (UInt32 i = 1; i < m_volumeHeader.blockCount;) { if (m_blocks.ContainsKey(i) == true) { BlockInfo block = m_blocks[i]; if (block.type == BlockType.Data) { //Console.WriteLine("Block " + i + ": Data"); // Write file data. m_bw.Write(block.data); // Duck final block. WriteDuck(); UInt32 blockCount = (UInt32)((block.data.Length + m_volumeHeader.blockSize - 1) / m_volumeHeader.blockSize); i += blockCount; //Console.WriteLine("size: " + blockCount); } else if (block.type == BlockType.Header) { //Console.WriteLine("Block " + i + ": Header"); // Directory header. m_bw.Write(Util.UInt32ToArray(block.directoryHeader.nextBlock)); m_bw.Write(Util.UInt32ToArray(block.directoryHeader.prevBlock)); m_bw.Write(Util.UInt32ToArray(block.directoryHeader.flags)); m_bw.Write(Util.UInt32ToArray(block.directoryHeader.firstFreeByte)); m_bw.Write(Util.UInt32ToArray(block.directoryHeader.firstEntryOffset)); // Entry headers. for (int j = 0; j < block.entryHeaders.Count; j++) { m_bw.Write(Util.UInt32ToArray(block.entryHeaders[j].flags)); m_bw.Write(Util.UInt32ToArray(block.entryHeaders[j].id)); for (int k = 0; k < block.entryHeaders[j].type.Length; k++) { m_bw.Write(block.entryHeaders[j].type[k]); } m_bw.Write(Util.UInt32ToArray(block.entryHeaders[j].blockSize)); m_bw.Write(Util.UInt32ToArray(block.entryHeaders[j].byteCount)); m_bw.Write(Util.UInt32ToArray(block.entryHeaders[j].blockCount)); m_bw.Write(Util.UInt32ToArray(block.entryHeaders[j].burst)); m_bw.Write(Util.UInt32ToArray(block.entryHeaders[j].gap)); for (int k = 0; k < block.entryHeaders[j].filename.Length; k++) { m_bw.Write(block.entryHeaders[j].filename[k]); } m_bw.Write(Util.UInt32ToArray(block.entryHeaders[j].avatarsCount)); for (int k = 0; k < block.entryHeaders[j].avatars.Length; k++) { m_bw.Write(Util.UInt32ToArray(block.entryHeaders[j].avatars[k])); } } // Duck this block. WriteDuck(); i++; } else { // FAIL block? Console.WriteLine("Block " + i + ": FAIL"); WriteDuck(); i++; } } else { // Empty block. Console.WriteLine("Block " + i + ": Empty"); WriteDuck(); i++; } } //---------- m_bw.Close(); fs.Close(); } catch (Exception ex) { Console.Error.WriteLine(ex); } }