예제 #1
0
        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);
                    }
                }
            }
        }
예제 #2
0
        // -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);
            }
        }
예제 #3
0
        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);
        }
예제 #4
0
        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);
            }
        }