use fmt; use os; use io; use fs; use strings; use errors; use rt; use getopt; use cmd; use mbr; use gpt; use sector; export fn convert(args: []str) void = { let nombr = false; let notranslation = false; let nohybrid = false; const c = getopt::parse(args, ('m', "do not overwrite the MBR bootstrap"), ('t', "do not translate partitions to GPT"), ('H', "do not create a hybrid MBR"), "disk file" ); defer getopt::finish(&c); for (let i = 0z; i < len(c.opts); i += 1) { const opt = c.opts[i]; switch (opt.0) { case 'm' => nombr = true; case 't' => notranslation = true; case 'H' => nohybrid = true; }; }; if (len(c.args) < 1) fmt::fatalf("gpt.convert: need a disk file"); let sourcefd = match (os::open(c.args[0], fs::flags::RDONLY)) { case let f: io::file => yield f; case => fmt::fatalf("gpt.convert: could not open file {}", args[1]); }; defer io::close(sourcefd)!; const source = mbr::from(sourcefd)!; defer mbr::finish(source); let fd = cmd::openfile(); defer io::close(fd)!; let vol = cmd::opengpt(fd); defer { vol.mbr.entries[3] = mbr::entry { part_type = 0xEE, lba_begin = 0, length = -1: u32, ... }; gpt::chksums(vol); gpt::commit(vol)!; gpt::finish(vol); }; if (!nombr) rt::memcpy(vol.mbr, source.bootsector, size(mbr::bootsector)); if (notranslation) return; for (let i = 0z; i < 4; i += 1) { const entry = &source.bootsector.entries[i]; if (entry.lba_begin == 0 && entry.length == 0) continue; const reader = mbr::partstream_reader(source, entry)!; const partlength = entry.length; const part = match (gpt::allocate(vol, partlength)) { case let e: *gpt::entry => yield e; case => fmt::errorfln("gpt.convert: could not allocate size needed for MBR partition {}", i)!; continue; }; const writer = gpt::partstream_writer(vol, part)!; io::copy(&writer, &reader)!; if (!nohybrid) { vol.mbr.entries[i].lba_begin = part.lba_begin: u32; vol.mbr.entries[i].length = (part.lba_end - part.lba_begin + 1): u32; }; }; };