public SupplementaryVolumeDescriptorRegion(SupplementaryVolumeDescriptor descriptor, long start)
     : base(start)
 {
     _descriptor = descriptor;
 }
Beispiel #2
0
        protected override List <BuilderExtent> FixExtents(out long totalLength)
        {
            List <BuilderExtent> fixedRegions = new List <BuilderExtent>();

            DateTime buildTime = DateTime.UtcNow;

            Encoding suppEncoding = _buildParams.UseJoliet ? Encoding.BigEndianUnicode : Encoding.ASCII;

            Dictionary <BuildDirectoryMember, uint> primaryLocationTable       = new Dictionary <BuildDirectoryMember, uint>();
            Dictionary <BuildDirectoryMember, uint> supplementaryLocationTable =
                new Dictionary <BuildDirectoryMember, uint>();

            long focus = DiskStart + 3 * _buildParams.SectorSize; // Primary, Supplementary, End (fixed at end...)

            if (_bootEntry != null)
            {
                focus += _buildParams.SectorSize;
            }

            // ####################################################################
            // # 0. Fix boot image location
            // ####################################################################
            long bootCatalogPos = 0;

            if (_bootEntry != null)
            {
                long   bootImagePos  = focus;
                Stream realBootImage = PatchBootImage(_bootImage, (uint)(DiskStart / _buildParams.SectorSize),
                                                      (uint)(bootImagePos / _buildParams.SectorSize));
                BuilderStreamExtent bootImageExtent = new BuilderStreamExtent(focus, realBootImage);
                fixedRegions.Add(bootImageExtent);
                focus += MathUtilities.RoundUp(bootImageExtent.Length, _buildParams.SectorSize);

                bootCatalogPos = focus;
                byte[] bootCatalog      = new byte[_buildParams.SectorSize];
                BootValidationEntry bve = new BootValidationEntry();
                bve.WriteTo(bootCatalog, 0x00);
                _bootEntry.ImageStart  = (uint)MathUtilities.Ceil(bootImagePos, _buildParams.SectorSize);
                _bootEntry.SectorCount = (ushort)MathUtilities.Ceil(_bootImage.Length, Sizes.Sector);
                _bootEntry.WriteTo(bootCatalog, 0x20);
                fixedRegions.Add(new BuilderBufferExtent(bootCatalogPos, bootCatalog));
                focus += _buildParams.SectorSize;
            }

            // ####################################################################
            // # 1. Fix file locations
            // ####################################################################

            // Find end of the file data, fixing the files in place as we go
            foreach (BuildFileInfo fi in _files)
            {
                primaryLocationTable.Add(fi, (uint)(focus / _buildParams.SectorSize));
                supplementaryLocationTable.Add(fi, (uint)(focus / _buildParams.SectorSize));
                FileExtent extent = new FileExtent(fi, focus);

                // Only remember files of non-zero length (otherwise we'll stomp on a valid file)
                if (extent.Length != 0)
                {
                    fixedRegions.Add(extent);
                }

                focus += MathUtilities.RoundUp(extent.Length, _buildParams.SectorSize);
            }

            // ####################################################################
            // # 2. Fix directory locations
            // ####################################################################

            // There are two directory tables
            //  1. Primary        (std ISO9660)
            //  2. Supplementary  (Joliet)

            // Find start of the second set of directory data, fixing ASCII directories in place.
            long startOfFirstDirData = focus;

            foreach (BuildDirectoryInfo di in _dirs)
            {
                primaryLocationTable.Add(di, (uint)(focus / _buildParams.SectorSize));
                DirectoryExtent extent = new DirectoryExtent(di, primaryLocationTable, Encoding.ASCII, focus);
                fixedRegions.Add(extent);
                focus += MathUtilities.RoundUp(extent.Length, _buildParams.SectorSize);
            }

            // Find end of the second directory table, fixing supplementary directories in place.
            long startOfSecondDirData = focus;

            foreach (BuildDirectoryInfo di in _dirs)
            {
                supplementaryLocationTable.Add(di, (uint)(focus / _buildParams.SectorSize));
                DirectoryExtent extent = new DirectoryExtent(di, supplementaryLocationTable, suppEncoding, focus);
                fixedRegions.Add(extent);
                focus += MathUtilities.RoundUp(extent.Length, _buildParams.SectorSize);
            }

            // ####################################################################
            // # 3. Fix path tables
            // ####################################################################

            // There are four path tables:
            //  1. LE, ASCII
            //  2. BE, ASCII
            //  3. LE, Supp Encoding (Joliet)
            //  4. BE, Supp Encoding (Joliet)

            // Find end of the path table
            long      startOfFirstPathTable = focus;
            PathTable pathTable             = new PathTable(false, Encoding.ASCII, _dirs, primaryLocationTable, focus);

            fixedRegions.Add(pathTable);
            focus += MathUtilities.RoundUp(pathTable.Length, _buildParams.SectorSize);
            long primaryPathTableLength = pathTable.Length;

            long startOfSecondPathTable = focus;

            pathTable = new PathTable(true, Encoding.ASCII, _dirs, primaryLocationTable, focus);
            fixedRegions.Add(pathTable);
            focus += MathUtilities.RoundUp(pathTable.Length, _buildParams.SectorSize);

            long startOfThirdPathTable = focus;

            pathTable = new PathTable(false, suppEncoding, _dirs, supplementaryLocationTable, focus);
            fixedRegions.Add(pathTable);
            focus += MathUtilities.RoundUp(pathTable.Length, _buildParams.SectorSize);
            long supplementaryPathTableLength = pathTable.Length;

            long startOfFourthPathTable = focus;

            pathTable = new PathTable(true, suppEncoding, _dirs, supplementaryLocationTable, focus);
            fixedRegions.Add(pathTable);
            focus += MathUtilities.RoundUp(pathTable.Length, _buildParams.SectorSize);

            // Find the end of the disk
            totalLength = focus;

            // ####################################################################
            // # 4. Prepare volume descriptors now other structures are fixed
            // ####################################################################
            int regionIdx = 0;

            focus = DiskStart;
            PrimaryVolumeDescriptor pvDesc = new PrimaryVolumeDescriptor(
                (uint)(totalLength / _buildParams.SectorSize),            // VolumeSpaceSize
                (uint)primaryPathTableLength,                             // PathTableSize
                (uint)(startOfFirstPathTable / _buildParams.SectorSize),  // TypeLPathTableLocation
                (uint)(startOfSecondPathTable / _buildParams.SectorSize), // TypeMPathTableLocation
                (uint)(startOfFirstDirData / _buildParams.SectorSize),    // RootDirectory.LocationOfExtent
                (uint)_rootDirectory.GetDataSize(Encoding.ASCII),         // RootDirectory.DataLength
                buildTime,
                _sectorSize);

            pvDesc.VolumeIdentifier = _buildParams.VolumeIdentifier;
            PrimaryVolumeDescriptorRegion pvdr = new PrimaryVolumeDescriptorRegion(pvDesc, focus, _sectorSize);

            fixedRegions.Insert(regionIdx++, pvdr);
            focus += _buildParams.SectorSize;

            if (_bootEntry != null)
            {
                BootVolumeDescriptor bvDesc = new BootVolumeDescriptor(
                    (uint)(bootCatalogPos / _buildParams.SectorSize), _buildParams.SectorSize);
                BootVolumeDescriptorRegion bvdr = new BootVolumeDescriptorRegion(bvDesc, focus, _buildParams.SectorSize);
                fixedRegions.Insert(regionIdx++, bvdr);
                focus += _buildParams.SectorSize;
            }

            SupplementaryVolumeDescriptor svDesc = new SupplementaryVolumeDescriptor(
                (uint)(totalLength / _buildParams.SectorSize),            // VolumeSpaceSize
                (uint)supplementaryPathTableLength,                       // PathTableSize
                (uint)(startOfThirdPathTable / _buildParams.SectorSize),  // TypeLPathTableLocation
                (uint)(startOfFourthPathTable / _buildParams.SectorSize), // TypeMPathTableLocation
                (uint)(startOfSecondDirData / _buildParams.SectorSize),   // RootDirectory.LocationOfExtent
                (uint)_rootDirectory.GetDataSize(suppEncoding),           // RootDirectory.DataLength
                buildTime,
                suppEncoding,
                _sectorSize);

            svDesc.VolumeIdentifier = _buildParams.VolumeIdentifier;
            SupplementaryVolumeDescriptorRegion svdr = new SupplementaryVolumeDescriptorRegion(svDesc, focus, _sectorSize);

            fixedRegions.Insert(regionIdx++, svdr);
            focus += _buildParams.SectorSize;

            VolumeDescriptorSetTerminator       evDesc = new VolumeDescriptorSetTerminator(_sectorSize);
            VolumeDescriptorSetTerminatorRegion evdr   = new VolumeDescriptorSetTerminatorRegion(evDesc, focus, _sectorSize);

            fixedRegions.Insert(regionIdx++, evdr);

            return(fixedRegions);
        }
        internal override List<BuilderExtent> FixExtents(out long totalLength)
        {
            List<BuilderExtent> fixedRegions = new List<BuilderExtent>();

            DateTime buildTime = DateTime.UtcNow;

            Encoding suppEncoding = _buildParams.UseJoliet ? Encoding.BigEndianUnicode : Encoding.ASCII;

            Dictionary<BuildDirectoryMember, uint> primaryLocationTable = new Dictionary<BuildDirectoryMember, uint>();
            Dictionary<BuildDirectoryMember, uint> supplementaryLocationTable = new Dictionary<BuildDirectoryMember, uint>();

            long focus = DiskStart + (3 * IsoUtilities.SectorSize); // Primary, Supplementary, End (fixed at end...)
            if (_bootEntry != null)
            {
                focus += IsoUtilities.SectorSize;
            }

            // ####################################################################
            // # 0. Fix boot image location
            // ####################################################################
            long bootCatalogPos = 0;
            if (_bootEntry != null)
            {
                long bootImagePos = focus;
                Stream realBootImage = PatchBootImage(_bootImage, (uint)(DiskStart / IsoUtilities.SectorSize), (uint)(bootImagePos / IsoUtilities.SectorSize));
                BuilderStreamExtent bootImageExtent = new BuilderStreamExtent(focus, realBootImage);
                fixedRegions.Add(bootImageExtent);
                focus += Utilities.RoundUp(bootImageExtent.Length, IsoUtilities.SectorSize);

                bootCatalogPos = focus;
                byte[] bootCatalog = new byte[IsoUtilities.SectorSize];
                BootValidationEntry bve = new BootValidationEntry();
                bve.WriteTo(bootCatalog, 0x00);
                _bootEntry.ImageStart = (uint)Utilities.Ceil(bootImagePos, IsoUtilities.SectorSize);
                _bootEntry.SectorCount = (ushort)Utilities.Ceil(_bootImage.Length, Sizes.Sector);
                _bootEntry.WriteTo(bootCatalog, 0x20);
                fixedRegions.Add(new BuilderBufferExtent(bootCatalogPos, bootCatalog));
                focus += IsoUtilities.SectorSize;
            }

            // ####################################################################
            // # 1. Fix file locations
            // ####################################################################

            // Find end of the file data, fixing the files in place as we go
            foreach (BuildFileInfo fi in _files)
            {
                primaryLocationTable.Add(fi, (uint)(focus / IsoUtilities.SectorSize));
                supplementaryLocationTable.Add(fi, (uint)(focus / IsoUtilities.SectorSize));
                FileExtent extent = new FileExtent(fi, focus);

                // Only remember files of non-zero length (otherwise we'll stomp on a valid file)
                if (extent.Length != 0)
                {
                    fixedRegions.Add(extent);
                }

                focus += Utilities.RoundUp(extent.Length, IsoUtilities.SectorSize);
            }

            // ####################################################################
            // # 2. Fix directory locations
            // ####################################################################

            // There are two directory tables
            //  1. Primary        (std ISO9660)
            //  2. Supplementary  (Joliet)

            // Find start of the second set of directory data, fixing ASCII directories in place.
            long startOfFirstDirData = focus;
            foreach (BuildDirectoryInfo di in _dirs)
            {
                primaryLocationTable.Add(di, (uint)(focus / IsoUtilities.SectorSize));
                DirectoryExtent extent = new DirectoryExtent(di, primaryLocationTable, Encoding.ASCII, focus);
                fixedRegions.Add(extent);
                focus += Utilities.RoundUp(extent.Length, IsoUtilities.SectorSize);
            }

            // Find end of the second directory table, fixing supplementary directories in place.
            long startOfSecondDirData = focus;
            foreach (BuildDirectoryInfo di in _dirs)
            {
                supplementaryLocationTable.Add(di, (uint)(focus / IsoUtilities.SectorSize));
                DirectoryExtent extent = new DirectoryExtent(di, supplementaryLocationTable, suppEncoding, focus);
                fixedRegions.Add(extent);
                focus += Utilities.RoundUp(extent.Length, IsoUtilities.SectorSize);
            }

            // ####################################################################
            // # 3. Fix path tables
            // ####################################################################

            // There are four path tables:
            //  1. LE, ASCII
            //  2. BE, ASCII
            //  3. LE, Supp Encoding (Joliet)
            //  4. BE, Supp Encoding (Joliet)

            // Find end of the path table
            long startOfFirstPathTable = focus;
            PathTable pathTable = new PathTable(false, Encoding.ASCII, _dirs, primaryLocationTable, focus);
            fixedRegions.Add(pathTable);
            focus += Utilities.RoundUp(pathTable.Length, IsoUtilities.SectorSize);
            long primaryPathTableLength = pathTable.Length;

            long startOfSecondPathTable = focus;
            pathTable = new PathTable(true, Encoding.ASCII, _dirs, primaryLocationTable, focus);
            fixedRegions.Add(pathTable);
            focus += Utilities.RoundUp(pathTable.Length, IsoUtilities.SectorSize);

            long startOfThirdPathTable = focus;
            pathTable = new PathTable(false, suppEncoding, _dirs, supplementaryLocationTable, focus);
            fixedRegions.Add(pathTable);
            focus += Utilities.RoundUp(pathTable.Length, IsoUtilities.SectorSize);
            long supplementaryPathTableLength = pathTable.Length;

            long startOfFourthPathTable = focus;
            pathTable = new PathTable(true, suppEncoding, _dirs, supplementaryLocationTable, focus);
            fixedRegions.Add(pathTable);
            focus += Utilities.RoundUp(pathTable.Length, IsoUtilities.SectorSize);

            // Find the end of the disk
            totalLength = focus;

            // ####################################################################
            // # 4. Prepare volume descriptors now other structures are fixed
            // ####################################################################
            int regionIdx = 0;
            focus = DiskStart;
            PrimaryVolumeDescriptor pvDesc = new PrimaryVolumeDescriptor(
                (uint)(totalLength / IsoUtilities.SectorSize),             // VolumeSpaceSize
                (uint)primaryPathTableLength,                              // PathTableSize
                (uint)(startOfFirstPathTable / IsoUtilities.SectorSize),   // TypeLPathTableLocation
                (uint)(startOfSecondPathTable / IsoUtilities.SectorSize),  // TypeMPathTableLocation
                (uint)(startOfFirstDirData / IsoUtilities.SectorSize),     // RootDirectory.LocationOfExtent
                (uint)_rootDirectory.GetDataSize(Encoding.ASCII),          // RootDirectory.DataLength
                buildTime);
            pvDesc.VolumeIdentifier = _buildParams.VolumeIdentifier;
            PrimaryVolumeDescriptorRegion pvdr = new PrimaryVolumeDescriptorRegion(pvDesc, focus);
            fixedRegions.Insert(regionIdx++, pvdr);
            focus += IsoUtilities.SectorSize;

            if (_bootEntry != null)
            {
                BootVolumeDescriptor bvDesc = new BootVolumeDescriptor(
                    (uint)(bootCatalogPos / IsoUtilities.SectorSize));
                BootVolumeDescriptorRegion bvdr = new BootVolumeDescriptorRegion(bvDesc, focus);
                fixedRegions.Insert(regionIdx++, bvdr);
                focus += IsoUtilities.SectorSize;
            }

            SupplementaryVolumeDescriptor svDesc = new SupplementaryVolumeDescriptor(
                (uint)(totalLength / IsoUtilities.SectorSize),             // VolumeSpaceSize
                (uint)supplementaryPathTableLength,                        // PathTableSize
                (uint)(startOfThirdPathTable / IsoUtilities.SectorSize),   // TypeLPathTableLocation
                (uint)(startOfFourthPathTable / IsoUtilities.SectorSize),  // TypeMPathTableLocation
                (uint)(startOfSecondDirData / IsoUtilities.SectorSize),    // RootDirectory.LocationOfExtent
                (uint)_rootDirectory.GetDataSize(suppEncoding),            // RootDirectory.DataLength
                buildTime,
                suppEncoding);
            svDesc.VolumeIdentifier = _buildParams.VolumeIdentifier;
            SupplementaryVolumeDescriptorRegion svdr = new SupplementaryVolumeDescriptorRegion(svDesc, focus);
            fixedRegions.Insert(regionIdx++, svdr);
            focus += IsoUtilities.SectorSize;

            VolumeDescriptorSetTerminator evDesc = new VolumeDescriptorSetTerminator();
            VolumeDescriptorSetTerminatorRegion evdr = new VolumeDescriptorSetTerminatorRegion(evDesc, focus);
            fixedRegions.Insert(regionIdx++, evdr);

            return fixedRegions;
        }
Beispiel #4
0
        internal override List<BuilderExtent> FixExtents(out long totalLength)
        {
            List<BuilderExtent> fixedRegions = new List<BuilderExtent>();

            DateTime buildTime = DateTime.UtcNow;

            Encoding suppEncoding = _buildParams.UseJoliet ? Encoding.BigEndianUnicode : Encoding.ASCII;

            Dictionary<BuildDirectoryMember, uint> primaryLocationTable = new Dictionary<BuildDirectoryMember, uint>();
            Dictionary<BuildDirectoryMember, uint> supplementaryLocationTable = new Dictionary<BuildDirectoryMember, uint>();

            // ####################################################################
            // # 1. Fix file locations
            // ####################################################################
            long focus = FirstDataExtent;
            long highestFileLocation = 0;

            // Find end of the file data, fixing the files in place as we go
            foreach (BuildFileInfo fi in _files)
            {
                primaryLocationTable.Add(fi, (uint)(focus / IsoUtilities.SectorSize));
                supplementaryLocationTable.Add(fi, (uint)(focus / IsoUtilities.SectorSize));
                FileExtent extent = new FileExtent(fi, focus);

                // Only remember files of non-zero length (otherwise we'll stomp on a valid file)
                if (extent.Length != 0)
                {
                    fixedRegions.Add(extent);
                }
                highestFileLocation = focus;
                focus += Utilities.RoundUp(extent.Length, IsoUtilities.SectorSize);
            }

            // ####################################################################
            // # 2. Fix directory locations
            // ####################################################################

            // There are two directory tables
            //  1. Primary        (std ISO9660)
            //  2. Supplementary  (Joliet)
            long pushFilesBackAmt = 0;
            int regionIdx = 0;
            long pushAmt = 0;
            //I actually want the path and directory tables before the files,
            //so lets find out how big it is then move all of the files
            long unfocused = focus;
            focus = FirstDataExtent;

            // Find start of the second set of directory data, fixing ASCII directories in place.
            long startOfFirstDirData = focus;
            foreach (BuildDirectoryInfo di in _dirs)
            {
                primaryLocationTable.Add(di, (uint)(focus / IsoUtilities.SectorSize));
                DirectoryExtent extent = new DirectoryExtent(di, primaryLocationTable, Encoding.ASCII, focus);
                fixedRegions.Insert(regionIdx++, extent);
                pushAmt = Utilities.RoundUp(extent.Length, IsoUtilities.SectorSize);
                pushFilesBackAmt += pushAmt;
                focus += pushAmt;
            }

            // Find end of the second directory table, fixing supplementary directories in place.
            long startOfSecondDirData = 0;
            if (_buildParams.UseJoliet)
            {
                startOfSecondDirData = focus;
                foreach (BuildDirectoryInfo di in _dirs)
                {
                    supplementaryLocationTable.Add(di, (uint)(focus / IsoUtilities.SectorSize));
                    DirectoryExtent extent = new DirectoryExtent(di, supplementaryLocationTable, suppEncoding, focus);
                    fixedRegions.Insert(regionIdx++, extent);
                    pushAmt = Utilities.RoundUp(extent.Length, IsoUtilities.SectorSize);
                    pushFilesBackAmt += pushAmt;
                    focus += pushAmt;
                }
            }

            //Push these back now because I'm going to throw the path tables in before them
            PushDataBack(primaryLocationTable, supplementaryLocationTable, fixedRegions, pushFilesBackAmt, regionIdx, false);
            unfocused += pushFilesBackAmt;
            highestFileLocation += pushFilesBackAmt;
            focus = FirstDataExtent;
            pushFilesBackAmt = 0;
            int numDirExtents = regionIdx;
            regionIdx = 0;

            // ####################################################################
            // # 3. Fix path tables
            // ####################################################################

            // There are four path tables:
            //  1. LE, ASCII
            //  2. BE, ASCII
            //  3. LE, Supp Encoding (Joliet)
            //  4. BE, Supp Encoding (Joliet)

            // Find end of the path table
            long startOfFirstPathTable = focus;
            PathTable pathTable = new PathTable(false, Encoding.ASCII, _dirs, primaryLocationTable, focus);
            fixedRegions.Insert(regionIdx++, pathTable);
            pushAmt = Utilities.RoundUp(pathTable.Length, IsoUtilities.SectorSize);
            focus += pushAmt;
            pushFilesBackAmt += pushAmt;
            long primaryPathTableLength = pathTable.Length;

            long startOfSecondPathTable = focus;
            pathTable = new PathTable(true, Encoding.ASCII, _dirs, primaryLocationTable, focus);
            fixedRegions.Insert(regionIdx++, pathTable);
            pushAmt = Utilities.RoundUp(pathTable.Length, IsoUtilities.SectorSize);
            focus += pushAmt;
            pushFilesBackAmt += pushAmt;

            long startOfThirdPathTable = 0;
            long startOfFourthPathTable = 0;
            long supplementaryPathTableLength = 0;
            if (_buildParams.UseJoliet)
            {
                startOfThirdPathTable = focus;
                pathTable = new PathTable(false, suppEncoding, _dirs, supplementaryLocationTable, focus);
                fixedRegions.Insert(regionIdx++, pathTable);
                pushAmt = Utilities.RoundUp(pathTable.Length, IsoUtilities.SectorSize);
                focus += pushAmt;
                pushFilesBackAmt += pushAmt;
                supplementaryPathTableLength = pathTable.Length;

                startOfFourthPathTable = 0;
                pathTable = new PathTable(true, suppEncoding, _dirs, supplementaryLocationTable, focus);
                fixedRegions.Insert(regionIdx++, pathTable);
                pushAmt = Utilities.RoundUp(pathTable.Length, IsoUtilities.SectorSize);
                focus += pushAmt;
                pushFilesBackAmt += pushAmt;
                startOfSecondDirData += pushFilesBackAmt;
            }
            startOfFirstDirData += pushFilesBackAmt;
            highestFileLocation += pushFilesBackAmt;

            PushDataBack(primaryLocationTable, supplementaryLocationTable, fixedRegions, pushFilesBackAmt, regionIdx, true);
            unfocused += pushFilesBackAmt;
            pushFilesBackAmt = 0; //Done pushing, unless we want to expand the disc next

            // ####################################################################
            // # 3a. Correct the file locations
            // ####################################################################

            if(_buildParams.LastFileStartSector > 0)
            {
                long highFileSector = highestFileLocation / IsoUtilities.SectorSize;
                if (_buildParams.LastFileStartSector < highFileSector + _buildParams.LBAoffset)
                {
                    throw new Exception("Disc image is too big for GD-ROM, can't build");
                }
                else
                {
                    pushFilesBackAmt = ((_buildParams.LastFileStartSector - highFileSector - _buildParams.LBAoffset) * IsoUtilities.SectorSize);
                }
                PushDataBack(primaryLocationTable, supplementaryLocationTable, fixedRegions, pushFilesBackAmt, regionIdx + numDirExtents, false);
            }

            // Find the end of the disk
            totalLength = unfocused;
            if (_buildParams.EndSector.HasValue)
            {
                long desiredLength = (_buildParams.EndSector.Value - _buildParams.LBAoffset) * IsoUtilities.SectorSize;
                if (totalLength < desiredLength)
                {
                    totalLength = desiredLength;
                }
                else
                {
                    throw new Exception("Disc is too big, exceeds the desired end sector.");
                }
            }

            // ####################################################################
            // # 4. Prepare volume descriptors now other structures are fixed
            // ####################################################################
            regionIdx = 0;
            focus = DiskStart;
            PrimaryVolumeDescriptor pvDesc = new PrimaryVolumeDescriptor(
                (uint)(totalLength / IsoUtilities.SectorSize),             // VolumeSpaceSize
                (uint)primaryPathTableLength,                              // PathTableSize
                (uint)(startOfFirstPathTable / IsoUtilities.SectorSize) + _buildParams.LBAoffset,   // TypeLPathTableLocation
                (uint)(startOfSecondPathTable / IsoUtilities.SectorSize) + _buildParams.LBAoffset,  // TypeMPathTableLocation
                (uint)(startOfFirstDirData / IsoUtilities.SectorSize) + _buildParams.LBAoffset,     // RootDirectory.LocationOfExtent
                (uint)_rootDirectory.GetDataSize(Encoding.ASCII),          // RootDirectory.DataLength
                buildTime);
            pvDesc.VolumeIdentifier = _buildParams.VolumeIdentifier;
            pvDesc.SystemIdentifier = _buildParams.SystemIdentifier;
            pvDesc.VolumeSetIdentifier = _buildParams.VolumeSetIdentifier;
            pvDesc.PublisherIdentifier = _buildParams.PublisherIdentifier;
            pvDesc.DataPreparerIdentifier = _buildParams.DataPreparerIdentifier;
            pvDesc.ApplicationIdentifier = _buildParams.ApplicationIdentifier;

            PrimaryVolumeDescriptorRegion pvdr = new PrimaryVolumeDescriptorRegion(pvDesc, focus);
            fixedRegions.Insert(regionIdx++, pvdr);
            focus += IsoUtilities.SectorSize;

            if (_buildParams.UseJoliet)
            {
                //If you're not using Joilet, this is a copy of the regular descriptor and a waste of space to include.
                SupplementaryVolumeDescriptor svDesc = new SupplementaryVolumeDescriptor(
                    (uint)(totalLength / IsoUtilities.SectorSize),             // VolumeSpaceSize
                    (uint)supplementaryPathTableLength,                        // PathTableSize
                    (uint)(startOfThirdPathTable / IsoUtilities.SectorSize) + _buildParams.LBAoffset,   // TypeLPathTableLocation
                    (uint)(startOfFourthPathTable / IsoUtilities.SectorSize) + _buildParams.LBAoffset,  // TypeMPathTableLocation
                    (uint)(startOfSecondDirData / IsoUtilities.SectorSize) + _buildParams.LBAoffset,    // RootDirectory.LocationOfExtent
                    (uint)_rootDirectory.GetDataSize(suppEncoding),            // RootDirectory.DataLength
                    buildTime,
                    suppEncoding);
                svDesc.VolumeIdentifier = _buildParams.VolumeIdentifier;
                SupplementaryVolumeDescriptorRegion svdr = new SupplementaryVolumeDescriptorRegion(svDesc, focus);
                fixedRegions.Insert(regionIdx++, svdr);
                focus += IsoUtilities.SectorSize;
            }

            VolumeDescriptorSetTerminator evDesc = new VolumeDescriptorSetTerminator();
            VolumeDescriptorSetTerminatorRegion evdr = new VolumeDescriptorSetTerminatorRegion(evDesc, focus);
            fixedRegions.Insert(regionIdx++, evdr);

            return fixedRegions;
        }
Beispiel #5
0
        /// <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");
            }
        }
Beispiel #6
0
        /// <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");
            }
        }
Beispiel #7
0
 public SupplementaryVolumeDescriptorRegion(SupplementaryVolumeDescriptor descriptor, long start)
     : base(start)
 {
     _descriptor = descriptor;
 }
Beispiel #8
0
        protected override List <BuilderExtent> FixExtents(out long totalLength)
        {
            List <BuilderExtent> fixedRegions = new List <BuilderExtent>();

            DateTime buildTime = DateTime.UtcNow;

            Encoding suppEncoding = _buildParams.UseJoliet ? Encoding.BigEndianUnicode : Encoding.ASCII;

            Dictionary <BuildDirectoryMember, uint> primaryLocationTable       = new Dictionary <BuildDirectoryMember, uint>();
            Dictionary <BuildDirectoryMember, uint> supplementaryLocationTable = new Dictionary <BuildDirectoryMember, uint>();

            long focus = DiskStart + (3 * IsoUtilities.SectorSize); // Primary, Supplementary, End (fixed at end...)

            // ####################################################################
            // # 1. Fix file locations
            // ####################################################################

            // Find end of the file data, fixing the files in place as we go
            foreach (BuildFileInfo fi in _files)
            {
                primaryLocationTable.Add(fi, (uint)(focus / IsoUtilities.SectorSize));
                supplementaryLocationTable.Add(fi, (uint)(focus / IsoUtilities.SectorSize));
                FileExtent extent = new FileExtent(fi, focus);

                // Only remember files of non-zero length (otherwise we'll stomp on a valid file)
                if (extent.Length != 0)
                {
                    fixedRegions.Add(extent);
                }

                focus += Utilities.RoundUp(extent.Length, IsoUtilities.SectorSize);
            }

            // ####################################################################
            // # 2. Fix directory locations
            // ####################################################################

            // There are two directory tables
            //  1. Primary        (std ISO9660)
            //  2. Supplementary  (Joliet)

            // Find start of the second set of directory data, fixing ASCII directories in place.
            long startOfFirstDirData = focus;

            foreach (BuildDirectoryInfo di in _dirs)
            {
                primaryLocationTable.Add(di, (uint)(focus / IsoUtilities.SectorSize));
                DirectoryExtent extent = new DirectoryExtent(di, primaryLocationTable, Encoding.ASCII, focus);
                fixedRegions.Add(extent);
                focus += Utilities.RoundUp(extent.Length, IsoUtilities.SectorSize);
            }

            // Find end of the second directory table, fixing supplementary directories in place.
            long startOfSecondDirData = focus;

            foreach (BuildDirectoryInfo di in _dirs)
            {
                supplementaryLocationTable.Add(di, (uint)(focus / IsoUtilities.SectorSize));
                DirectoryExtent extent = new DirectoryExtent(di, supplementaryLocationTable, suppEncoding, focus);
                fixedRegions.Add(extent);
                focus += Utilities.RoundUp(extent.Length, IsoUtilities.SectorSize);
            }

            // ####################################################################
            // # 3. Fix path tables
            // ####################################################################

            // There are four path tables:
            //  1. LE, ASCII
            //  2. BE, ASCII
            //  3. LE, Supp Encoding (Joliet)
            //  4. BE, Supp Encoding (Joliet)

            // Find end of the path table
            long      startOfFirstPathTable = focus;
            PathTable pathTable             = new PathTable(false, Encoding.ASCII, _dirs, primaryLocationTable, focus);

            fixedRegions.Add(pathTable);
            focus += Utilities.RoundUp(pathTable.Length, IsoUtilities.SectorSize);
            long primaryPathTableLength = pathTable.Length;

            long startOfSecondPathTable = focus;

            pathTable = new PathTable(true, Encoding.ASCII, _dirs, primaryLocationTable, focus);
            fixedRegions.Add(pathTable);
            focus += Utilities.RoundUp(pathTable.Length, IsoUtilities.SectorSize);

            long startOfThirdPathTable = focus;

            pathTable = new PathTable(false, suppEncoding, _dirs, supplementaryLocationTable, focus);
            fixedRegions.Add(pathTable);
            focus += Utilities.RoundUp(pathTable.Length, IsoUtilities.SectorSize);
            long supplementaryPathTableLength = pathTable.Length;

            long startOfFourthPathTable = focus;

            pathTable = new PathTable(true, suppEncoding, _dirs, supplementaryLocationTable, focus);
            fixedRegions.Add(pathTable);
            focus += Utilities.RoundUp(pathTable.Length, IsoUtilities.SectorSize);

            // Find the end of the disk
            totalLength = focus;

            // ####################################################################
            // # 4. Prepare volume descriptors now other structures are fixed
            // ####################################################################
            int regionIdx = 0;

            focus = DiskStart;
            PrimaryVolumeDescriptor pvDesc = new PrimaryVolumeDescriptor(
                (uint)(totalLength / IsoUtilities.SectorSize),             // VolumeSpaceSize
                (uint)primaryPathTableLength,                              // PathTableSize
                (uint)(startOfFirstPathTable / IsoUtilities.SectorSize),   // TypeLPathTableLocation
                (uint)(startOfSecondPathTable / IsoUtilities.SectorSize),  // TypeMPathTableLocation
                (uint)(startOfFirstDirData / IsoUtilities.SectorSize),     // RootDirectory.LocationOfExtent
                (uint)_rootDirectory.GetDataSize(Encoding.ASCII),          // RootDirectory.DataLength
                buildTime)
            {
                VolumeIdentifier = _buildParams.VolumeIdentifier
            };
            PrimaryVolumeDescriptorRegion pvdr = new PrimaryVolumeDescriptorRegion(pvDesc, focus);

            fixedRegions.Insert(regionIdx++, pvdr);
            focus += IsoUtilities.SectorSize;

            SupplementaryVolumeDescriptor svDesc = new SupplementaryVolumeDescriptor(
                (uint)(totalLength / IsoUtilities.SectorSize),             // VolumeSpaceSize
                (uint)supplementaryPathTableLength,                        // PathTableSize
                (uint)(startOfThirdPathTable / IsoUtilities.SectorSize),   // TypeLPathTableLocation
                (uint)(startOfFourthPathTable / IsoUtilities.SectorSize),  // TypeMPathTableLocation
                (uint)(startOfSecondDirData / IsoUtilities.SectorSize),    // RootDirectory.LocationOfExtent
                (uint)_rootDirectory.GetDataSize(suppEncoding),            // RootDirectory.DataLength
                buildTime,
                suppEncoding)
            {
                VolumeIdentifier = _buildParams.VolumeIdentifier
            };
            SupplementaryVolumeDescriptorRegion svdr = new SupplementaryVolumeDescriptorRegion(svDesc, focus);

            fixedRegions.Insert(regionIdx++, svdr);
            focus += IsoUtilities.SectorSize;

            VolumeDescriptorSetTerminator       evDesc = new VolumeDescriptorSetTerminator();
            VolumeDescriptorSetTerminatorRegion evdr   = new VolumeDescriptorSetTerminatorRegion(evDesc, focus);

            fixedRegions.Insert(regionIdx, evdr);

            return(fixedRegions);
        }
Beispiel #9
0
        internal override List <BuilderExtent> FixExtents(out long totalLength)
        {
            List <BuilderExtent> fixedRegions = new List <BuilderExtent>();

            DateTime buildTime = DateTime.UtcNow;

            Encoding suppEncoding = _buildParams.UseJoliet ? Encoding.BigEndianUnicode : Encoding.ASCII;

            Dictionary <BuildDirectoryMember, uint> primaryLocationTable       = new Dictionary <BuildDirectoryMember, uint>();
            Dictionary <BuildDirectoryMember, uint> supplementaryLocationTable = new Dictionary <BuildDirectoryMember, uint>();

            // ####################################################################
            // # 1. Fix file locations
            // ####################################################################
            long focus = FirstDataExtent;
            long highestFileLocation = 0;

            // Find end of the file data, fixing the files in place as we go
            foreach (BuildFileInfo fi in _files)
            {
                primaryLocationTable.Add(fi, (uint)(focus / IsoUtilities.SectorSize));
                supplementaryLocationTable.Add(fi, (uint)(focus / IsoUtilities.SectorSize));
                FileExtent extent = new FileExtent(fi, focus);

                // Only remember files of non-zero length (otherwise we'll stomp on a valid file)
                if (extent.Length != 0)
                {
                    fixedRegions.Add(extent);
                }
                highestFileLocation = focus;
                focus += Utilities.RoundUp(extent.Length, IsoUtilities.SectorSize);
            }

            // ####################################################################
            // # 2. Fix directory locations
            // ####################################################################

            // There are two directory tables
            //  1. Primary        (std ISO9660)
            //  2. Supplementary  (Joliet)
            long pushFilesBackAmt = 0;
            int  regionIdx        = 0;
            long pushAmt          = 0;
            //I actually want the path and directory tables before the files,
            //so lets find out how big it is then move all of the files
            long unfocused = focus;

            focus = FirstDataExtent;

            // Find start of the second set of directory data, fixing ASCII directories in place.
            long startOfFirstDirData = focus;

            foreach (BuildDirectoryInfo di in _dirs)
            {
                primaryLocationTable.Add(di, (uint)(focus / IsoUtilities.SectorSize));
                DirectoryExtent extent = new DirectoryExtent(di, primaryLocationTable, Encoding.ASCII, focus);
                fixedRegions.Insert(regionIdx++, extent);
                pushAmt           = Utilities.RoundUp(extent.Length, IsoUtilities.SectorSize);
                pushFilesBackAmt += pushAmt;
                focus            += pushAmt;
            }

            // Find end of the second directory table, fixing supplementary directories in place.
            long startOfSecondDirData = 0;

            if (_buildParams.UseJoliet)
            {
                startOfSecondDirData = focus;
                foreach (BuildDirectoryInfo di in _dirs)
                {
                    supplementaryLocationTable.Add(di, (uint)(focus / IsoUtilities.SectorSize));
                    DirectoryExtent extent = new DirectoryExtent(di, supplementaryLocationTable, suppEncoding, focus);
                    fixedRegions.Insert(regionIdx++, extent);
                    pushAmt           = Utilities.RoundUp(extent.Length, IsoUtilities.SectorSize);
                    pushFilesBackAmt += pushAmt;
                    focus            += pushAmt;
                }
            }

            //Push these back now because I'm going to throw the path tables in before them
            PushDataBack(primaryLocationTable, supplementaryLocationTable, fixedRegions, pushFilesBackAmt, regionIdx, false);
            unfocused           += pushFilesBackAmt;
            highestFileLocation += pushFilesBackAmt;
            focus            = FirstDataExtent;
            pushFilesBackAmt = 0;
            int numDirExtents = regionIdx;

            regionIdx = 0;

            // ####################################################################
            // # 3. Fix path tables
            // ####################################################################

            // There are four path tables:
            //  1. LE, ASCII
            //  2. BE, ASCII
            //  3. LE, Supp Encoding (Joliet)
            //  4. BE, Supp Encoding (Joliet)

            // Find end of the path table
            long      startOfFirstPathTable = focus;
            PathTable pathTable             = new PathTable(false, Encoding.ASCII, _dirs, primaryLocationTable, focus);

            fixedRegions.Insert(regionIdx++, pathTable);
            pushAmt           = Utilities.RoundUp(pathTable.Length, IsoUtilities.SectorSize);
            focus            += pushAmt;
            pushFilesBackAmt += pushAmt;
            long primaryPathTableLength = pathTable.Length;

            long startOfSecondPathTable = focus;

            pathTable = new PathTable(true, Encoding.ASCII, _dirs, primaryLocationTable, focus);
            fixedRegions.Insert(regionIdx++, pathTable);
            pushAmt           = Utilities.RoundUp(pathTable.Length, IsoUtilities.SectorSize);
            focus            += pushAmt;
            pushFilesBackAmt += pushAmt;

            long startOfThirdPathTable        = 0;
            long startOfFourthPathTable       = 0;
            long supplementaryPathTableLength = 0;

            if (_buildParams.UseJoliet)
            {
                startOfThirdPathTable = focus;
                pathTable             = new PathTable(false, suppEncoding, _dirs, supplementaryLocationTable, focus);
                fixedRegions.Insert(regionIdx++, pathTable);
                pushAmt                      = Utilities.RoundUp(pathTable.Length, IsoUtilities.SectorSize);
                focus                       += pushAmt;
                pushFilesBackAmt            += pushAmt;
                supplementaryPathTableLength = pathTable.Length;

                startOfFourthPathTable = 0;
                pathTable = new PathTable(true, suppEncoding, _dirs, supplementaryLocationTable, focus);
                fixedRegions.Insert(regionIdx++, pathTable);
                pushAmt               = Utilities.RoundUp(pathTable.Length, IsoUtilities.SectorSize);
                focus                += pushAmt;
                pushFilesBackAmt     += pushAmt;
                startOfSecondDirData += pushFilesBackAmt;
            }
            startOfFirstDirData += pushFilesBackAmt;
            highestFileLocation += pushFilesBackAmt;

            PushDataBack(primaryLocationTable, supplementaryLocationTable, fixedRegions, pushFilesBackAmt, regionIdx, true);
            unfocused       += pushFilesBackAmt;
            pushFilesBackAmt = 0; //Done pushing, unless we want to expand the disc next

            // ####################################################################
            // # 3a. Correct the file locations
            // ####################################################################

            if (_buildParams.LastFileStartSector > 0)
            {
                long highFileSector = highestFileLocation / IsoUtilities.SectorSize;
                if (_buildParams.LastFileStartSector < highFileSector + _buildParams.LBAoffset)
                {
                    throw new Exception("Disc image is too big for GD-ROM, can't build");
                }
                else
                {
                    pushFilesBackAmt = ((_buildParams.LastFileStartSector - highFileSector - _buildParams.LBAoffset) * IsoUtilities.SectorSize);
                }
                PushDataBack(primaryLocationTable, supplementaryLocationTable, fixedRegions, pushFilesBackAmt, regionIdx + numDirExtents, false);
            }

            // Find the end of the disk
            totalLength = unfocused;
            if (_buildParams.EndSector.HasValue)
            {
                long desiredLength = (_buildParams.EndSector.Value - _buildParams.LBAoffset) * IsoUtilities.SectorSize;
                if (totalLength < desiredLength)
                {
                    totalLength = desiredLength;
                }
                else
                {
                    throw new Exception("Disc is too big, exceeds the desired end sector.");
                }
            }

            // ####################################################################
            // # 4. Prepare volume descriptors now other structures are fixed
            // ####################################################################
            regionIdx = 0;
            focus     = DiskStart;
            PrimaryVolumeDescriptor pvDesc = new PrimaryVolumeDescriptor(
                (uint)(totalLength / IsoUtilities.SectorSize),                                     // VolumeSpaceSize
                (uint)primaryPathTableLength,                                                      // PathTableSize
                (uint)(startOfFirstPathTable / IsoUtilities.SectorSize) + _buildParams.LBAoffset,  // TypeLPathTableLocation
                (uint)(startOfSecondPathTable / IsoUtilities.SectorSize) + _buildParams.LBAoffset, // TypeMPathTableLocation
                (uint)(startOfFirstDirData / IsoUtilities.SectorSize) + _buildParams.LBAoffset,    // RootDirectory.LocationOfExtent
                (uint)_rootDirectory.GetDataSize(Encoding.ASCII),                                  // RootDirectory.DataLength
                buildTime);

            pvDesc.VolumeIdentifier       = _buildParams.VolumeIdentifier;
            pvDesc.SystemIdentifier       = _buildParams.SystemIdentifier;
            pvDesc.VolumeSetIdentifier    = _buildParams.VolumeSetIdentifier;
            pvDesc.PublisherIdentifier    = _buildParams.PublisherIdentifier;
            pvDesc.DataPreparerIdentifier = _buildParams.DataPreparerIdentifier;
            pvDesc.ApplicationIdentifier  = _buildParams.ApplicationIdentifier;

            PrimaryVolumeDescriptorRegion pvdr = new PrimaryVolumeDescriptorRegion(pvDesc, focus);

            fixedRegions.Insert(regionIdx++, pvdr);
            focus += IsoUtilities.SectorSize;

            if (_buildParams.UseJoliet)
            {
                //If you're not using Joilet, this is a copy of the regular descriptor and a waste of space to include.
                SupplementaryVolumeDescriptor svDesc = new SupplementaryVolumeDescriptor(
                    (uint)(totalLength / IsoUtilities.SectorSize),                                     // VolumeSpaceSize
                    (uint)supplementaryPathTableLength,                                                // PathTableSize
                    (uint)(startOfThirdPathTable / IsoUtilities.SectorSize) + _buildParams.LBAoffset,  // TypeLPathTableLocation
                    (uint)(startOfFourthPathTable / IsoUtilities.SectorSize) + _buildParams.LBAoffset, // TypeMPathTableLocation
                    (uint)(startOfSecondDirData / IsoUtilities.SectorSize) + _buildParams.LBAoffset,   // RootDirectory.LocationOfExtent
                    (uint)_rootDirectory.GetDataSize(suppEncoding),                                    // RootDirectory.DataLength
                    buildTime,
                    suppEncoding);
                svDesc.VolumeIdentifier = _buildParams.VolumeIdentifier;
                SupplementaryVolumeDescriptorRegion svdr = new SupplementaryVolumeDescriptorRegion(svDesc, focus);
                fixedRegions.Insert(regionIdx++, svdr);
                focus += IsoUtilities.SectorSize;
            }

            VolumeDescriptorSetTerminator       evDesc = new VolumeDescriptorSetTerminator();
            VolumeDescriptorSetTerminatorRegion evdr   = new VolumeDescriptorSetTerminatorRegion(evDesc, focus);

            fixedRegions.Insert(regionIdx++, evdr);

            return(fixedRegions);
        }
        /// <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);
        }