/// <summary> /// Reads a logical volume descriptor from the buffer. /// </summary> /// <param name="buffer">The buffer to read the data from.</param> /// <returns>Returns true if the descriptor is valid.</returns> private bool ReadLogicalDescriptor(byte[] buffer) { LogicalVolume volume = new LogicalVolume(); volume.Id.Parse(84, buffer); volume.BlockSize = UdfHelper.Get32(212, buffer); if (volume.BlockSize < VirtualSectorSize || volume.BlockSize > MaxExtents) { return(false); } volume.FileSetLocation.Parse(248, buffer); int numPartitionMaps = UdfHelper.Get32(268, buffer); if (numPartitionMaps > MaxPartitions) { return(false); } int position = 440; for (int index = 0; index < numPartitionMaps; index++) { if (position + 2 > SectorSize) { return(false); } PartitionMap pm = new PartitionMap(); pm.Type = buffer[position]; byte length = buffer[position + 1]; if (position + length > SectorSize) { return(false); } if (pm.Type == 1) { if (position + 6 > SectorSize) { return(false); } pm.PartitionNumber = UdfHelper.Get16(position + 4, buffer); } else { return(false); } position += length; pm.PartitionIndex = volume.PartitionMaps.Count; volume.PartitionMaps.Add(pm); } this.LogicalVolumes.Add(volume); return(true); }
/// <summary> /// Reads a partition descriptor from the buffer. /// </summary> /// <param name="buffer">The buffer to read the partition data from.</param> private void ReadPartitionDescriptor(byte[] buffer) { var partition = new Partition { Number = UdfHelper.Get16(22, buffer), Position = UdfHelper.Get32(188, buffer), Length = UdfHelper.Get32(192, buffer) }; this.Partitions.Add(partition); }
/// <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); }