/// <summary> /// Detects if a stream contains a valid ISO file system. /// </summary> /// <param name="data">The stream to inspect</param> /// <returns><c>true</c> if the stream contains an ISO file system, else false.</returns> public static bool Detect(Stream data) { byte[] buffer = new byte[IsoUtilities.SectorSize]; if (data.Length < 0x8000 + IsoUtilities.SectorSize) { return false; } data.Position = 0x8000; int numRead = Utilities.ReadFully(data, buffer, 0, IsoUtilities.SectorSize); if (numRead != IsoUtilities.SectorSize) { return false; } BaseVolumeDescriptor bvd = new BaseVolumeDescriptor(buffer, 0); return bvd.StandardIdentifier == "CD001"; }
/// <summary> /// Detects if a stream contains a valid ISO file system. /// </summary> /// <param name="data">The stream to inspect</param> /// <returns><c>true</c> if the stream contains an ISO file system, else false.</returns> public static bool Detect(Stream data) { byte[] buffer = new byte[IsoUtilities.SectorSize]; if (data.Length < 0x8000 + IsoUtilities.SectorSize) { return(false); } data.Position = 0x8000; int numRead = Utilities.ReadFully(data, buffer, 0, IsoUtilities.SectorSize); if (numRead != IsoUtilities.SectorSize) { return(false); } BaseVolumeDescriptor bvd = new BaseVolumeDescriptor(buffer, 0); return(bvd.StandardIdentifier == "CD001"); }
/// <summary> /// Detects if a stream contains a valid ISO file system. /// </summary> /// <param name="data">The stream to inspect.</param> /// <returns><c>true</c> if the stream contains an ISO file system, else false.</returns> public static bool Detect(Stream data, int sectorSize) { byte[] buffer = new byte[sectorSize]; if (data.Length < 0x8000 + sectorSize) { return(false); } data.Position = 0x8000; int numRead = StreamUtilities.ReadMaximum(data, buffer, 0, sectorSize); if (numRead != sectorSize) { return(false); } BaseVolumeDescriptor bvd = new BaseVolumeDescriptor(buffer, 0); return(bvd.StandardIdentifier == BaseVolumeDescriptor.Iso9660StandardIdentifier); }
/// <summary> /// Initializes a new instance of the VfsCDReader class. /// </summary> /// <param name="data">The stream to read the ISO image from.</param> /// <param name="variantPriorities">Which possible file system variants to use, and with which priority.</param> /// <param name="hideVersions">Hides version numbers (e.g. ";1") from the end of files.</param> /// <remarks> /// <para> /// The implementation considers each of the file system variants in <c>variantProperties</c> and selects /// the first which is determined to be present. In this example Joliet, then Rock Ridge, then vanilla /// Iso9660 will be considered: /// </para> /// <code lang="cs"> /// VfsCDReader(stream, new Iso9660Variant[] {Joliet, RockRidge, Iso9660}, true); /// </code> /// <para>The Iso9660 variant should normally be specified as the final entry in the list. Placing it earlier /// in the list will effectively mask later items and not including it may prevent some ISOs from being read.</para> /// </remarks> public VfsCDReader(Stream data, Iso9660Variant[] variantPriorities, bool hideVersions) : base(new DiscFileSystemOptions()) { _data = data; _hideVersions = hideVersions; long vdpos = 0x8000; // Skip lead-in byte[] buffer = new byte[IsoUtilities.SectorSize]; long pvdPos = 0; long svdPos = 0; BaseVolumeDescriptor bvd; do { data.Position = vdpos; int numRead = data.Read(buffer, 0, IsoUtilities.SectorSize); if (numRead != IsoUtilities.SectorSize) { break; } bvd = new BaseVolumeDescriptor(buffer, 0); if (bvd.StandardIdentifier != BaseVolumeDescriptor.Iso9660StandardIdentifier) { throw new InvalidFileSystemException("Volume is not ISO-9660"); } switch (bvd.VolumeDescriptorType) { case VolumeDescriptorType.Boot: _bootVolDesc = new BootVolumeDescriptor(buffer, 0); if (_bootVolDesc.SystemId != BootVolumeDescriptor.ElToritoSystemIdentifier) { _bootVolDesc = null; } break; case VolumeDescriptorType.Primary: // Primary Vol Descriptor pvdPos = vdpos; break; case VolumeDescriptorType.Supplementary: // Supplementary Vol Descriptor svdPos = vdpos; break; case VolumeDescriptorType.Partition: // Volume Partition Descriptor break; case VolumeDescriptorType.SetTerminator: // Volume Descriptor Set Terminator break; } vdpos += IsoUtilities.SectorSize; } while (bvd.VolumeDescriptorType != VolumeDescriptorType.SetTerminator); ActiveVariant = Iso9660Variant.None; foreach (Iso9660Variant variant in variantPriorities) { switch (variant) { case Iso9660Variant.Joliet: if (svdPos != 0) { data.Position = svdPos; data.Read(buffer, 0, IsoUtilities.SectorSize); SupplementaryVolumeDescriptor volDesc = new SupplementaryVolumeDescriptor(buffer, 0); Context = new IsoContext { VolumeDescriptor = volDesc, DataStream = _data }; RootDirectory = new ReaderDirectory(Context, new ReaderDirEntry(Context, volDesc.RootDirectory)); ActiveVariant = Iso9660Variant.Iso9660; } break; case Iso9660Variant.RockRidge: case Iso9660Variant.Iso9660: if (pvdPos != 0) { data.Position = pvdPos; data.Read(buffer, 0, IsoUtilities.SectorSize); PrimaryVolumeDescriptor volDesc = new PrimaryVolumeDescriptor(buffer, 0); IsoContext context = new IsoContext { VolumeDescriptor = volDesc, DataStream = _data }; DirectoryRecord rootSelfRecord = ReadRootSelfRecord(context); InitializeSusp(context, rootSelfRecord); if (variant == Iso9660Variant.Iso9660 || (variant == Iso9660Variant.RockRidge && !string.IsNullOrEmpty(context.RockRidgeIdentifier))) { Context = context; RootDirectory = new ReaderDirectory(context, new ReaderDirEntry(context, rootSelfRecord)); ActiveVariant = variant; } } break; } if (ActiveVariant != Iso9660Variant.None) { break; } } if (ActiveVariant == Iso9660Variant.None) { throw new IOException("None of the permitted ISO9660 file system variants was detected"); } }
/// <summary> /// Initializes a new instance of the VfsCDReader class. /// </summary> /// <param name="data">The stream to read the ISO image from.</param> /// <param name="variantPriorities">Which possible file system variants to use, and with which priority</param> /// <param name="hideVersions">Hides version numbers (e.g. ";1") from the end of files</param> /// <remarks> /// <para> /// The implementation considers each of the file system variants in <c>variantProperties</c> and selects /// the first which is determined to be present. In this example Joliet, then Rock Ridge, then vanilla /// Iso9660 will be considered: /// </para> /// <code lang="cs"> /// VfsCDReader(stream, new Iso9660Variant[] {Joliet, RockRidge, Iso9660}, true); /// </code> /// <para>The Iso9660 variant should normally be specified as the final entry in the list. Placing it earlier /// in the list will effectively mask later items and not including it may prevent some ISOs from being read.</para> /// </remarks> private VfsCDReader(Stream data, IEnumerable <Iso9660Variant> variantPriorities, bool hideVersions) { _data = data; _hideVersions = hideVersions; long vdpos = 0x8000; // Skip lead-in byte[] buffer = new byte[IsoUtilities.SectorSize]; long pvdPos = 0; long svdPos = 0; BaseVolumeDescriptor bvd; do { data.Position = vdpos; int numRead = data.Read(buffer, 0, IsoUtilities.SectorSize); if (numRead != IsoUtilities.SectorSize) { break; } bvd = new BaseVolumeDescriptor(buffer, 0); switch (bvd.VolumeDescriptorType) { case VolumeDescriptorType.Primary: // Primary Vol Descriptor pvdPos = vdpos; break; case VolumeDescriptorType.Supplementary: // Supplementary Vol Descriptor svdPos = vdpos; break; case VolumeDescriptorType.Partition: // Volume Partition Descriptor break; case VolumeDescriptorType.SetTerminator: // Volume Descriptor Set Terminator break; } vdpos += IsoUtilities.SectorSize; }while (bvd.VolumeDescriptorType != VolumeDescriptorType.SetTerminator); _activeVariant = Iso9660Variant.None; foreach (var variant in variantPriorities) { switch (variant) { case Iso9660Variant.Joliet: if (svdPos != 0) { data.Position = svdPos; data.Read(buffer, 0, IsoUtilities.SectorSize); var volDesc = new SupplementaryVolumeDescriptor(buffer, 0); Context = new IsoContext { VolumeDescriptor = volDesc, DataStream = _data }; RootDirectory = new ReaderDirectory(Context, new ReaderDirEntry(null, volDesc.RootDirectory)); _activeVariant = Iso9660Variant.Iso9660; } break; case Iso9660Variant.RockRidge: case Iso9660Variant.Iso9660: if (pvdPos != 0) { data.Position = pvdPos; data.Read(buffer, 0, IsoUtilities.SectorSize); var volDesc = new PrimaryVolumeDescriptor(buffer, 0); IsoContext context = new IsoContext { VolumeDescriptor = volDesc, DataStream = _data }; DirectoryRecord rootSelfRecord = ReadRootSelfRecord(context); if (variant == Iso9660Variant.Iso9660) { Context = context; RootDirectory = new ReaderDirectory(context, new ReaderDirEntry(null, rootSelfRecord)); _activeVariant = variant; } } break; } if (_activeVariant != Iso9660Variant.None) { break; } } if (_activeVariant == Iso9660Variant.None) { throw new IOException("None of the permitted ISO9660 file system variants was detected"); } }
/// <summary> /// Initializes a new instance of the VfsCDReader class. /// </summary> /// <param name="data">The stream to read the ISO image from.</param> /// <param name="joliet">Whether to read Joliet extensions.</param> /// <param name="hideVersions">Hides version numbers (e.g. ";1") from the end of files</param> public VfsCDReader(Stream data, bool joliet, bool hideVersions) : base(new DiscFileSystemOptions()) { _data = data; _hideVersions = hideVersions; long vdpos = 0x8000; // Skip lead-in byte[] buffer = new byte[IsoUtilities.SectorSize]; long pvdPos = 0; long svdPos = 0; BaseVolumeDescriptor bvd; do { data.Position = vdpos; int numRead = data.Read(buffer, 0, IsoUtilities.SectorSize); if (numRead != IsoUtilities.SectorSize) { break; } bvd = new BaseVolumeDescriptor(buffer, 0); switch (bvd.VolumeDescriptorType) { case VolumeDescriptorType.Boot: _bootVolDesc = new BootVolumeDescriptor(buffer, 0); if (_bootVolDesc.SystemId != BootVolumeDescriptor.ElToritoSystemIdentifier) { _bootVolDesc = null; } break; case VolumeDescriptorType.Primary: // Primary Vol Descriptor pvdPos = vdpos; break; case VolumeDescriptorType.Supplementary: // Supplementary Vol Descriptor svdPos = vdpos; break; case VolumeDescriptorType.Partition: // Volume Partition Descriptor break; case VolumeDescriptorType.SetTerminator: // Volume Descriptor Set Terminator break; } vdpos += IsoUtilities.SectorSize; }while (bvd.VolumeDescriptorType != VolumeDescriptorType.SetTerminator); CommonVolumeDescriptor volDesc; if (joliet && svdPos != 0) { data.Position = svdPos; data.Read(buffer, 0, IsoUtilities.SectorSize); volDesc = new SupplementaryVolumeDescriptor(buffer, 0); } else { data.Position = pvdPos; data.Read(buffer, 0, IsoUtilities.SectorSize); volDesc = new PrimaryVolumeDescriptor(buffer, 0); } Context = new IsoContext { VolumeDescriptor = volDesc, DataStream = _data }; RootDirectory = new ReaderDirectory(Context, volDesc.RootDirectory); }