136 lines
4.5 KiB
C#
136 lines
4.5 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using System.IO;
|
|
|
|
namespace ISOParser {
|
|
/// <summary>
|
|
/// This class is meant to parse disk images as specified by ISO9660.
|
|
/// Specifically, it should work for most disk images that are created
|
|
/// by the stanard disk imaging software. This class is by no means
|
|
/// robust to all variations of ISO9660.
|
|
/// Also, this class does not currently support the UDF file system.
|
|
///
|
|
/// TODO: Add functions to enumerate a directory or visit a file...
|
|
///
|
|
/// The information for building class came from three primary sources:
|
|
/// 1. The ISO9660 wikipedia article:
|
|
/// http://en.wikipedia.org/wiki/ISO_9660
|
|
/// 2. ISO9660 Simplified for DOS/Windows
|
|
/// http://alumnus.caltech.edu/~pje/iso9660.html
|
|
/// 3. The ISO 9660 File System
|
|
/// http://users.telenet.be/it3.consultants.bvba/handouts/ISO9960.html
|
|
/// </summary>
|
|
public class ISOFile {
|
|
#region Constants
|
|
|
|
/// <summary>
|
|
/// We are hard coding the SECTOR_SIZE
|
|
/// </summary>
|
|
public const int SECTOR_SIZE = 2048;
|
|
|
|
#endregion
|
|
|
|
#region Public Members
|
|
|
|
/// <summary>
|
|
/// This is a list of all the volume descriptors in the disk image.
|
|
/// NOTE: The first entry should be the primary volume.
|
|
/// </summary>
|
|
public List<ISOVolumeDescriptor> VolumeDescriptors;
|
|
|
|
/// <summary>
|
|
/// The Directory that is the root of this file system
|
|
/// </summary>
|
|
public ISODirectoryNode Root;
|
|
|
|
#endregion
|
|
|
|
#region Construction
|
|
|
|
/// <summary>
|
|
/// Construct the ISO file data structures, but leave everything
|
|
/// blank.
|
|
/// </summary>
|
|
public ISOFile() {
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Parsing
|
|
|
|
/// <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;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Printing
|
|
|
|
/// <summary>
|
|
/// Print the directory tree for the image.
|
|
/// </summary>
|
|
public void Print() {
|
|
// DEBUGGING: Now print out the directory structure
|
|
this.Root.Print(0);
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|