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.
This commit is contained in:
parent
e1dddc0532
commit
7285a491c1
20 changed files with 4375 additions and 0 deletions
402
src/cmd/9660/dump9660.c
Normal file
402
src/cmd/9660/dump9660.c
Normal file
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue