Esempio n. 1
0
        /// <summary>
        /// Reads the volume descriptors for
        /// </summary>
        /// <param name="extentVds">The anchor volume extent information.</param>
        /// <returns>Returns true if the volume descriptors were read from the image successfully.</returns>
        private bool ReadVolumeDescriptors(UdfFileExtent extentVds)
        {
            byte[] buffer = new byte[SectorSize];

            long location = extentVds.Position;

            while (location < extentVds.Length && location < this.imageSize)
            {
                this.stream.Seek(location << SectorSizeLog, (int)SeekOrigin.Begin, IntPtr.Zero);
                if (!this.stream.ReadSafe(buffer, buffer.Length))
                {
                    return(false);
                }

                VolumeTag tag = new VolumeTag();
                tag.Parse(0, buffer, buffer.Length);

                switch ((VolumeDescriptorType)tag.Identifier)
                {
                case VolumeDescriptorType.Terminating:
                    // Found terminating descriptor.  Image is valid.
                    return(true);

                case VolumeDescriptorType.Partition:
                    if (this.Partitions.Count >= MaxPartitions)
                    {
                        return(false);
                    }

                    this.ReadPartitionDescriptor(buffer);
                    break;

                case VolumeDescriptorType.LogicalVolume:
                    if (this.LogicalVolumes.Count >= MaxLogicalVolumes || !this.ReadLogicalDescriptor(buffer))
                    {
                        return(false);
                    }

                    break;
                }

                location++;
            }

            // Did not find the terminating descriptor.  Not a valid image.
            return(false);
        }
Esempio n. 2
0
        /// <summary>
        /// Reads the file and directory structure from the image.
        /// </summary>
        /// <returns>Returns true if the file system is valid.</returns>
        private bool ReadFileStructure()
        {
            foreach (var volume in this.LogicalVolumes)
            {
                // Ensure the volume and parittion are valid.
                if (!this.ValidateVolumePartition(volume))
                {
                    return(false);
                }

                int volIndex = this.LogicalVolumes.IndexOf(volume);
                LongAllocationDescriptor nextExtent = volume.FileSetLocation;
                if (nextExtent.Length < VirtualSectorSize)
                {
                    return(false);
                }

                byte[] buffer = new byte[nextExtent.Length];
                this.ReadData(volIndex, nextExtent, buffer);
                VolumeTag tag = new VolumeTag();
                tag.Parse(0, buffer, buffer.Length);
                if (tag.Identifier != (int)VolumeDescriptorType.FileSet)
                {
                    return(false);
                }

                UdfFileSet fs = new UdfFileSet();
                fs.RecordingTime.Parse(16, buffer);
                fs.RootDirICB.Parse(400, buffer);
                volume.FileSet = fs;

                if (!this.ReadRecord(this.RootDirectory as UdfRecord, volIndex, fs.RootDirICB, MaxRecurseLevels))
                {
                    return(false);
                }
            }

            return(true);
        }
Esempio n. 3
0
        /// <summary>
        /// Reads the Anchor Volume pointer from the image.
        /// </summary>
        /// <returns>Returns true if the pointer was found.</returns>
        private UdfFileExtent ReadAnchorVolumePointer()
        {
            UdfFileExtent result = null;

            byte[] buffer = new byte[SectorSize];
            this.stream.Seek(-buffer.Length, (int)SeekOrigin.End, IntPtr.Zero);
            if (!this.stream.ReadSafe(buffer, buffer.Length))
            {
                return(result);
            }

            VolumeTag tag = new VolumeTag();

            if (tag.Parse(0, buffer, buffer.Length) &&
                tag.Identifier == (short)VolumeDescriptorType.AnchorVolumePtr)
            {
                result = new UdfFileExtent();
                result.Parse(16, buffer);
            }

            return(result);
        }
Esempio n. 4
0
        /// <summary>
        /// Reads the data from the image for a record.
        /// </summary>
        /// <param name="item">The item to read the data into.</param>
        /// <param name="volumeIndex">The index of the volume the file resides on.</param>
        /// <param name="lad">The long allocation descriptor of the file.</param>
        /// <param name="numRecurseAllowed">The number of recursions allowed before the method fails.</param>
        /// <returns>Returns true if the record was read successfully.</returns>
        private bool ReadRecordData(UdfRecord item, int volumeIndex, LongAllocationDescriptor lad, int numRecurseAllowed)
        {
            if (this.itemCount > MaxItems)
            {
                return(false);
            }

            LogicalVolume volume = this.LogicalVolumes[volumeIndex];

            if (lad.Length != volume.BlockSize)
            {
                return(false);
            }

            // Read the record.
            int size = lad.Length;

            byte[] buffer = new byte[size];
            if (!this.ReadData(volumeIndex, lad, buffer))
            {
                return(false);
            }

            // Validate the tag is a file.
            VolumeTag tag = new VolumeTag();

            tag.Parse(0, buffer, size);
            if (tag.Identifier != (short)VolumeDescriptorType.File)
            {
                return(false);
            }

            // Validate the IcbTage indicates file or directory.
            item.IcbTag.Parse(16, buffer);
            if (item.IcbTag.FileType != IcbFileType.Directory && item.IcbTag.FileType != IcbFileType.File)
            {
                return(false);
            }

            item.Parse(buffer);
            int extendedAttrLen     = UdfHelper.Get32(168, buffer);
            int allocDescriptorsLen = UdfHelper.Get32(172, buffer);

            if ((extendedAttrLen & 3) != 0)
            {
                return(false);
            }

            int position = 176;

            if (extendedAttrLen > size - position)
            {
                return(false);
            }

            position += extendedAttrLen;
            IcbDescriptorType desctType = item.IcbTag.DescriptorType;

            if (allocDescriptorsLen > size - position)
            {
                return(false);
            }

            if (desctType == IcbDescriptorType.Inline)
            {
                // If the file data is inline, read it in now since we have it.
                item.IsInline   = true;
                item.InlineData = UdfHelper.Readbytes(position, buffer, allocDescriptorsLen);
            }
            else
            {
                // Otherwise read the information about where the file is located for later.
                item.IsInline   = false;
                item.InlineData = new byte[0];
                if ((desctType != IcbDescriptorType.Short) && (desctType != IcbDescriptorType.Long))
                {
                    return(false);
                }

                for (int index = 0; index < allocDescriptorsLen;)
                {
                    FileExtent extent = new FileExtent();
                    if (desctType == IcbDescriptorType.Short)
                    {
                        if (index + 8 > allocDescriptorsLen)
                        {
                            return(false);
                        }

                        ShortAllocationDescriptor sad = new ShortAllocationDescriptor();
                        sad.Parse(position + index, buffer);
                        extent.Position           = sad.Position;
                        extent.Length             = sad.Length;
                        extent.PartitionReference = lad.Location.PartitionReference;
                        index += 8;
                    }
                    else
                    {
                        if (index + 16 > allocDescriptorsLen)
                        {
                            return(false);
                        }

                        LongAllocationDescriptor ladNew = new LongAllocationDescriptor();
                        ladNew.Parse(position + index, buffer);
                        extent.Position           = ladNew.Location.Position;
                        extent.PartitionReference = ladNew.Location.PartitionReference;
                        extent.Length             = ladNew.Length;
                        index += 16;
                    }

                    item.Extents.Add(extent);
                }
            }

            if (item.IcbTag.IsDirectory)
            {
                if (!item.CheckChunkSizes() || !this.CheckItemExtents(volumeIndex, item))
                {
                    return(false);
                }

                buffer = new byte[0];
                if (!this.ReadFromFile(volumeIndex, ref item, ref buffer))
                {
                    return(false);
                }

                item._size = 0;
                item.Extents.Clear();
                size = buffer.Length;
                int processedTotal = 0;
                int processedCur   = -1;
                while (processedTotal < size || processedCur == 0)
                {
                    UdfFileInformation fileId = new UdfFileInformation();
                    fileId.Parse(processedTotal, buffer, (size - processedTotal), ref processedCur);
                    if (!fileId.IsItLinkParent)
                    {
                        // Recursively read the contentst of the drirectory
                        UdfRecord fileItem = new UdfRecord();
                        fileItem.Id = fileId.Identifier;
                        if (fileItem.Id.Data != null)
                        {
                            this.fileNameLengthTotal += fileItem.Id.Data.Length;
                        }

                        if (this.fileNameLengthTotal > MaxFileNameLength)
                        {
                            return(false);
                        }

                        fileItem._Parent = item;
                        item.Subitems.Add(fileItem);
                        if (item.Subitems.Count > MaxFiles)
                        {
                            return(false);
                        }

                        this.ReadRecord(fileItem, volumeIndex, fileId.Icb, numRecurseAllowed);
                    }

                    processedTotal += processedCur;
                }
            }
            else
            {
                if (item.Extents.Count > MaxExtents - this.numExtents)
                {
                    return(false);
                }

                this.numExtents += item.Extents.Count;
                if (item.InlineData.Length > MaxInlineExtentsSize - this.inlineExtentsSize)
                {
                    return(false);
                }

                this.inlineExtentsSize += item.InlineData.Length;
            }

            this.itemCount++;
            return(true);
        }
Esempio n. 5
0
        /// <summary>
        /// Reads the volume descriptors for
        /// </summary>
        /// <param name="extentVds">The anchor volume extent information.</param>
        /// <returns>Returns true if the volume descriptors were read from the image successfully.</returns>
        private bool ReadVolumeDescriptors(UdfFileExtent extentVds)
        {
            byte[] buffer = new byte[SectorSize];

            long location = extentVds.Position;
            while (location < extentVds.Length && location < this.imageSize)
            {
                this.stream.Seek(location << SectorSizeLog, (int)SeekOrigin.Begin, IntPtr.Zero);
                if (!this.stream.ReadSafe(buffer, buffer.Length))
                {
                    return false;
                }

                VolumeTag tag = new VolumeTag();
                tag.Parse(0, buffer, buffer.Length);

                switch ((VolumeDescriptorType)tag.Identifier)
                {
                    case VolumeDescriptorType.Terminating:
                        // Found terminating descriptor.  Image is valid.
                        return true;
                    case VolumeDescriptorType.Partition:
                        if (this.Partitions.Count >= MaxPartitions)
                        {
                            return false;
                        }

                        this.ReadPartitionDescriptor(buffer);
                        break;
                    case VolumeDescriptorType.LogicalVolume:
                        if (this.LogicalVolumes.Count >= MaxLogicalVolumes || !this.ReadLogicalDescriptor(buffer))
                        {
                            return false;
                        }

                        break;
                }

                location++;
            }

            // Did not find the terminating descriptor.  Not a valid image.
            return false;
        }
Esempio n. 6
0
        /// <summary>
        /// Reads the data from the image for a record.
        /// </summary>
        /// <param name="item">The item to read the data into.</param>
        /// <param name="volumeIndex">The index of the volume the file resides on.</param>
        /// <param name="lad">The long allocation descriptor of the file.</param>
        /// <param name="numRecurseAllowed">The number of recursions allowed before the method fails.</param>
        /// <returns>Returns true if the record was read successfully.</returns>
        private bool ReadRecordData(UdfRecord item, int volumeIndex, LongAllocationDescriptor lad, int numRecurseAllowed)
        {
            if (this.itemCount > MaxItems)
            {
                return false;
            }

            LogicalVolume volume = this.LogicalVolumes[volumeIndex];
            if (lad.Length != volume.BlockSize)
            {
                return false;
            }

            // Read the record.
            int size = lad.Length;
            byte[] buffer = new byte[size];
            if (!this.ReadData(volumeIndex, lad, buffer))
            {
                return false;
            }

            // Validate the tag is a file.
            VolumeTag tag = new VolumeTag();
            tag.Parse(0, buffer, size);
            if (tag.Identifier != (short)VolumeDescriptorType.File)
            {
                return false;
            }

            // Validate the IcbTage indicates file or directory.
            item.IcbTag.Parse(16, buffer);
            if (item.IcbTag.FileType != IcbFileType.Directory && item.IcbTag.FileType != IcbFileType.File)
            {
                return false;
            }

            item.Parse(buffer);
            int extendedAttrLen = UdfHelper.Get32(168, buffer);
            int allocDescriptorsLen = UdfHelper.Get32(172, buffer);
            if ((extendedAttrLen & 3) != 0)
            {
                return false;
            }

            int position = 176;
            if (extendedAttrLen > size - position)
            {
                return false;
            }

            position += extendedAttrLen;
            IcbDescriptorType desctType = item.IcbTag.DescriptorType;
            if (allocDescriptorsLen > size - position)
            {
                return false;
            }

            if (desctType == IcbDescriptorType.Inline)
            {
                // If the file data is inline, read it in now since we have it.
                item.IsInline = true;
                item.InlineData = UdfHelper.Readbytes(position, buffer, allocDescriptorsLen);
            }
            else
            {
                // Otherwise read the information about where the file is located for later.
                item.IsInline = false;
                item.InlineData = new byte[0];
                if ((desctType != IcbDescriptorType.Short) && (desctType != IcbDescriptorType.Long))
                {
                    return false;
                }

                for (int index = 0; index < allocDescriptorsLen;)
                {
                    FileExtent extent = new FileExtent();
                    if (desctType == IcbDescriptorType.Short)
                    {
                        if (index + 8 > allocDescriptorsLen)
                        {
                            return false;
                        }

                        ShortAllocationDescriptor sad = new ShortAllocationDescriptor();
                        sad.Parse(position + index, buffer);
                        extent.Position = sad.Position;
                        extent.Length = sad.Length;
                        extent.PartitionReference = lad.Location.PartitionReference;
                        index += 8;
                    }
                    else
                    {
                        if (index + 16 > allocDescriptorsLen)
                        {
                            return false;
                        }

                        LongAllocationDescriptor ladNew = new LongAllocationDescriptor();
                        ladNew.Parse(position + index, buffer);
                        extent.Position = ladNew.Location.Position;
                        extent.PartitionReference = ladNew.Location.PartitionReference;
                        extent.Length = ladNew.Length;
                        index += 16;
                    }

                    item.Extents.Add(extent);
                }
            }

            if (item.IcbTag.IsDirectory)
            {
                if (!item.CheckChunkSizes() || !this.CheckItemExtents(volumeIndex, item))
                {
                    return false;
                }

                buffer = new byte[0];
                if (!this.ReadFromFile(volumeIndex, ref item, ref buffer))
                {
                    return false;
                }

                item._size = 0;
                item.Extents.Clear();
                size = buffer.Length;
                int processedTotal = 0;
                int processedCur = -1;
                while (processedTotal < size || processedCur == 0)
                {
                    UdfFileInformation fileId = new UdfFileInformation();
                    fileId.Parse(processedTotal, buffer, (size - processedTotal), ref processedCur);
                    if (!fileId.IsItLinkParent)
                    {
                        // Recursively read the contentst of the drirectory
                        UdfRecord fileItem = new UdfRecord();
                        fileItem.Id = fileId.Identifier;
                        if (fileItem.Id.Data != null)
                        {
                            this.fileNameLengthTotal += fileItem.Id.Data.Length;
                        }

                        if (this.fileNameLengthTotal > MaxFileNameLength)
                        {
                            return false;
                        }

                        fileItem._Parent = item;
                        item.Subitems.Add(fileItem);
                        if (item.Subitems.Count > MaxFiles)
                        {
                            return false;
                        }

                        this.ReadRecord(fileItem, volumeIndex, fileId.Icb, numRecurseAllowed);
                    }

                    processedTotal += processedCur;
                }
            }
            else
            {
                if (item.Extents.Count > MaxExtents - this.numExtents)
                {
                    return false;
                }

                this.numExtents += item.Extents.Count;
                if (item.InlineData.Length > MaxInlineExtentsSize - this.inlineExtentsSize)
                {
                    return false;
                }

                this.inlineExtentsSize += item.InlineData.Length;
            }

            this.itemCount++;
            return true;
        }
Esempio n. 7
0
        /// <summary>
        /// Reads the file and directory structure from the image.
        /// </summary>
        /// <returns>Returns true if the file system is valid.</returns>
        private bool ReadFileStructure()
        {
            foreach (var volume in this.LogicalVolumes)
            {
                // Ensure the volume and parittion are valid.
                if (!this.ValidateVolumePartition(volume))
                {
                    return false;
                }

                int volIndex = this.LogicalVolumes.IndexOf(volume);
                LongAllocationDescriptor nextExtent = volume.FileSetLocation;
                if (nextExtent.Length < VirtualSectorSize)
                {
                    return false;
                }

                byte[] buffer = new byte[nextExtent.Length];
                this.ReadData(volIndex, nextExtent, buffer);
                VolumeTag tag = new VolumeTag();
                tag.Parse(0, buffer, buffer.Length);
                if (tag.Identifier != (int)VolumeDescriptorType.FileSet)
                {
                    return false;
                }

                UdfFileSet fs = new UdfFileSet();
                fs.RecordingTime.Parse(16, buffer);
                fs.RootDirICB.Parse(400, buffer);
                volume.FileSet = fs;

                if (!this.ReadRecord(this.RootDirectory as UdfRecord, volIndex, fs.RootDirICB, MaxRecurseLevels))
                {
                    return false;
                }
            }

            return true;
        }
Esempio n. 8
0
        /// <summary>
        /// Reads the Anchor Volume pointer from the image.
        /// </summary>
        /// <returns>Returns true if the pointer was found.</returns>
        private UdfFileExtent ReadAnchorVolumePointer()
        {
            UdfFileExtent result = null;

            byte[] buffer = new byte[SectorSize];
            this.stream.Seek(-buffer.Length, (int)SeekOrigin.End, IntPtr.Zero);
            if (!this.stream.ReadSafe(buffer, buffer.Length))
            {
                return result;
            }

            VolumeTag tag = new VolumeTag();
            if (tag.Parse(0, buffer, buffer.Length)
                && tag.Identifier == (short)VolumeDescriptorType.AnchorVolumePtr)
            {
                result = new UdfFileExtent();
                result.Parse(16, buffer);
            }

            return result;
        }