aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/9660/dump9660.c
diff options
context:
space:
mode:
authorwkj <devnull@localhost>2004-06-17 01:47:21 +0000
committerwkj <devnull@localhost>2004-06-17 01:47:21 +0000
commit7285a491c1ce1e630a0751b1011fd33e6b17234b (patch)
treeb2b2e24e333fa4660325a35f6c0f1d333e50e797 /src/cmd/9660/dump9660.c
parente1dddc053287874e82e2b67f95ccee7d7bc63e22 (diff)
downloadplan9port-7285a491c1ce1e630a0751b1011fd33e6b17234b.tar.gz
plan9port-7285a491c1ce1e630a0751b1011fd33e6b17234b.tar.bz2
plan9port-7285a491c1ce1e630a0751b1011fd33e6b17234b.zip
Dump9660 (and mk9660). Until we either do something
intelligent with symlinks or put in a switch for things like dump9660, this is of rather limited utility under Unix.
Diffstat (limited to 'src/cmd/9660/dump9660.c')
-rw-r--r--src/cmd/9660/dump9660.c402
1 files changed, 402 insertions, 0 deletions
diff --git a/src/cmd/9660/dump9660.c b/src/cmd/9660/dump9660.c
new file mode 100644
index 00000000..320e56d3
--- /dev/null
+++ b/src/cmd/9660/dump9660.c
@@ -0,0 +1,402 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <disk.h>
+#include <libsec.h>
+#include "iso9660.h"
+
+ulong now;
+int chatty;
+int doabort;
+int docolon;
+int mk9660;
+Conform *map;
+
+static void addprotofile(char *new, char *old, Dir *d, void *a);
+void usage(void);
+
+char *argv0;
+
+void
+usage(void)
+{
+ if(mk9660)
+ fprint(2, "usage: disk/mk9660 [-D:] [-9cjr] [-b bootfile] [-p proto] [-s src] cdimage\n");
+ else
+ fprint(2, "usage: disk/dump9660 [-D:] [-9cjr] [-m maxsize] [-n now] [-p proto] [-s src] cdimage\n");
+ exits("usage");
+}
+
+int
+main(int argc, char **argv)
+{
+ int fix;
+ char buf[256], *dumpname, *proto, *s, *src, *status;
+ ulong block, length, newnull, cblock, clength, maxsize;
+ Cdimg *cd;
+ Cdinfo info;
+ XDir dir;
+ Direc *iconform, idumproot, iroot, *jconform, jdumproot, jroot, *r;
+ Dump *dump;
+
+ fix = 0;
+ status = nil;
+ memset(&info, 0, sizeof info);
+ proto = "/sys/lib/sysconfig/proto/allproto";
+ src = "./";
+
+ info.volumename = atom("9CD");
+ info.volumeset = atom("9VolumeSet");
+ info.publisher = atom("9Publisher");
+ info.preparer = atom("dump9660");
+ info.application = atom("dump9660");
+ info.flags = CDdump;
+ maxsize = 0;
+ mk9660 = 0;
+ fmtinstall('H', encodefmt);
+
+ ARGBEGIN{
+ case 'D':
+ chatty++;
+ break;
+ case 'M':
+ mk9660 = 1;
+ argv0 = "disk/mk9660";
+ info.flags &= ~CDdump;
+ break;
+ case '9':
+ info.flags |= CDplan9;
+ break;
+ case ':':
+ docolon = 1;
+ break;
+ case 'a':
+ doabort = 1;
+ break;
+ case 'b':
+ if(!mk9660)
+ usage();
+ info.flags |= CDbootable;
+ info.bootimage = EARGF(usage());
+ break;
+ case 'c':
+ info.flags |= CDconform;
+ break;
+ case 'f':
+ fix = 1;
+ break;
+ case 'j':
+ info.flags |= CDjoliet;
+ break;
+ case 'n':
+ now = atoi(EARGF(usage()));
+ break;
+ case 'm':
+ maxsize = strtoul(EARGF(usage()), 0, 0);
+ break;
+ case 'p':
+ proto = EARGF(usage());
+ break;
+ case 'r':
+ info.flags |= CDrockridge;
+ break;
+ case 's':
+ src = EARGF(usage());
+ break;
+ case 'v':
+ info.volumename = atom(EARGF(usage()));
+ break;
+ default:
+ usage();
+ }ARGEND
+
+ if(mk9660 && (fix || now || maxsize))
+ usage();
+
+ if(argc != 1)
+ usage();
+
+ if(now == 0)
+ now = (ulong)time(0);
+ if(mk9660){
+ if((cd = createcd(argv[0], info)) == nil)
+ sysfatal("cannot create '%s': %r", argv[0]);
+ }else{
+ if((cd = opencd(argv[0], info)) == nil)
+ sysfatal("cannot open '%s': %r", argv[0]);
+ if(!(cd->flags & CDdump))
+ sysfatal("not a dump cd");
+ }
+
+ /* create ISO9660/Plan 9 tree in memory */
+ memset(&dir, 0, sizeof dir);
+ dir.name = atom("");
+ dir.uid = atom("sys");
+ dir.gid = atom("sys");
+ dir.uidno = 0;
+ dir.gidno = 0;
+ dir.mode = DMDIR | 0755;
+ dir.mtime = now;
+ dir.atime = now;
+ dir.ctime = now;
+
+ mkdirec(&iroot, &dir);
+ iroot.srcfile = src;
+
+ /*
+ * Read new files into memory
+ */
+ if(rdproto(proto, src, addprotofile, nil, &iroot) < 0)
+ sysfatal("rdproto: %r");
+
+ if(mk9660){
+ dump = emalloc(sizeof *dump);
+ dumpname = nil;
+ }else{
+ /*
+ * Read current dump tree and _conform.map.
+ */
+ idumproot = readdumpdirs(cd, &dir, isostring);
+ readdumpconform(cd);
+ if(cd->flags & CDjoliet)
+ jdumproot = readdumpdirs(cd, &dir, jolietstring);
+
+ if(fix){
+ dumpname = nil;
+ cd->nextblock = cd->nulldump+1;
+ cd->nulldump = 0;
+ Cwseek(cd, cd->nextblock*Blocksize);
+ goto Dofix;
+ }
+
+ dumpname = adddumpdir(&idumproot, now, &dir);
+ /* note that we assume all names are conforming and thus sorted */
+ if(cd->flags & CDjoliet) {
+ s = adddumpdir(&jdumproot, now, &dir);
+ if(s != dumpname)
+ sysfatal("dumpnames don't match %s %s\n", dumpname, s);
+ }
+ dump = dumpcd(cd, &idumproot);
+ cd->nextblock = cd->nulldump+1;
+ }
+
+ /*
+ * Write new files, starting where the dump tree was.
+ * Must be done before creation of the Joliet tree so that
+ * blocks and lengths are correct.
+ */
+ Cwseek(cd, cd->nextblock*Blocksize);
+ writefiles(dump, cd, &iroot);
+
+ if(cd->bootimage){
+ findbootimage(cd, &iroot);
+ Cupdatebootcat(cd);
+ }
+
+ /* create Joliet tree */
+ if(cd->flags & CDjoliet)
+ copydirec(&jroot, &iroot);
+
+ if(info.flags & CDconform) {
+ checknames(&iroot, isbadiso9660);
+ convertnames(&iroot, struprcpy);
+ } else
+ convertnames(&iroot, (void *) strcpy);
+
+// isoabstract = findconform(&iroot, abstract);
+// isobiblio = findconform(&iroot, biblio);
+// isonotice = findconform(&iroot, notice);
+
+ dsort(&iroot, isocmp);
+
+ if(cd->flags & CDjoliet) {
+ // jabstract = findconform(&jroot, abstract);
+ // jbiblio = findconform(&jroot, biblio);
+ // jnotice = findconform(&jroot, notice);
+
+ checknames(&jroot, isbadjoliet);
+ convertnames(&jroot, (void *) strcpy);
+ dsort(&jroot, jolietcmp);
+ }
+
+ /*
+ * Write directories.
+ */
+ writedirs(cd, &iroot, Cputisodir);
+ if(cd->flags & CDjoliet)
+ writedirs(cd, &jroot, Cputjolietdir);
+
+ if(mk9660){
+ cblock = 0;
+ clength = 0;
+ newnull = 0;
+ }else{
+ /*
+ * Write incremental _conform.map block.
+ */
+ wrconform(cd, cd->nconform, &cblock, &clength);
+
+ /* jump here if we're just fixing up the cd */
+Dofix:
+ /*
+ * Write null dump header block; everything after this will be
+ * overwritten at the next dump. Because of this, it needs to be
+ * reconstructable. We reconstruct the _conform.map and dump trees
+ * from the header blocks in dump.c, and we reconstruct the path
+ * tables by walking the cd.
+ */
+ newnull = Cputdumpblock(cd);
+ }
+
+ /*
+ * Write _conform.map.
+ */
+ dir.mode = 0444;
+ if(cd->flags & (CDconform|CDjoliet)) {
+ if(!mk9660 && cd->nconform == 0){
+ block = cblock;
+ length = clength;
+ }else
+ wrconform(cd, 0, &block, &length);
+
+ if(mk9660)
+{
+ idumproot = iroot;
+ jdumproot = jroot;
+ }
+ if(length) {
+ /* The ISO9660 name will get turned into uppercase when written. */
+ if((iconform = walkdirec(&idumproot, "_conform.map")) == nil)
+ iconform = adddirec(&idumproot, "_conform.map", &dir);
+ jconform = nil;
+ if(cd->flags & CDjoliet) {
+ if((jconform = walkdirec(&jdumproot, "_conform.map")) == nil)
+ jconform = adddirec(&jdumproot, "_conform.map", &dir);
+ }
+ iconform->block = block;
+ iconform->length = length;
+ if(cd->flags & CDjoliet) {
+ jconform->block = block;
+ jconform->length = length;
+ }
+ }
+ if(mk9660) {
+ iroot = idumproot;
+ jroot = jdumproot;
+ }
+ }
+
+ if(mk9660){
+ /*
+ * Patch in root directories.
+ */
+ setroot(cd, cd->iso9660pvd, iroot.block, iroot.length);
+ setvolsize(cd, cd->iso9660pvd, cd->nextblock*Blocksize);
+ if(cd->flags & CDjoliet){
+ setroot(cd, cd->jolietsvd, jroot.block, jroot.length);
+ setvolsize(cd, cd->jolietsvd, cd->nextblock*Blocksize);
+ }
+ }else{
+ /*
+ * Write dump tree at end. We assume the name characters
+ * are all conforming, so everything is already sorted properly.
+ */
+ convertnames(&idumproot, (info.flags & CDconform) ? (void *) struprcpy : (void *) strcpy);
+ if(cd->nulldump) {
+ r = walkdirec(&idumproot, dumpname);
+ assert(r != nil);
+ copybutname(r, &iroot);
+ }
+ if(cd->flags & CDjoliet) {
+ convertnames(&jdumproot, (void *) strcpy);
+ if(cd->nulldump) {
+ r = walkdirec(&jdumproot, dumpname);
+ assert(r != nil);
+ copybutname(r, &jroot);
+ }
+ }
+
+ writedumpdirs(cd, &idumproot, Cputisodir);
+ if(cd->flags & CDjoliet)
+ writedumpdirs(cd, &jdumproot, Cputjolietdir);
+
+ /*
+ * Patch in new root directory entry.
+ */
+ setroot(cd, cd->iso9660pvd, idumproot.block, idumproot.length);
+ setvolsize(cd, cd->iso9660pvd, cd->nextblock*Blocksize);
+ if(cd->flags & CDjoliet){
+ setroot(cd, cd->jolietsvd, jdumproot.block, jdumproot.length);
+ setvolsize(cd, cd->jolietsvd, cd->nextblock*Blocksize);
+ }
+ }
+ writepathtables(cd);
+
+ if(!mk9660){
+ /*
+ * If we've gotten too big, truncate back to what we started with,
+ * fix up the cd, and exit with a non-zero status.
+ */
+ Cwflush(cd);
+ if(cd->nulldump && maxsize && Cwoffset(cd) > maxsize){
+ fprint(2, "too big; writing old tree back\n");
+ status = "cd too big; aborted";
+
+ rmdumpdir(&idumproot, dumpname);
+ rmdumpdir(&jdumproot, dumpname);
+
+ cd->nextblock = cd->nulldump+1;
+ cd->nulldump = 0;
+ Cwseek(cd, cd->nextblock*Blocksize);
+ goto Dofix;
+ }
+
+ /*
+ * Write old null header block; this commits all our changes.
+ */
+ if(cd->nulldump){
+ Cwseek(cd, cd->nulldump*Blocksize);
+ sprint(buf, "plan 9 dump cd\n");
+ sprint(buf+strlen(buf), "%s %lud %lud %lud %lud %lud %lud",
+ dumpname, now, newnull, cblock, clength, iroot.block,
+ iroot.length);
+ if(cd->flags & CDjoliet)
+ sprint(buf+strlen(buf), " %lud %lud",
+ jroot.block, jroot.length);
+ strcat(buf, "\n");
+ Cwrite(cd, buf, strlen(buf));
+ Cpadblock(cd);
+ Cwflush(cd);
+ }
+ }
+ fdtruncate(cd->fd, cd->nextblock*Blocksize);
+ exits(status);
+ return 0;
+}
+
+static void
+addprotofile(char *new, char *old, Dir *d, void *a)
+{
+ char *name, *p;
+ Direc *direc;
+ XDir xd;
+
+ dirtoxdir(&xd, d);
+ name = nil;
+ if(docolon && strchr(new, ':')) {
+ name = emalloc(strlen(new)+1);
+ strcpy(name, new);
+ while((p=strchr(name, ':')))
+ *p=' ';
+ new = name;
+ }
+ if((direc = adddirec((Direc*)a, new, &xd))) {
+ direc->srcfile = atom(old);
+
+ // BUG: abstract, biblio, notice
+ }
+ if(name)
+ free(name);
+
+}
+