Exemplo n.º 1
0
        static int dir_sorter(AnnotatedFSO a, AnnotatedFSO b)
        {
            var fname_len = Math.Max(a.FName.Length, b.FName.Length);
            var afn       = a.FName.PadRight(fname_len);
            var bfn       = b.FName.PadRight(fname_len);

            var fn_cmp = string.CompareOrdinal(afn, bfn);

            if (fn_cmp != 0)
            {
                return(fn_cmp);
            }

            var ext_len = Math.Max(a.Ext == null ? 0 : a.Ext.Length, b.Ext == null ? 0 : b.Ext.Length);
            var aext    = (a.Ext ?? "").PadRight(ext_len);
            var bext    = (b.Ext ?? "").PadRight(ext_len);

            return(string.CompareOrdinal(aext, bext));
        }
Exemplo n.º 2
0
        private static AnnotatedFSO doscache_add(FileSystemInfo d, AnnotatedFSO parent, Dictionary <string, List <AnnotatedFSO> > doscache, bool is_root = false)
        {
            var dosname = build_dosname(d, is_root, out var dn2);

            if (!doscache.TryGetValue(dn2, out var dcl))
            {
                dcl           = new List <AnnotatedFSO>();
                doscache[dn2] = dcl;
            }

            var new_afso = new AnnotatedFSO();

            new_afso.fsi    = d;
            new_afso.Parent = parent;
            new_afso.FName  = dosname[0];
            new_afso.Ext    = dosname[1];
            dcl.Add(new_afso);

            var di = d as DirectoryInfo;

            if (di != null)
            {
                foreach (var c in di.GetFiles())
                {
                    new_afso.Children.Add(doscache_add(c, new_afso, doscache));
                }
                foreach (var c in di.GetDirectories())
                {
                    new_afso.Children.Add(doscache_add(c, new_afso, doscache));
                }
                if (Program.boot_catalog_d != null && Program.boot_catalog_d.Equals(di.FullName))
                {
                    new_afso.Children.Add(doscache_add(new BootCatalogFileInfo(), new_afso, doscache));
                }
            }

            return(new_afso);
        }
Exemplo n.º 3
0
        private static void build_path_table(AnnotatedFSO afso, List <byte> ret, bool lsb)
        {
            var id_len = afso.Identifier.Length;
            var pt_len = align(8 + id_len, 2);

            int cur_idx = ret.Count;

            ret.Add((byte)id_len);
            ret.Add(0);

            ret.AddRange(ToByteArray(afso.lba, 4, lsb));
            ret.AddRange(ToByteArray(afso.Parent == null ? 1 : afso.Parent.dir_idx, 2, lsb));

            foreach (var c in afso.Identifier)
            {
                ret.Add((byte)c);
            }

            while (ret.Count < (cur_idx + pt_len))
            {
                ret.Add(0);
            }
        }
Exemplo n.º 4
0
        private static void build_dir_tree(AnnotatedFSO cur_afso, List <byte> dir_tree, int base_lba,
                                           Dictionary <int, AnnotatedFSO> parent_dir_map)
        {
            int cur_lba = base_lba + dir_tree.Count / 2048;

            cur_afso.lba = cur_lba;

            int cur_count = dir_tree.Count;

            // Add "." and ".." entries, store their location for future patching up
            parent_dir_map[dir_tree.Count] = cur_afso;
            var b1 = build_dir_entry("\0", 0, 0, null, cur_afso.Parent == null);

            add_dir_entry(b1, dir_tree);
            parent_dir_map[dir_tree.Count] = cur_afso.Parent ?? cur_afso;
            var b2 = build_dir_entry("\u0001", 0, 0);

            add_dir_entry(b2, dir_tree);

            cur_afso.Children.Sort(dir_sorter);

            foreach (var c in cur_afso.Children)
            {
                if (c.fsi is FileInfo)
                {
                    add_dir_entry(build_dir_entry(c.Identifier, c.lba, (int)((FileInfo)c.fsi).Length, c.fsi), dir_tree);
                }
                else
                {
                    add_dir_entry(build_dir_entry(c.Identifier, c.lba, c.len, c.fsi), dir_tree);
                }
            }

            cur_afso.len = (int)align(dir_tree.Count - cur_count);

            align(dir_tree);
        }
Exemplo n.º 5
0
        static int sort_func(AnnotatedFSO a, AnnotatedFSO b)
        {
            if (a.Parent == null && b.Parent == null)
            {
                return(0);
            }
            else if (a.Parent == null)
            {
                return(-1);
            }
            else if (b.Parent == null)
            {
                return(1);
            }

            int pcompare = sort_func(a.Parent, b.Parent);

            if (pcompare != 0)
            {
                return(pcompare);
            }

            return(a.Identifier.CompareTo(b.Identifier));
        }
Exemplo n.º 6
0
        static void Main(string[] args)
        {
            if (!parse_args(args))
            {
                show_usage();
                return;
            }

            var d = new System.IO.DirectoryInfo(src_dir);

            var o = new System.IO.BinaryWriter(new System.IO.FileStream(ofname, System.IO.FileMode.Create));


            // Write 32 kiB of zeros to the system area
            o.Write(new byte[32 * 1024]);

            List <VolumeDescriptor> voldescs = new List <VolumeDescriptor>();

            // Add a primary volume descriptor
            var pvd = new PrimaryVolumeDescriptor();

            voldescs.Add(pvd);

            ElToritoBootDescriptor bvd = null;

            if (bootEntries.Count > 0)
            {
                bvd = new ElToritoBootDescriptor();
                voldescs.Add(bvd);
            }

            voldescs.Add(new VolumeDescriptorSetTerminator());

            // Generate directory tree
            List <AnnotatedFSO> files, dirs;
            var afso = AnnotatedFSO.BuildAFSOTree(d, out dirs, out files);

            // Allocate space for files + directories
            int cur_lba = 0x10 + voldescs.Count;

            List <AnnotatedFSO> output_order = new List <AnnotatedFSO>();
            AnnotatedFSO        afso_bc      = null;

            foreach (var file in files)
            {
                if (file.fsi is BootCatalogFileInfo)
                {
                    afso_bc = file;
                    continue;
                }
                var fi   = file.fsi as FileInfo;
                var l    = align(fi.Length);
                var lbal = l / 2048;

                file.lba = cur_lba;
                file.len = (int)fi.Length;
                cur_lba += (int)lbal;

                output_order.Add(file);

                foreach (var bfe in bootEntries)
                {
                    if (bfe.ffname != null && bfe.boot_table && bfe.ffname == fi.FullName)
                    {
                        file.needs_boot_table = true;
                        bfe.afso_boot_file    = file;
                    }
                }
            }

            // create boot catalog
            List <byte> bc     = new List <byte>();
            var         bc_lba = cur_lba;

            if (bootEntries.Count > 0)
            {
                // Validation entry
                List <byte> val_ent = new List <byte>();
                val_ent.Add(0x01);
                if (bootEntries[0].type == BootEntry.BootType.BIOS)
                {
                    val_ent.Add(0);
                }
                else
                {
                    val_ent.Add(0xef);
                }
                val_ent.Add(0);
                val_ent.Add(0);
                //val_ent.AddRange(Encoding.ASCII.GetBytes("isomake".PadRight(24)));
                for (int i = 0; i < 24; i++)
                {
                    val_ent.Add(0);
                }
                var cs = elt_checksum(val_ent, 0xaa55);
                val_ent.Add((byte)(cs & 0xff));
                val_ent.Add((byte)((cs >> 8) & 0xff));
                val_ent.Add(0x55);
                val_ent.Add(0xaa);
                bc.AddRange(val_ent);

                // default entry
                List <byte> def_ent = new List <byte>();
                if (bootEntries[0].bootable)
                {
                    def_ent.Add(0x88);
                }
                else
                {
                    def_ent.Add(0x00);
                }
                switch (bootEntries[0].etype)
                {
                case BootEntry.EmulType.Floppy:
                    def_ent.Add(0x02);
                    break;

                case BootEntry.EmulType.Hard:
                    def_ent.Add(0x04);
                    break;

                case BootEntry.EmulType.NoEmul:
                    def_ent.Add(0x00);
                    break;

                default:
                    throw new NotSupportedException();
                }
                def_ent.AddRange(BitConverter.GetBytes((ushort)bootEntries[0].load_seg));
                def_ent.Add(0x0);
                def_ent.Add(0x0);
                def_ent.AddRange(BitConverter.GetBytes((ushort)bootEntries[0].sector_count));
                if (bootEntries[0].afso_boot_file != null)
                {
                    def_ent.AddRange(BitConverter.GetBytes(bootEntries[0].afso_boot_file.lba));
                }
                else
                {
                    def_ent.AddRange(BitConverter.GetBytes((int)0));
                }
                for (int i = 0; i < 20; i++)
                {
                    def_ent.Add(0);
                }
                bc.AddRange(def_ent);

                for (int idx = 1; idx < bootEntries.Count; idx++)
                {
                    // section header
                    List <byte> sh = new List <byte>();
                    if (idx == bootEntries.Count - 1)
                    {
                        sh.Add(0x91);
                    }
                    else
                    {
                        sh.Add(0x90);
                    }
                    if (bootEntries[idx].type == BootEntry.BootType.BIOS)
                    {
                        sh.Add(0x0);
                    }
                    else
                    {
                        sh.Add(0xef);
                    }
                    sh.AddRange(BitConverter.GetBytes((ushort)1));
                    for (int i = 0; i < 28; i++)
                    {
                        sh.Add(0);
                    }
                    //sh.AddRange(Encoding.ASCII.GetBytes(bootEntries[idx].type.ToString().PadRight(28)));
                    bc.AddRange(sh);

                    // section entry
                    List <byte> se = new List <byte>();
                    if (bootEntries[idx].bootable)
                    {
                        se.Add(0x88);
                    }
                    else
                    {
                        se.Add(0x00);
                    }
                    switch (bootEntries[idx].etype)
                    {
                    case BootEntry.EmulType.Floppy:
                        se.Add(0x02);
                        break;

                    case BootEntry.EmulType.Hard:
                        se.Add(0x04);
                        break;

                    case BootEntry.EmulType.NoEmul:
                        se.Add(0x00);
                        break;

                    default:
                        throw new NotSupportedException();
                    }
                    se.AddRange(BitConverter.GetBytes((ushort)bootEntries[idx].load_seg));
                    se.Add(0);
                    se.Add(0);
                    se.AddRange(BitConverter.GetBytes((ushort)bootEntries[idx].sector_count));
                    if (bootEntries[idx].afso_boot_file != null)
                    {
                        se.AddRange(BitConverter.GetBytes((int)bootEntries[idx].afso_boot_file.lba));
                    }
                    else
                    {
                        se.AddRange(BitConverter.GetBytes((int)0));
                    }
                    se.Add(0);
                    for (int i = 0; i < 19; i++)
                    {
                        se.Add(0);
                    }
                    bc.AddRange(se);
                }

                afso_bc.lba = bc_lba;
                afso_bc.len = bc.Count;

                cur_lba += (int)align(bc.Count) / 2048;
            }

            // create root dir first entry continuation area containing rockridge attribute if required
            rr_ce = new List <byte>();
            if (do_rr)
            {
                // Use a spare sector to contain the 'ER' field as is it too big for the system use area
                // This is later referenced in a 'CE' entry
                rr_ce_lba = cur_lba++;

                // Add SUSP ER field to identify RR
                rr_ce.Add(0x45); rr_ce.Add(0x52); // "ER"
                var ext_id   = "IEEE_P1282";
                var ext_desc = "THE IEEE P1282 PROTOCOL PROVIDES SUPPORT FOR POSIX FILE SYSTEM SEMANTICS.";
                var ext_src  = "PLEASE CONTACT THE IEEE STANDARDS DEPARTMENT, PISCATAWAY, NJ, USA FOR THE P1282 SPECIFICATION.";
                rr_ce.Add((byte)(8 + ext_id.Length + ext_desc.Length + ext_src.Length)); // length
                rr_ce.Add(1);                                                            // version
                rr_ce.Add((byte)ext_id.Length);                                          // LEN_ID
                rr_ce.Add((byte)ext_desc.Length);                                        // LEN_DES
                rr_ce.Add((byte)ext_src.Length);                                         // LEN_SRC
                rr_ce.Add(1);                                                            // EXT_VER
                rr_ce.AddRange(Encoding.ASCII.GetBytes(ext_id));
                rr_ce.AddRange(Encoding.ASCII.GetBytes(ext_desc));
                rr_ce.AddRange(Encoding.ASCII.GetBytes(ext_src));
            }

            // build directory tree from most deeply nested to most shallow, so that we automatically patch up
            //  the appropriate child lbas as we go
            List <byte> dir_tree = new List <byte>();
            var         dt_lba   = cur_lba;
            Dictionary <int, AnnotatedFSO> parent_dir_map = new Dictionary <int, AnnotatedFSO>();

            for (int i = 7; i >= 0; i--)
            {
                var afso_level = afso[i];
                foreach (var cur_afso in afso_level)
                {
                    build_dir_tree(cur_afso, dir_tree, dt_lba, parent_dir_map);
                }
            }

            // patch up parent lbas
            foreach (var kvp in parent_dir_map)
            {
                var lba = kvp.Value.lba;
                var len = kvp.Value.len;

                var lba_b = int_lsb_msb(lba);
                var len_b = int_lsb_msb(len);

                insert_bytes(lba_b, kvp.Key + 2, dir_tree);
                insert_bytes(len_b, kvp.Key + 10, dir_tree);
            }

            // And root directory entry
            var root_entry = build_dir_entry("\0", afso[0][0].lba, afso[0][0].len, d);

            cur_lba += dir_tree.Count / 2048;

            // create path table
            var path_table_l_lba = cur_lba;

            byte[] path_table_l     = build_path_table(afso, true);
            var    path_table_b_lba = path_table_l_lba + (int)align(path_table_l.Length) / 2048;

            byte[] path_table_b = build_path_table(afso, false);

            cur_lba = path_table_b_lba + (int)align(path_table_b.Length) / 2048;

            // Set pvd entries
            pvd.WriteString("VolumeIdentifier", "UNNAMED");
            pvd.WriteInt("VolumeSpaceSize", cur_lba);
            pvd.WriteInt("VolumeSetSize", 1);
            pvd.WriteInt("VolumeSequenceNumber", 1);
            pvd.WriteInt("LogicalBlockSize", 2048);
            pvd.WriteInt("PathTableSize", path_table_l.Length);
            pvd.WriteInt("LocTypeLPathTable", path_table_l_lba);
            pvd.WriteInt("LocTypeMPathTable", path_table_b_lba);
            pvd.WriteBytes("RootDir", root_entry);

            if (bootEntries.Count > 0)
            {
                bvd.BootCatalogAddress = bc_lba;
            }

            // Write out volume descriptors
            foreach (var vd in voldescs)
            {
                vd.Write(o);
            }

            // files
            foreach (var f in output_order)
            {
                o.Seek(f.lba * 2048, SeekOrigin.Begin);
                var fin = new BinaryReader(((FileInfo)f.fsi).OpenRead());

                var b = fin.ReadBytes(f.len);

                if (f.needs_boot_table)
                {
                    // patch in the eltorito boot info table to offset 8

                    // first get 32 bit checksum from offset 64 onwards
                    uint csum = elt_checksum32(b, 64);
                    insert_bytes(BitConverter.GetBytes((int)0x10), 8, b);
                    insert_bytes(BitConverter.GetBytes((int)f.lba), 12, b);
                    insert_bytes(BitConverter.GetBytes((int)f.len), 16, b);
                    insert_bytes(BitConverter.GetBytes(csum), 20, b);
                }

                o.Write(b, 0, f.len);
            }

            // directory records
            o.Seek(dt_lba * 2048, SeekOrigin.Begin);
            o.Write(dir_tree.ToArray(), 0, dir_tree.Count);

            // path tables
            o.Seek(path_table_l_lba * 2048, SeekOrigin.Begin);
            o.Write(path_table_l, 0, path_table_l.Length);
            o.Seek(path_table_b_lba * 2048, SeekOrigin.Begin);
            o.Write(path_table_b, 0, path_table_b.Length);

            // boot catalog
            if (bootEntries.Count > 0)
            {
                o.Seek(bc_lba * 2048, SeekOrigin.Begin);

                o.Write(bc.ToArray(), 0, bc.Count);
            }

            // rr es field continuation area
            if (rr_ce != null)
            {
                o.Seek(rr_ce_lba * 2048, SeekOrigin.Begin);

                o.Write(rr_ce.ToArray(), 0, rr_ce.Count);
            }

            // Align to sector size
            o.Seek(0, SeekOrigin.End);
            while ((o.BaseStream.Position % 2048) != 0)
            {
                o.Write((byte)0);
            }

            // Add 300k padding - required for VirtualBox it seems
            //  According to 'man xorriso':
            //  "This is a traditional remedy for a traditional bug in block device read drivers."
            for (int i = 0; i < 300 * 1024 / 4; i++)
            {
                o.Write((int)0);
            }

            o.Close();
        }