Example #1
0
        /// <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, int sectorSize)
            : base(new DiscFileSystemOptions())
        {
            _data         = data;
            _sectorSize   = sectorSize;
            _hideVersions = hideVersions;

            long vdpos = _sectorSize * 16; // Skip lead-in

            byte[] buffer = new byte[_sectorSize];

            long pvdPos = 0;
            long svdPos = 0;

            BaseVolumeDescriptor bvd;

            do
            {
                data.Position = vdpos;
                int numRead = data.Read(buffer, 0, _sectorSize);
                if (numRead != _sectorSize)
                {
                    break;
                }

                var offset = 24;

                bvd = new BaseVolumeDescriptor(buffer, offset);

                if (bvd.StandardIdentifier != BaseVolumeDescriptor.Iso9660StandardIdentifier)
                {
                    throw new InvalidFileSystemException("Volume is not ISO-9660");
                }

                switch (bvd.VolumeDescriptorType)
                {
                case VolumeDescriptorType.Boot:
                    _bootVolDesc = new BootVolumeDescriptor(buffer, offset);
                    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 += _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, _sectorSize);
                        SupplementaryVolumeDescriptor volDesc = new SupplementaryVolumeDescriptor(buffer, 0);

                        Context = new IsoContext(_sectorSize)
                        {
                            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 + 24;
                        data.Read(buffer, 0, _sectorSize);
                        PrimaryVolumeDescriptor volDesc = new PrimaryVolumeDescriptor(buffer, 0);

                        volDesc.LogicalBlockSize = 2352;

                        IsoContext context = new IsoContext(_sectorSize)
                        {
                            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");
            }
        }