diff options
author | wkj <devnull@localhost> | 2004-06-17 01:47:21 +0000 |
---|---|---|
committer | wkj <devnull@localhost> | 2004-06-17 01:47:21 +0000 |
commit | 7285a491c1ce1e630a0751b1011fd33e6b17234b (patch) | |
tree | b2b2e24e333fa4660325a35f6c0f1d333e50e797 /src/cmd/9660/dump9660.c | |
parent | e1dddc053287874e82e2b67f95ccee7d7bc63e22 (diff) | |
download | plan9port-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.c | 402 |
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); + +} + |