/// <summary> /// Parse the given stream to populate the iso information /// </summary> /// <param name="s">The stream which we are using to parse the image. /// Should already be located at the start of the image.</param> public bool Parse(Stream s, int startSector = 16) { this.VolumeDescriptors = new List <ISOVolumeDescriptor>(); Root = null; long startPosition = s.Position; byte[] buffer = new byte[ISOFile.SECTOR_SIZE]; // Seek through the first volume descriptor s.Seek(startPosition + (SECTOR_SIZE * startSector), SeekOrigin.Begin); // Read one of more volume descriptors do { //zero 24-jun-2013 - improved validity checks ISOVolumeDescriptor desc = new ISOVolumeDescriptor(); bool isValid = desc.Parse(s); if (!isValid) { return(false); } if (desc.IsTerminator()) { break; } else if (desc.Type < 4) { this.VolumeDescriptors.Add(desc); } else { //found a volume descriptor of incorrect type.. maybe this isnt a cdfs //supposedly these exist.. wait for one to show up return(false); } } while (true); //zero 24-jun-2013 - well, my very first test iso had 2 volume descriptors. // Check to make sure we only read one volume descriptor // Finding more could be an error with the disk. //if (this.VolumeDescriptors.Count != 1) { // Console.WriteLine("Strange ISO format..."); // return; //} //zero 24-jun-2013 - if theres no volume descriptors, we're gonna call this not a cdfs if (VolumeDescriptors.Count == 0) { return(false); } // Visit all the directories and get the offset of each directory/file // We need to keep track of the directories and files we have visited in case there are loops. Dictionary <long, ISONode> visitedNodes = new Dictionary <long, ISONode>(); // Create (and visit) the root node this.Root = new ISODirectoryNode(this.VolumeDescriptors[0].RootDirectoryRecord); visitedNodes.Add(this.Root.Offset, this.Root); this.Root.Parse(s, visitedNodes); return(true); }
/// <summary> /// Parse the children based on the data in this directory. /// </summary> /// <param name="s">The stream to parse from.</param> /// <param name="visited">The set of already handled /// files/directories.</param> public void Parse(Stream s, Dictionary <long, ISONode> visited) { // Go to the beginning of the set of directories s.Seek(this.Offset * ISOFile.SECTOR_SIZE, SeekOrigin.Begin); List <ISONodeRecord> records = new List <ISONodeRecord>(); // Read the directory entries while (s.Position < ((this.Offset * ISOFile.SECTOR_SIZE) + this.Length)) { ISONode node; ISONodeRecord record; // Read the record record = new ISONodeRecord(); record.Parse(s); //zero 24-jun-2013 - improved validity checks //theres nothing here! if (record.Length == 0) { break; } else { // Check if we already have this node if (visited.ContainsKey(record.OffsetOfData)) { // Get the node node = visited[record.OffsetOfData]; } else { // Create the node from the record if (record.IsFile()) { node = new ISOFileNode(record); } else if (record.IsDirectory()) { node = new ISODirectoryNode(record); } else { node = new ISONode(record); } // Keep track that we've now seen the node and are parsing it visited.Add(node.Offset, node); } // Add the node as a child this.Children.Add(record.Name, node); } } long currentPosition = s.Position; // Iterate over directories... foreach (KeyValuePair <string, ISONode> child in this.Children) { // Parse this node if (child.Key != ISONodeRecord.CURRENT_DIRECTORY && child.Key != ISONodeRecord.PARENT_DIRECTORY && child.Value is ISODirectoryNode) { ((ISODirectoryNode)child.Value).Parse(s, visited); } } s.Seek(currentPosition, SeekOrigin.Begin); }