예제 #1
0
        /// <summary>
        /// Retieve the positions of all linked metadata entries found in this block and associated child data blocks.
        /// </summary>
        /// <returns>Array of Long.</returns>
        public long[] GetMetadataBlocks()
        {
            if (CfsCommon.IsTrue(IsFile))
            {
                throw new InvalidOperationException("Get metadata blocks must only be called on directory metadata blocks");
            }

            List <long> ret = new List <long>();

            if (Data == null || Data.Length < 8)
            {
                return(ret.ToArray());
            }
            int pos = 0;

            LogDebug("GetMetadataBlocks retrieving metadata blocks from data length of " + Data.Length);

            while (pos < Data.Length)
            {
                byte[] currBlock = new byte[8];
                Buffer.BlockCopy(Data, pos, currBlock, 0, 8);
                Int64 block = BitConverter.ToInt64(currBlock, 0);

                LogDebug("GetMetadataBlocks adding metadata block position " + block);
                ret.Add(block);
                pos += 8;
            }

            if (ChildDataBlock > 0)
            {
                LogDebug("GetMetadataBlocks child data block referenced at " + ChildDataBlock);
                byte[]        nextBlockBytes = CfsCommon.ReadFromPosition(Filestream, ChildDataBlock, 512);
                MetadataBlock nextBlock      = MetadataBlock.FromBytes(Filestream, BlockSizeBytes, nextBlockBytes, Logging);
                nextBlock.Filestream = Filestream;
                long[] childBlocks = nextBlock.GetMetadataBlocks();

                foreach (long curr in childBlocks)
                {
                    ret.Add(curr);
                }
            }

            return(ret.ToArray());
        }
예제 #2
0
        /// <summary>
        /// Create a new metadata block instance from a byte array from data found within the container file.
        /// </summary>
        /// <param name="fs">The FileStream instance to use.</param>
        /// <param name="blockSize">The block size, in bytes.</param>
        /// <param name="ba">The byte array containing the full block.</param>
        /// <param name="logging">Instance of LoggingModule to use for logging events.</param>
        /// <returns>A populated MetadataBlock object.</returns>
        public static MetadataBlock FromBytes(FileStream fs, int blockSize, byte[] ba, LoggingModule logging)
        {
            try
            {
                if (ba == null || ba.Length < 1)
                {
                    throw new ArgumentNullException(nameof(ba));
                }
                if (ba.Length < 64)
                {
                    throw new ArgumentException("Byte array has length less than 64");
                }
                if (blockSize < 4096)
                {
                    throw new ArgumentOutOfRangeException("Block size must be greater than or equal to 4096");
                }
                if (blockSize % 4096 != 0)
                {
                    throw new ArgumentOutOfRangeException("Block size must be evenly divisible by 4096");
                }
                if (fs == null)
                {
                    throw new ArgumentNullException(nameof(fs));
                }

                MetadataBlock ret = new MetadataBlock();
                ret.Signature      = MetadataBlock.SignatureBytes;
                ret.BlockSizeBytes = blockSize;
                ret.Logging        = logging;
                ret.Filestream     = fs;

                byte[] temp;

                Buffer.BlockCopy(ba, 0, ret.Signature, 0, 4);

                temp = new byte[8];
                Buffer.BlockCopy(ba, 4, temp, 0, 8);
                ret.ParentBlock = BitConverter.ToInt64(temp, 0);

                temp = new byte[8];
                Buffer.BlockCopy(ba, 12, temp, 0, 8);
                ret.ChildDataBlock = BitConverter.ToInt64(temp, 0);

                temp = new byte[4];
                Buffer.BlockCopy(ba, 20, temp, 0, 4);
                ret.FullDataLength = BitConverter.ToInt32(temp, 0);

                temp = new byte[4];
                Buffer.BlockCopy(ba, 28, temp, 0, 4);
                ret.LocalDataLength = BitConverter.ToInt32(temp, 0);

                temp = new byte[4];
                Buffer.BlockCopy(ba, 32, temp, 0, 4);
                ret.IsDirectory = BitConverter.ToInt32(temp, 0);

                temp = new byte[4];
                Buffer.BlockCopy(ba, 36, temp, 0, 4);
                ret.IsFile = BitConverter.ToInt32(temp, 0);

                temp = new byte[256];
                Buffer.BlockCopy(ba, 40, temp, 0, 256);
                ret.Name = Encoding.UTF8.GetString(CfsCommon.TrimNullBytes(temp)).Trim();

                temp = new byte[32];
                Buffer.BlockCopy(ba, 296, temp, 0, 32);
                ret.CreatedUtc = Encoding.UTF8.GetString(CfsCommon.TrimNullBytes(temp)).Trim();

                temp = new byte[32];
                Buffer.BlockCopy(ba, 328, temp, 0, 32);
                ret.LastUpdateUtc = Encoding.UTF8.GetString(CfsCommon.TrimNullBytes(temp)).Trim();

                temp = new byte[ret.LocalDataLength];
                Buffer.BlockCopy(ba, 512, temp, 0, ret.LocalDataLength);
                ret.Data = temp;

                return(ret);
            }
            catch (Exception e)
            {
                if (logging != null)
                {
                    logging.LogException("MetadataBlock", "FromBytes", e);
                }
                else
                {
                    LoggingModule.ConsoleException("MetadataBlock", "FromBytes", e);
                }
                throw;
            }
        }