Пример #1
0
        /*
         *      BP  Size in bytes   Description
         *      1   1               Name size
         *      2   1               Extended Attribute record length
         *      3   4               Directory block address
         *      7   2               Parent Directory number
         *      9   n               Directory file name
         */

        public static List <CDIPathNode> ParsePathTable(Stream s, int PathTableSize)
        {
            EndianBitConverter bc    = EndianBitConverter.CreateForLittleEndian();
            EndianBitConverter bcBig = EndianBitConverter.CreateForBigEndian();

            byte[] buffer = new byte[ISOFile.SECTOR_SIZE];

            // Read the entire structure
            s.Read(buffer, 0, ISOFile.SECTOR_SIZE);

            int startCursor = 0;

            List <CDIPathNode> pathNodes = new List <CDIPathNode>();

            int pad = 0;

            do
            {
                CDIPathNode node = new CDIPathNode();
                byte[]      data = bc.ReadBytes(buffer, startCursor, ISOFile.SECTOR_SIZE - startCursor);
                node.NameLength = data[0];

                node.ExtendedAttribRecordLength = data[1];
                node.DirectoryBlockAddress      = bcBig.ReadIntValue(data, 2, 4);
                node.ParentDirectoryNumber      = bcBig.ReadIntValue(data, 6, 2);
                node.Name = Encoding.ASCII.GetString(bc.ReadBytes(data, 8, data[0]));

                // if nameLength is odd a padding byte must be added

                if (node.NameLength % 2 != 0)
                {
                    pad = 1;
                }

                pathNodes.Add(node);

                startCursor += node.NameLength + 8;
            } while (startCursor < PathTableSize + pad);


            return(pathNodes);
        }
Пример #2
0
        public void ParseCDInteractive(Stream s)
        {
            /* From the Green Book Spec
             * BP (byte position) obviously is n+1
             *
             * BP Size in Bytes Description
             * 1 1 Disc Label Record Type
             * 2 5 Volume Structure Standard ID
             * 7 1 Volume Structure Version number
             * 8 1 Volume flags
             * 9 32 System identifier
             * 41 32 Volume identifier
             * 73 12 Reserved
             * 85 4 Volume space size
             * 89 32 Coded Character Set identifier
             * 121 2 Reserved
             * 123 2 Number of Volumes in Album
             * 125 2 Reserved
             * 127 2 Album Set Sequence number
             * 129 2 Reserved
             * 131 2 Logical Block size
             * 133 4 Reserved
             * 137 4 Path Table size
             * 141 8 Reserved
             * 149 4 Address of Path Table
             * 153 38 Reserved
             * 191 128 Album identifier
             * 319 128 Publisher identifier
             * 447 128 Data Preparer identifier
             * 575 128 Application identifier
             * 703 32 Copyright file name
             * 735 5 Reserved
             * 740 32 Abstract file name
             * 772 5 Reserved
             * 777 32 Bibliographic file name
             * 809 5 Reserved
             * 814 16 Creation date and time
             * 830 1 Reserved
             * 831 16 Modification date and time
             * 847 1 Reserved
             * 848 16 Expiration date and time
             * 864 1 Reserved
             * 865 16 Effective date and time
             * 881 1 Reserved
             * 882 1 File Structure Standard Version number
             * 883 1 Reserved
             * 884 512 Application use
             * 1396 653 Reserved                      */

            long startPosition = s.Position;

            byte[] buffer = new byte[ISOFile.SECTOR_SIZE];
            s.Position = startPosition - ISOFile.SECTOR_SIZE;

            // Read the entire structure
            s.Read(buffer, 0, ISOFile.SECTOR_SIZE);

            // Get the type
            this.Type = buffer[0];

            // Handle the primary volume information
            if (this.Type == 1)
            {
                this.VolumeFlags          = buffer[7];
                this.SystemIdentifier     = bc.ReadBytes(buffer, 8, LENGTH_SHORT_IDENTIFIER);
                this.VolumeIdentifier     = bc.ReadBytes(buffer, 40, LENGTH_SHORT_IDENTIFIER);
                this.NumberOfSectors      = bcBig.ReadIntValue(buffer, 84, 4);
                this.CodedCharSetIdent    = bc.ReadBytes(buffer, 88, LENGTH_SHORT_IDENTIFIER);
                this.VolumeSetSize        = bcBig.ReadIntValue(buffer, 122, 2);
                this.VolumeSequenceNumber = bcBig.ReadIntValue(buffer, 126, 2);
                this.SectorSize           = bcBig.ReadIntValue(buffer, 130, 2);
                this.PathTableSize        = bcBig.ReadIntValue(buffer, 136, 4);
                this.AddressOfPathTable   = bcBig.ReadIntValue(buffer, 148, 4);

                this.VolumeSetIdentifier    = bc.ReadBytes(buffer, 190, LENGTH_LONG_IDENTIFIER);
                this.PublisherIdentifier    = bc.ReadBytes(buffer, 318, LENGTH_LONG_IDENTIFIER);
                this.DataPreparerIdentifier = bc.ReadBytes(buffer, 446, LENGTH_LONG_IDENTIFIER);
                this.ApplicationIdentifier  = bc.ReadBytes(buffer, 574, LENGTH_LONG_IDENTIFIER);

                this.CopyrightFileIdentifier       = bc.ReadBytes(buffer, 702, LENGTH_SHORT_IDENTIFIER);
                this.AbstractFileIdentifier        = bc.ReadBytes(buffer, 739, LENGTH_SHORT_IDENTIFIER);
                this.BibliographicalFileIdentifier = bc.ReadBytes(buffer, 776, LENGTH_SHORT_IDENTIFIER);

                this.VolumeCreationDateTime = bc.ReadBytes(buffer, 813, 16);
                this.LastModifiedDateTime   = bc.ReadBytes(buffer, 830, 16);
                this.ExpirationDateTime     = bc.ReadBytes(buffer, 847, 16);
                this.EffectiveDateTime      = bc.ReadBytes(buffer, 864, 16);

                // save current position
                long pos = s.Position;

                // get path table records
                s.Position           = ISOFile.SECTOR_SIZE * this.AddressOfPathTable;
                ISOFile.CDIPathTable = CDIPathNode.ParsePathTable(s, this.PathTableSize);

                // read the root dir record
                s.Position = ISOFile.SECTOR_SIZE * ISOFile.CDIPathTable[0].DirectoryBlockAddress;
                s.Read(buffer, 0, ISOFile.SECTOR_SIZE);
                this.RootDirectoryRecord.Parse(buffer, 0);

                // go back to where we were
                s.Position = pos;
            }
        }
Пример #3
0
        /// <summary>
        /// Parse the node record from the given CD-I stream.
        /// </summary>
        /// <param name="s">The stream to parse from.</param>
        public void ParseCDInteractive(Stream s)
        {
            /*
             * BP      Size in bytes   Description
             * 1       1               Record length
             * 2       1               Extended Attribute record length
             * 3       4               Reserved
             * 7       4               File beginning LBN
             * 11      4               Reserved
             * 15      4               File size
             * 19      6               Creation date
             * 25      1               Reserved
             * 26      1               File flags
             * 27      2               Interleave
             * 29      2               Reserved
             * 31      2               Album Set Sequence number
             * 33      1               File name size
             * 34      (n)             File name
             * 34+n    4               Owner ID
             * 38+n    2               Attributes
             * 40+n    2               Reserved
             * 42+n    1               File number
             * 43+n    1               Reserved
             *      43+n            Total
             */

            EndianBitConverter bc    = EndianBitConverter.CreateForLittleEndian();
            EndianBitConverter bcBig = EndianBitConverter.CreateForBigEndian();
            long startPosition       = s.Position;

            byte[] buffer = new byte[ISOFile.SECTOR_SIZE];

            // Read the entire structure
            s.Read(buffer, 0, ISOFile.SECTOR_SIZE);
            s.Position -= ISOFile.SECTOR_SIZE;

            // Get the record length
            this.Length = buffer[0];

            // extended attribute record length
            this.ExtendedAttribRecordLength = buffer[1];

            // Read Data Offset
            this.OffsetOfData = bcBig.ReadIntValue(buffer, 6, 4);

            // Read Data Length
            this.LengthOfData = bcBig.ReadIntValue(buffer, 14, 4);

            // Read the time
            var ti = bc.ReadBytes(buffer, 18, 6);

            this.Year   = ti[0];
            this.Month  = ti[1];
            this.Day    = ti[2];
            this.Hour   = ti[3];
            this.Minute = ti[4];
            this.Second = ti[5];

            // read interleave - still to do

            // read album (volume) set sequence number (we are ignoring this)

            // Read the name length
            this.NameLength = buffer[32];

            // Read the file/directory name
            var name = bc.ReadBytes(buffer, 33, this.NameLength);

            if (this.NameLength == 1 && (name[0] == 0 || name[0] == 1))
            {
                if (name[0] == 0)
                {
                    this.Name = ISONodeRecord.CURRENT_DIRECTORY;
                }
                else
                {
                    this.Name = ISONodeRecord.PARENT_DIRECTORY;
                }
            }
            else
            {
                this.Name = ASCIIEncoding.ASCII.GetString(name, 0, this.NameLength);
            }

            // skip ownerID for now

            // read the flags - only really interested in the directory attribute (bit 15)
            // (confusingly these are called 'attributes' in CD-I. the CD-I 'File Flags' entry is something else entirely)
            this.Flags = buffer[37 + this.NameLength];

            // skip filenumber
            //this.FileNumber = buffer[41 + this.NameLength];

            // Seek to end
            s.Seek(startPosition + this.Length, SeekOrigin.Begin);
        }