Пример #1
0
        /// <summary>
        /// Create a new metadata block.
        /// </summary>
        /// <param name="fs">The FileStream instance to use.</param>
        /// <param name="blockSize">The block size, in bytes.</param>
        /// <param name="parentBlock">The position of the parent block.</param>
        /// <param name="childDataBlock">The position of the child data block.</param>
        /// <param name="fullDataLength">The full length of the data represented by this metadata block.</param>
        /// <param name="isDirectory">Indicates if this metadata block describes a directory.</param>
        /// <param name="isFile">Indicates if this metadata block describes a file.</param>
        /// <param name="name">The name of the file or directory.</param>
        /// <param name="data">Byte data stored in this block.</param>
        /// <param name="logging">Instance of LoggingModule to use for logging events.</param>
        public MetadataBlock(
            FileStream fs,
            int blockSize,
            long parentBlock,
            long childDataBlock,
            long fullDataLength,
            int isDirectory,
            int isFile,
            string name,
            byte[] data,
            LoggingModule logging)
        {
            if (fs == null)
            {
                throw new ArgumentNullException(nameof(fs));
            }
            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 (!CfsCommon.IsTrue(isFile) && !CfsCommon.IsTrue(isDirectory))
            {
                throw new ArgumentException("Either isFile or isDirectory must be set");
            }
            if (CfsCommon.IsTrue(isFile) && CfsCommon.IsTrue(isDirectory))
            {
                throw new ArgumentException("Only one of isFile and isDirectory must be set");
            }

            Logging        = logging;
            BlockSizeBytes = blockSize;
            ParentBlock    = parentBlock;
            ChildDataBlock = childDataBlock;

            if (data == null)
            {
                LocalDataLength = 0;
            }
            else
            {
                LocalDataLength = data.Length;
            }
            Data = data;

            FullDataLength = fullDataLength;
            IsDirectory    = isDirectory;
            IsFile         = isFile;
            Name           = name;
            DateTime ts = DateTime.Now.ToUniversalTime();

            CreatedUtc    = ts.ToString(DateTimeFormat);
            LastUpdateUtc = ts.ToString(DateTimeFormat);
        }
Пример #2
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());
        }
Пример #3
0
        /// <summary>
        /// Retrieve data from the specified range.
        /// </summary>
        /// <param name="startPosition">The starting position from which to read.</param>
        /// <param name="count">The number of bytes to read.</param>
        /// <returns>Byte data for the requested range.</returns>
        public byte[] GetData(long startPosition, long count)
        {
            if (CfsCommon.IsTrue(IsDirectory))
            {
                throw new InvalidOperationException("Get data must only be called on file metadata blocks");
            }

            if (Data == null || Data.Length < 1)
            {
                return(null);
            }

            byte[] localData = new byte[LocalDataLength];
            Buffer.BlockCopy(Data, 0, localData, 0, LocalDataLength);

            if (ChildDataBlock > 0)
            {
                // get child data
                byte[]    nextBytes = CfsCommon.ReadFromPosition(Filestream, ChildDataBlock, 64);
                DataBlock nextBlock = DataBlock.FromBytes(Filestream, BlockSizeBytes, nextBytes, Logging);
                nextBlock.Filestream = Filestream;
                byte[] childData = nextBlock.GetAllData();

                // join
                if (childData != null)
                {
                    byte[] ret = new byte[(localData.Length + childData.Length)];
                    Buffer.BlockCopy(localData, 0, ret, 0, localData.Length);
                    Buffer.BlockCopy(childData, 0, ret, localData.Length, childData.Length);
                    return(ret);
                }
                else
                {
                    return(localData);
                }
            }
            else
            {
                return(localData);
            }
        }