Example #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);
        }
Example #2
0
        /// <summary>
        /// Parse the node record from the given stream.
        /// </summary>
        /// <param name="s">The stream to parse from.</param>
        public void Parse(Stream s)
        {
            EndianBitConverter bc = EndianBitConverter.CreateForLittleEndian();
            long startPosition    = s.Position;

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

            // Get the length
            s.Read(buffer, 0, 1);
            this.Length = buffer[0];

            //  "CD001" + 0x01
            s.Read(buffer, 0, 1);

            // Read Data Offset
            s.Read(buffer, 0, 8);
            this.OffsetOfData = (long)bc.ToInt32(buffer);

            // Read Data Length
            s.Read(buffer, 0, 8);
            this.LengthOfData = (long)bc.ToInt32(buffer);

            // Read the time and flags
            s.Read(buffer, 0, 8);
            this.Year           = buffer[0];
            this.Month          = buffer[1];
            this.Day            = buffer[2];
            this.Hour           = buffer[3];
            this.Minute         = buffer[4];
            this.Second         = buffer[5];
            this.TimeZoneOffset = buffer[6];

            this.Flags = buffer[7];

            s.Read(buffer, 0, 6);

            // Read the name length
            s.Read(buffer, 0, 1);
            this.NameLength = buffer[0];

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

            // Seek to end
            s.Seek(startPosition + this.Length, SeekOrigin.Begin);
        }
        /// <summary>
        /// Parse the volume descriptor header.
        /// </summary>
        /// <param name="s">The stream to parse from.</param>
        public void Parse(Stream s)
        {
            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);

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

            //  "CD001" + 0x01

            // Handle the primary volume information
            if (this.Type == 1)
            {
                int cursor = 8;
                // Get the system identifier
                Array.Copy(buffer, cursor,
                           this.SystemIdentifier, 0, LENGTH_SHORT_IDENTIFIER);
                cursor += LENGTH_SHORT_IDENTIFIER;

                // Get the volume identifier
                Array.Copy(buffer, cursor,
                           this.VolumeIdentifier, 0, LENGTH_SHORT_IDENTIFIER);
                cursor += LENGTH_SHORT_IDENTIFIER;

                cursor += 8;

                // Get the total number of sectors
                this.NumberOfSectors = bc.ToInt32(buffer, cursor);
                cursor += 8;

                cursor += 32;

                this.VolumeSetSize        = bc.ToInt16(buffer, cursor);
                cursor                   += 4;
                this.VolumeSequenceNumber = bc.ToInt16(buffer, cursor);
                cursor                   += 4;
                this.SectorSize           = bc.ToInt16(buffer, cursor);
                cursor                   += 4;

                this.PathTableSize = bc.ToInt32(buffer, cursor);
                cursor            += 8;
                this.OffsetOfFirstLittleEndianPathTable = bc.ToInt32(buffer, cursor);
                cursor += 4;
                this.OffsetOfSecondLittleEndianPathTable = bc.ToInt32(buffer, cursor);
                cursor += 4;
                this.OffsetOfFirstLittleEndianPathTable = bcBig.ToInt32(buffer, cursor);
                cursor += 4;
                this.OffsetOfSecondLittleEndianPathTable = bcBig.ToInt32(buffer, cursor);
                cursor += 4;

                this.RootDirectoryRecord.Parse(buffer, cursor);
                cursor += LENGTH_ROOT_DIRECTORY_RECORD;

                Array.Copy(buffer, cursor,
                           this.VolumeSetIdentifier, 0, LENGTH_LONG_IDENTIFIER);
                cursor += LENGTH_LONG_IDENTIFIER;
                Array.Copy(buffer, cursor,
                           this.PublisherIdentifier, 0, LENGTH_LONG_IDENTIFIER);
                cursor += LENGTH_LONG_IDENTIFIER;
                Array.Copy(buffer, cursor,
                           this.DataPreparerIdentifier, 0, LENGTH_LONG_IDENTIFIER);
                cursor += LENGTH_LONG_IDENTIFIER;
                Array.Copy(buffer, cursor,
                           this.ApplicationIdentifier, 0, LENGTH_LONG_IDENTIFIER);
                cursor += LENGTH_LONG_IDENTIFIER;

                Array.Copy(buffer, cursor,
                           this.CopyrightFileIdentifier, 0, LENGTH_IDENTIFIER);
                cursor += LENGTH_IDENTIFIER;
                Array.Copy(buffer, cursor,
                           this.AbstractFileIdentifier, 0, LENGTH_IDENTIFIER);
                cursor += LENGTH_IDENTIFIER;
                Array.Copy(buffer, cursor,
                           this.BibliographicalFileIdentifier, 0, LENGTH_IDENTIFIER);
                cursor += LENGTH_IDENTIFIER;

                Array.Copy(buffer, cursor,
                           this.VolumeCreationDateTime, 0, LENGTH_TIME);
                cursor += LENGTH_TIME;
                Array.Copy(buffer, cursor,
                           this.LastModifiedDateTime, 0, LENGTH_TIME);
                cursor += LENGTH_TIME;
                Array.Copy(buffer, cursor,
                           this.ExpirationDateTime, 0, LENGTH_TIME);
                cursor += LENGTH_TIME;
                Array.Copy(buffer, cursor,
                           this.EffectiveDateTime, 0, LENGTH_TIME);
                cursor += LENGTH_TIME;

                cursor += 1;

                cursor += 1;

                Array.Copy(buffer, cursor,
                           this.Reserved, 0, LENGTH_RESERVED);
                cursor += LENGTH_RESERVED;
            }
        }
Example #4
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);
        }