예제 #1
0
        /// <summary>
        /// Create a new VolumeHeader from a Stream and version
        /// </summary>
        public static VolumeHeader Create(Stream stream, int version)
        {
            var header = new VolumeHeader();

            if (version <= 5)
            {
                if (stream.Length - stream.Position < Constants.VOLUME_HEADER_SIZE_V5)
                {
                    return(null);
                }

                header.DataOffset = stream.ReadUInt32();
                stream.Seek(4, SeekOrigin.Current);
                header.FirstFileIndex          = stream.ReadUInt32();
                header.LastFileIndex           = stream.ReadUInt32();
                header.FirstFileOffset         = stream.ReadUInt32();
                header.FirstFileSizeExpanded   = stream.ReadUInt32();
                header.FirstFileSizeCompressed = stream.ReadUInt32();
                header.LastFileOffset          = stream.ReadUInt32();
                header.LastFileSizeExpanded    = stream.ReadUInt32();
                header.LastFileSizeCompressed  = stream.ReadUInt32();

                if (header.LastFileOffset == 0)
                {
                    header.LastFileOffset = int.MaxValue;
                }
            }
            else
            {
                if (stream.Length - stream.Position < Constants.VOLUME_HEADER_SIZE_V6)
                {
                    return(null);
                }

                header.DataOffset                  = stream.ReadUInt32();
                header.DataOffsetHigh              = stream.ReadUInt32();
                header.FirstFileIndex              = stream.ReadUInt32();
                header.LastFileIndex               = stream.ReadUInt32();
                header.FirstFileOffset             = stream.ReadUInt32();
                header.FirstFileOffsetHigh         = stream.ReadUInt32();
                header.FirstFileSizeExpanded       = stream.ReadUInt32();
                header.FirstFileSizeExpandedHigh   = stream.ReadUInt32();
                header.FirstFileSizeCompressed     = stream.ReadUInt32();
                header.FirstFileSizeCompressedHigh = stream.ReadUInt32();
                header.LastFileOffset              = stream.ReadUInt32();
                header.LastFileOffsetHigh          = stream.ReadUInt32();
                header.LastFileSizeExpanded        = stream.ReadUInt32();
                header.LastFileSizeExpandedHigh    = stream.ReadUInt32();
                header.LastFileSizeCompressed      = stream.ReadUInt32();
                header.LastFileSizeCompressedHigh  = stream.ReadUInt32();
            }

            return(header);
        }
예제 #2
0
        /// <summary>
        /// Open the volume at the inputted index
        /// </summary>
        public bool OpenVolume(int volume)
        {
            this.VolumeFile?.Close();
            this.VolumeFile = this.Cabinet.OpenFileForReading(volume, Constants.CABINET_SUFFIX);
            if (this.VolumeFile == null)
            {
                Console.Error.WriteLine($"Failed to open input cabinet file {volume}");
                return(false);
            }

            var commonHeader = CommonHeader.Create(this.VolumeFile);

            if (commonHeader == default)
            {
                return(false);
            }

            this.VolumeHeader = VolumeHeader.Create(this.VolumeFile, this.Cabinet.HeaderList.MajorVersion);
            if (this.VolumeHeader == null)
            {
                return(false);
            }

            // enable support for split archives for IS5
            if (this.Cabinet.HeaderList.MajorVersion == 5)
            {
                if (this.Index < (this.Cabinet.HeaderList.Descriptor.FileCount - 1) &&
                    this.Index == this.VolumeHeader.LastFileIndex &&
                    this.VolumeHeader.LastFileSizeCompressed != this.FileDescriptor.CompressedSize)
                {
                    this.FileDescriptor.Flags |= FileDescriptorFlag.FILE_SPLIT;
                }
                else if (this.Index > 0 &&
                         this.Index == this.VolumeHeader.FirstFileIndex &&
                         this.VolumeHeader.FirstFileSizeCompressed != this.FileDescriptor.CompressedSize)
                {
                    this.FileDescriptor.Flags |= FileDescriptorFlag.FILE_SPLIT;
                }
            }

            ulong dataOffset, volumeBytesLeftCompressed, volumeBytesLeftExpanded;

            if (this.FileDescriptor.Flags.HasFlag(FileDescriptorFlag.FILE_SPLIT))
            {
                if (this.Index == this.VolumeHeader.LastFileIndex && this.VolumeHeader.LastFileOffset != 0x7FFFFFFF)
                {
                    // can be first file too
                    dataOffset = this.VolumeHeader.LastFileOffset;
                    volumeBytesLeftExpanded   = this.VolumeHeader.LastFileSizeExpanded;
                    volumeBytesLeftCompressed = this.VolumeHeader.LastFileSizeCompressed;
                }
                else if (this.Index == this.VolumeHeader.FirstFileIndex)
                {
                    dataOffset = this.VolumeHeader.FirstFileOffset;
                    volumeBytesLeftExpanded   = this.VolumeHeader.FirstFileSizeExpanded;
                    volumeBytesLeftCompressed = this.VolumeHeader.FirstFileSizeCompressed;
                }
                else
                {
                    return(true);
                }
            }
            else
            {
                dataOffset = this.FileDescriptor.DataOffset;
                volumeBytesLeftExpanded   = this.FileDescriptor.ExpandedSize;
                volumeBytesLeftCompressed = this.FileDescriptor.CompressedSize;
            }

            if (this.FileDescriptor.Flags.HasFlag(FileDescriptorFlag.FILE_COMPRESSED))
            {
                this.VolumeBytesLeft = volumeBytesLeftCompressed;
            }
            else
            {
                this.VolumeBytesLeft = volumeBytesLeftExpanded;
            }

            this.VolumeFile.Seek((long)dataOffset, SeekOrigin.Begin);
            this.Volume = volume;

            return(true);
        }