private void GenFile(IsoFile f)
 {
     f.DataBlock  = this.generator.Index / LogicalBlockSize;
     f.DataLength = (int)f.fileInfo.Length;
     this.generator.WriteFile(f, PrimaryVolumeDescriptor);
     this.generator.FinishBlock();
 }
        private void GenBootCatalog(IsoFile f)
        {
            BootCatalog = this.generator.Index / LogicalBlockSize;
            // write validation entry first... see El Torito section 2.1
            var ve = new FieldValidator(this.generator);

            ve.Byte(1, 1);                   // Header ID, must be 0x01
            ve.Byte(0, 2);                   // 0 == x86 - TODO FIXME: 1 == PowerPC, 2 == Mac, see El Torito figure 2
            ve.DupByte(0, 3, 4);             // Reserved
            ve.DupByte(0, 5, 0x1C);          // Manufacturer/Developer of CD-ROM, see El Torito figure 2
            ve.ShortLSB(0x55AA, 0x1D, 0x1E); // checksum - TODO FIXME - allow custom Manufacturer string - calculate checksum dynamically
            ve.Byte(0x55, 0x1F);             // 1st Key Byte
            ve.Byte(0xAA, 0x20);             // 2nd Key Byte

            // initial/default entry... see El Torito section 2.2 and figure 3
            var ide = new FieldValidator(this.generator);

            ide.Byte(0x88, 1);             // 0x88 = bootable, 0x00 = not bootable

            // TODO FIXME - this is extremely hackish... fix me...
            ide.Byte(0, 2);             // no emulation

            /*if ( f.fileInfo.Length <= 1182720 )
             *      ide.Byte(1, 2); // 1.2 meg diskette
             * else if ( f.fileInfo.Length <= 1440 * 1024 )
             *      ide.Byte(2,2); // 1.44 meg diskette
             * else if ( f.fileInfo.Length <= 2880 * 1024 )
             *      ide.Byte(3,2); // 2.88 meg diskette
             * else
             *      ide.Byte(4,2);*/
            // Hard Disk ( drive 80 )

            ide.ShortLSB(0, 3, 4);      // Load Segment - 0 == default of 0x7C0
            ide.Byte(0, 5);             // System Type, according to El Torito figure 3 this MUST be a copy of the "System Type" from the boot image. In practice this appears to not be the case.
            ide.Byte(0, 6);             // Unused, must be 0
            if (this.bootLoadSize == 0)
            {
                this.bootLoadSize = (short)((f.fileInfo.Length - 1) / 0x200 + 1);
            }
            ide.ShortLSB(this.bootLoadSize, 7, 8);  // Sector Count
            ide.IntLSB(this.boot.DataBlock, 9, 12); // Logical Block of boot image
            ide.Zero(13, 32);                       // unused

            this.generator.FinishBlock();
        }
Beispiel #3
0
        /// <summary>
        /// writes a file out to cd. Generate the Boot Info Table if necessary
        /// </summary>
        /// <param Name="f">the file to write</param>
        /// <param Name="primaryVolumeDescriptor">the PVD block, passed in case we need to generate the Boot Info Table</param>
        public void WriteFile(IsoFile f, int primaryVolumeDescriptor)
        {
            if (f.fileInfo.Length > 0xffffffff)
            {
                throw new NotImplementedException(">4G files not implemented");
            }

            int bytes = (int)f.fileInfo.Length;

            if (this.fs == null)
            {
                this.Index += bytes;
                return;
            }

            // TODO FIXME - create smaller reusable buffer and read fixed-size chunks at a time...
            byte[] b = new byte[bytes];

            using (FileStream stream = f.fileInfo.OpenRead())
            {
                if (bytes != stream.Read(b, 0, bytes))
                {
                    throw new Exception("number of bytes read from file != reported length of file: " + f.fileInfo.Name);
                }
            }

            if (f.BootInfoTable)
            {
                // TODO FIXME - this is TERRIBLE. This should be implemented at a higher level, and
                // doing it here requires passing the primaryVolumeDescriptor to every call of WriteFile()
                // The reason it is here is because this is the only place where the file actually gets
                // pulled into memory and I didn't want to modify the boot image on-disk like mkisofs does.
                Bytes(b, 0, 8);
                Bytes(ConvertTo.Int2LSB(primaryVolumeDescriptor));
                Bytes(ConvertTo.Int2LSB(f.DataBlock));
                Bytes(ConvertTo.Int2LSB((int)f.fileInfo.Length));
                Bytes(ConvertTo.Int2LSB(0));    // TODO FIXME - checksum
                DupByte(0, 40);                 // reserved
                Bytes(b, 64, bytes - 64);
            }
            else
            {
                Bytes(b);
            }
        }
        /// <summary>
        /// add a file to the ISO ( common implementation - called by AddFile() and AddBootFile() )
        /// </summary>
        private IsoFile AddFileEx(string path, FileInfo fileInfo)
        {
            string key;

            string[]  ar = NormalizePath(path).Split('/');
            int       i;
            IsoFolder f = this.isoRoot;

            for (i = 0; i < ar.Length - 1; i++)
            {
                key = ar[i].Trim().ToLower();
                if (!f.entries.ContainsKey(key))
                {
                    var subf = new IsoFolder();
                    subf.Name      = ar[i].Trim();
                    f.entries[key] = subf;
                }
                IsoEntry e = f.entries[key];
                if (e.IsFile)
                {
                    throw new Exception("cannot create directory \"" + ar[i].Trim() + "\", a file by that Name already exists");
                    //return;
                }
                f = (IsoFolder)e;
            }
            var x = new IsoFile(fileInfo);

            x.Name = ar[i].Trim();
            key    = ar[i].Trim().ToLower();
            if (f.entries.ContainsKey(key))
            {
                //throw new Exception("file or folder by that Name already exists");
                return((IsoFile)f.entries[key]);                // just don't add it for now...
            }
            f.entries[key] = x;

            return(x);
        }
Beispiel #5
0
		private void GenFile(IsoFile f)
		{
			f.DataBlock = this.generator.Index / LogicalBlockSize;
			f.DataLength = (int)f.fileInfo.Length;
			this.generator.WriteFile(f, PrimaryVolumeDescriptor);
			this.generator.FinishBlock();
		}
Beispiel #6
0
		private void GenBootCatalog(IsoFile f)
		{
			BootCatalog = this.generator.Index / LogicalBlockSize;
			// write validation entry first... see El Torito section 2.1
			var ve = new FieldValidator(this.generator);
			ve.Byte(1, 1); // Header ID, must be 0x01
			ve.Byte(0, 2); // 0 == x86 - TODO FIXME: 1 == PowerPC, 2 == Mac, see El Torito figure 2
			ve.DupByte(0, 3, 4); // Reserved
			ve.DupByte(0, 5, 0x1C); // Manufacturer/Developer of CD-ROM, see El Torito figure 2
			ve.ShortLSB(0x55AA, 0x1D, 0x1E); // checksum - TODO FIXME - allow custom Manufacturer string - calculate checksum dynamically
			ve.Byte(0x55, 0x1F); // 1st Key Byte
			ve.Byte(0xAA, 0x20); // 2nd Key Byte

			// initial/default entry... see El Torito section 2.2 and figure 3
			var ide = new FieldValidator(this.generator);
			ide.Byte(0x88, 1); // 0x88 = bootable, 0x00 = not bootable

			// TODO FIXME - this is extremely hackish... fix me...
			ide.Byte(0, 2); // no emulation
			/*if ( f.fileInfo.Length <= 1182720 )
				ide.Byte(1, 2); // 1.2 meg diskette
			else if ( f.fileInfo.Length <= 1440 * 1024 )
				ide.Byte(2,2); // 1.44 meg diskette
			else if ( f.fileInfo.Length <= 2880 * 1024 )
				ide.Byte(3,2); // 2.88 meg diskette
			else
				ide.Byte(4,2);*/
			// Hard Disk ( drive 80 )

			ide.ShortLSB(0, 3, 4); // Load Segment - 0 == default of 0x7C0
			ide.Byte(0, 5); // System Type, according to El Torito figure 3 this MUST be a copy of the "System Type" from the boot image. In practice this appears to not be the case.
			ide.Byte(0, 6); // Unused, must be 0
			if (this.bootLoadSize == 0)
				this.bootLoadSize = (short)((f.fileInfo.Length - 1) / 0x200 + 1);
			ide.ShortLSB(this.bootLoadSize, 7, 8); // Sector Count
			ide.IntLSB(this.boot.DataBlock, 9, 12); // Logical Block of boot image
			ide.Zero(13, 32); // unused

			this.generator.FinishBlock();
		}
Beispiel #7
0
		/// <summary>
		/// add a file to the ISO ( common implementation - called by AddFile() and AddBootFile() )
		/// </summary>
		private IsoFile AddFileEx(string path, FileInfo fileInfo)
		{
			string key;
			string[] ar = NormalizePath(path).Split('/');
			int i;
			IsoFolder f = this.isoRoot;
			for (i = 0; i < ar.Length - 1; i++) {
				key = ar[i].Trim().ToLower();
				if (!f.entries.ContainsKey(key)) {
					var subf = new IsoFolder();
					subf.Name = ar[i].Trim();
					f.entries[key] = subf;
				}
				IsoEntry e = f.entries[key];
				if (e.IsFile) {
					throw new Exception("cannot create directory \"" + ar[i].Trim() + "\", a file by that Name already exists");
					//return;
				}
				f = (IsoFolder)e;
			}
			var x = new IsoFile(fileInfo);
			x.Name = ar[i].Trim();
			key = ar[i].Trim().ToLower();
			if (f.entries.ContainsKey(key)) {
				//throw new Exception("file or folder by that Name already exists");
				return (IsoFile)f.entries[key]; // just don't add it for now...
			}
			f.entries[key] = x;

			return x;
		}
Beispiel #8
0
		/// <summary>
		/// writes a file out to cd. Generate the Boot Info Table if necessary
		/// </summary>
		/// <param Name="f">the file to write</param>
		/// <param Name="primaryVolumeDescriptor">the PVD block, passed in case we need to generate the Boot Info Table</param>
		public void WriteFile(IsoFile f, int primaryVolumeDescriptor)
		{
			if (f.fileInfo.Length > 0xffffffff)
				throw new NotImplementedException(">4G files not implemented");

			int bytes = (int)f.fileInfo.Length;
			if (this.fs == null)
			{
				this.Index += bytes;
				return;
			}

			// TODO FIXME - create smaller reusable buffer and read fixed-size chunks at a time...
			byte[] b = new byte[bytes];

			using (FileStream stream = f.fileInfo.OpenRead())
			{
				if (bytes != stream.Read(b, 0, bytes))
					throw new Exception("number of bytes read from file != reported length of file: " + f.fileInfo.Name);
			}

			if (f.BootInfoTable)
			{
				// TODO FIXME - this is TERRIBLE. This should be implemented at a higher level, and
				// doing it here requires passing the primaryVolumeDescriptor to every call of WriteFile()
				// The reason it is here is because this is the only place where the file actually gets
				// pulled into memory and I didn't want to modify the boot image on-disk like mkisofs does.
				Bytes(b, 0, 8);
				Bytes(ConvertTo.Int2LSB(primaryVolumeDescriptor));
				Bytes(ConvertTo.Int2LSB(f.DataBlock));
				Bytes(ConvertTo.Int2LSB((int)f.fileInfo.Length));
				Bytes(ConvertTo.Int2LSB(0)); // TODO FIXME - checksum
				DupByte(0, 40); // reserved
				Bytes(b, 64, bytes - 64);
			}
			else
				Bytes(b);
		}
        private string DirectoryRecordEx(byte[] fileName, string realName, IsoEntry e, byte root, bool secondPass)
        {
            byte[] /*b_fi,*/ b_su = null;

            /*if (fileName == ".")
             * {
             *      b_fi = new byte[] { 0 };
             *      realName = "";
             * }
             * else if (fileName == "..")
             * {
             *      b_fi = new byte[] { 1 };
             *      realName = "";
             * }
             * else
             *      b_fi = generator.Ascii.GetBytes(fileName);*/
            byte LEN_FI     = (byte)fileName.Length;
            byte LEN_DR     = (byte)(33 + LEN_FI);
            bool fi_padding = ((LEN_DR & 1) != 0);

            if (fi_padding)
            {
                LEN_DR++;
            }
            // as much as I HATE to do it, I have to generate this data in both passes for now.
            // I don't yet understand enough about what and how many DR entries have to be made to figure out how to do it "right"
            byte LEN_SU = 0;

#if ROCKRIDGE
            if (root != 1)             // don't generate susp on PVD's root entry...
            {
                b_su = Susp(ref realName, e, root == 2, secondPass, (byte)(255 - LEN_DR));
                if (b_su.Length > 255)
                {
                    throw new NotImplementedException("can't yet handle SUSP > 255 bytes");
                }
                LEN_SU = (byte)b_su.Length;
            }
            else
            {
                realName = "";
            }
#endif
            LEN_DR += LEN_SU;

            var dr = new FieldValidator(this.generator);
            dr.Byte(LEN_DR, 1);               // Length of Directory Record ( 9.1.1 )
            dr.Byte(0, 2);                    // Extended Attribute Record Length ( 9.1.2 )
            dr.IntLSBMSB(e.DataBlock, 3, 10); // Location of Extent ( 9.1.3 )
#if true
            // in this test - I round the data length up to the next multiple of 2048, didn't help fix my booting problem though...
            dr.IntLSBMSB(((e.DataLength - 1) / 2048 + 1) * 2048, 11, 18); // Data Length ( 9.1.4 )
#else
            dr.IntLSBMSB(e.DataLength, 11, 18);                           // Data Length ( 9.1.4 )
#endif
            dr.BinaryDateTime(System.DateTime.Now, 19, 25);               // Recording Date and Time ( 9.1.5 )
            byte flags = 0;
            if (e.IsFile)
            {
                IsoFile f = (IsoFile)e;
                if ((f.fileInfo.Attributes & FileAttributes.Hidden) != 0)
                {
                    flags |= 1;                     // hidden
                }
            }
            else
            {
                // TODO FIXME - not supporting hidden folders right now
                //IsoFolder f = (IsoFolder)e;
                //if ((f.dirInfo.Attributes & DirectoryAttributes.Hidden) != 0)
                //    flags |= 1; // hidden
            }
            if (e.IsFolder)
            {
                flags |= 2; // directory
            }
#if false                   // I'm disabling this because analysing of a working ISO never sets this bit...
            if (real_name.Length == 0)
            {
                flags |= 128;                 // final
            }
#endif
            dr.Byte(flags, 26);         // flags ( 9.1.6 )
            dr.Byte(0, 27);             // File Unit Size ( 9.1.7 )
            dr.Byte(0, 28);             // Interleave Gap Size ( 9.1.8 )
            dr.ShortLSBMSB(1, 29, 32);  // Volume Sequence Number ( 9.1.9 )
            dr.Byte(LEN_FI, 33);        // Length of File Identifier ( 9.1.10 )
            dr.Bytes(fileName, 34, 33 + LEN_FI);
            if (fi_padding)
            {
                dr.Zero(34 + LEN_FI, 34 + LEN_FI);
            }
            if (LEN_SU > 0)
            {
                dr.Bytes(b_su, LEN_DR - LEN_SU + 1, LEN_DR);
            }

            return(realName);
        }