예제 #1
0
        internal long Persist()
        {
            if (_ids.Count <= 0)
            {
                return -1;
            }

            if (_ids.Count * 4 > _context.DataBlockSize)
            {
                throw new NotImplementedException("Large numbers of user / group id's");
            }

            for (int i = 0; i < _ids.Count; ++i)
            {
                Utilities.WriteBytesLittleEndian(_ids[i], _context.IoBuffer, i * 4);
            }

            // Persist the actual Id's
            long blockPos = _context.RawStream.Position;
            MetablockWriter writer = new MetablockWriter();
            writer.Write(_context.IoBuffer, 0, _ids.Count * 4);
            writer.Persist(_context.RawStream);

            // Persist the table that references the block containing the id's
            long tablePos = _context.RawStream.Position;
            byte[] tableBuffer = new byte[8];
            Utilities.WriteBytesLittleEndian(blockPos, tableBuffer, 0);
            _context.RawStream.Write(tableBuffer, 0, 8);

            return tablePos;
        }
예제 #2
0
        internal long Persist()
        {
            if (_ids.Count <= 0)
            {
                return(-1);
            }

            if (_ids.Count * 4 > _context.DataBlockSize)
            {
                throw new NotImplementedException("Large numbers of user / group id's");
            }

            for (int i = 0; i < _ids.Count; ++i)
            {
                EndianUtilities.WriteBytesLittleEndian(_ids[i], _context.IoBuffer, i * 4);
            }

            // Persist the actual Id's
            long            blockPos = _context.RawStream.Position;
            MetablockWriter writer   = new MetablockWriter();

            writer.Write(_context.IoBuffer, 0, _ids.Count * 4);
            writer.Persist(_context.RawStream);

            // Persist the table that references the block containing the id's
            long tablePos = _context.RawStream.Position;

            byte[] tableBuffer = new byte[8];
            EndianUtilities.WriteBytesLittleEndian(blockPos, tableBuffer, 0);
            _context.RawStream.Write(tableBuffer, 0, 8);

            return(tablePos);
        }
예제 #3
0
        internal long Persist()
        {
            if (_fragmentBlocks.Count <= 0)
            {
                return(-1);
            }

            if (_fragmentBlocks.Count * FragmentRecord.RecordSize > _context.DataBlockSize)
            {
                throw new NotImplementedException("Large numbers of fragments");
            }

            // Persist the table that references the block containing the fragment records
            long blockPos   = _context.RawStream.Position;
            int  recordSize = FragmentRecord.RecordSize;

            byte[] buffer = new byte[_fragmentBlocks.Count * recordSize];
            for (int i = 0; i < _fragmentBlocks.Count; ++i)
            {
                _fragmentBlocks[i].WriteTo(buffer, i * recordSize);
            }

            MetablockWriter writer = new MetablockWriter();

            writer.Write(buffer, 0, buffer.Length);
            writer.Persist(_context.RawStream);

            long tablePos = _context.RawStream.Position;

            byte[] tableBuffer = new byte[8];
            EndianUtilities.WriteBytesLittleEndian(blockPos, tableBuffer, 0);
            _context.RawStream.Write(tableBuffer, 0, 8);

            return(tablePos);
        }
예제 #4
0
        internal long Persist()
        {
            if (_fragmentBlocks.Count <= 0)
            {
                return -1;
            }

            if (_fragmentBlocks.Count * FragmentRecord.RecordSize > _context.DataBlockSize)
            {
                throw new NotImplementedException("Large numbers of fragments");
            }

            // Persist the table that references the block containing the fragment records
            long blockPos = _context.RawStream.Position;
            int recordSize = FragmentRecord.RecordSize;
            byte[] buffer = new byte[_fragmentBlocks.Count * recordSize];
            for (int i = 0; i < _fragmentBlocks.Count; ++i)
            {
                _fragmentBlocks[i].WriteTo(buffer, i * recordSize);
            }

            MetablockWriter writer = new MetablockWriter();
            writer.Write(buffer, 0, buffer.Length);
            writer.Persist(_context.RawStream);

            long tablePos = _context.RawStream.Position;
            byte[] tableBuffer = new byte[8];
            Utilities.WriteBytesLittleEndian(blockPos, tableBuffer, 0);
            _context.RawStream.Write(tableBuffer, 0, 8);

            return tablePos;
        }
        /// <summary>
        /// Writes the file system to an existing stream.
        /// </summary>
        /// <param name="output">The stream to write to.</param>
        /// <remarks>The <c>output</c> stream must support seeking and writing.</remarks>
        public void Build(Stream output)
        {
            if (output == null)
            {
                throw new ArgumentNullException("output");
            }

            if (!output.CanWrite)
            {
                throw new ArgumentException("Output stream must be writable", "output");
            }

            if (!output.CanSeek)
            {
                throw new ArgumentException("Output stream must support seeking", "output");
            }

            _context = new BuilderContext()
            {
                RawStream     = output,
                DataBlockSize = DefaultBlockSize,
                IoBuffer      = new byte[DefaultBlockSize],
            };

            MetablockWriter inodeWriter = new MetablockWriter();
            MetablockWriter dirWriter   = new MetablockWriter();
            FragmentWriter  fragWriter  = new FragmentWriter(_context);
            IdTableWriter   idWriter    = new IdTableWriter(_context);

            _context.AllocateInode   = AllocateInode;
            _context.AllocateId      = idWriter.AllocateId;
            _context.WriteDataBlock  = WriteDataBlock;
            _context.WriteFragment   = fragWriter.WriteFragment;
            _context.InodeWriter     = inodeWriter;
            _context.DirectoryWriter = dirWriter;

            _nextInode = 1;

            SuperBlock superBlock = new SuperBlock();

            superBlock.Magic         = SuperBlock.SquashFsMagic;
            superBlock.CreationTime  = DateTime.Now;
            superBlock.BlockSize     = (uint)_context.DataBlockSize;
            superBlock.Compression   = 1; // DEFLATE
            superBlock.BlockSizeLog2 = (ushort)Utilities.Log2(superBlock.BlockSize);
            superBlock.MajorVersion  = 4;
            superBlock.MinorVersion  = 0;

            output.Position = superBlock.Size;

            GetRoot().Reset();
            GetRoot().Write(_context);
            fragWriter.Flush();
            superBlock.RootInode      = GetRoot().InodeRef;
            superBlock.InodesCount    = _nextInode - 1;
            superBlock.FragmentsCount = (uint)fragWriter.FragmentCount;
            superBlock.UidGidCount    = (ushort)idWriter.IdCount;

            superBlock.InodeTableStart = output.Position;
            inodeWriter.Persist(output);

            superBlock.DirectoryTableStart = output.Position;
            dirWriter.Persist(output);

            superBlock.FragmentTableStart      = fragWriter.Persist();
            superBlock.LookupTableStart        = -1;
            superBlock.UidGidTableStart        = idWriter.Persist();
            superBlock.ExtendedAttrsTableStart = -1;
            superBlock.BytesUsed = output.Position;

            // Pad to 4KB
            long end = Utilities.RoundUp(output.Position, 4 * Sizes.OneKiB);

            if (end != output.Position)
            {
                byte[] padding = new byte[(int)(end - output.Position)];
                output.Write(padding, 0, padding.Length);
            }

            // Go back and write the superblock
            output.Position = 0;
            byte[] buffer = new byte[superBlock.Size];
            superBlock.WriteTo(buffer, 0);
            output.Write(buffer, 0, buffer.Length);
            output.Position = end;
        }
예제 #6
0
        /// <summary>
        /// Writes the file system to an existing stream.
        /// </summary>
        /// <param name="output">The stream to write to.</param>
        /// <remarks>The <c>output</c> stream must support seeking and writing.</remarks>
        public void Build(Stream output)
        {
            if (output == null)
            {
                throw new ArgumentNullException("output");
            }

            if (!output.CanWrite)
            {
                throw new ArgumentException("Output stream must be writable", "output");
            }

            if (!output.CanSeek)
            {
                throw new ArgumentException("Output stream must support seeking", "output");
            }

            _context = new BuilderContext()
            {
                RawStream = output,
                DataBlockSize = DefaultBlockSize,
                IoBuffer = new byte[DefaultBlockSize],
            };

            MetablockWriter inodeWriter = new MetablockWriter();
            MetablockWriter dirWriter = new MetablockWriter();
            FragmentWriter fragWriter = new FragmentWriter(_context);
            IdTableWriter idWriter = new IdTableWriter(_context);

            _context.AllocateInode = AllocateInode;
            _context.AllocateId = idWriter.AllocateId;
            _context.WriteDataBlock = WriteDataBlock;
            _context.WriteFragment = fragWriter.WriteFragment;
            _context.InodeWriter = inodeWriter;
            _context.DirectoryWriter = dirWriter;

            _nextInode = 1;

            SuperBlock superBlock = new SuperBlock();
            superBlock.Magic = SuperBlock.SquashFsMagic;
            superBlock.CreationTime = DateTime.Now;
            superBlock.BlockSize = (uint)_context.DataBlockSize;
            superBlock.Compression = 1; // DEFLATE
            superBlock.BlockSizeLog2 = (ushort)Utilities.Log2(superBlock.BlockSize);
            superBlock.MajorVersion = 4;
            superBlock.MinorVersion = 0;

            output.Position = superBlock.Size;

            GetRoot().Reset();
            GetRoot().Write(_context);
            fragWriter.Flush();
            superBlock.RootInode = GetRoot().InodeRef;
            superBlock.InodesCount = _nextInode - 1;
            superBlock.FragmentsCount = (uint)fragWriter.FragmentCount;
            superBlock.UidGidCount = (ushort)idWriter.IdCount;

            superBlock.InodeTableStart = output.Position;
            inodeWriter.Persist(output);

            superBlock.DirectoryTableStart = output.Position;
            dirWriter.Persist(output);

            superBlock.FragmentTableStart = fragWriter.Persist();
            superBlock.LookupTableStart = -1;
            superBlock.UidGidTableStart = idWriter.Persist();
            superBlock.ExtendedAttrsTableStart = -1;
            superBlock.BytesUsed = output.Position;

            // Pad to 4KB
            long end = Utilities.RoundUp(output.Position, 4 * Sizes.OneKiB);
            if (end != output.Position)
            {
                byte[] padding = new byte[(int)(end - output.Position)];
                output.Write(padding, 0, padding.Length);
            }

            // Go back and write the superblock
            output.Position = 0;
            byte[] buffer = new byte[superBlock.Size];
            superBlock.WriteTo(buffer, 0);
            output.Write(buffer, 0, buffer.Length);
            output.Position = end;
        }