From 7285a491c1ce1e630a0751b1011fd33e6b17234b Mon Sep 17 00:00:00 2001 From: wkj Date: Thu, 17 Jun 2004 01:47:21 +0000 Subject: 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. --- src/cmd/9660/path.c | 155 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 src/cmd/9660/path.c (limited to 'src/cmd/9660/path.c') diff --git a/src/cmd/9660/path.c b/src/cmd/9660/path.c new file mode 100644 index 00000000..f2757dba --- /dev/null +++ b/src/cmd/9660/path.c @@ -0,0 +1,155 @@ +#include +#include +#include +#include + +#include "iso9660.h" + +/* + * Add the requisite path tables to the CD image. + * They get put on the end once everything else is done. + * We use the path table itself as a queue in the breadth-first + * traversal of the tree. + * + * The only problem with this is that the path table does not + * store the lengths of the directories. So we keep an explicit + * map in an array in memory. + */ + +enum { + Big, + Little +}; + +static void +Crdpath(Cdimg *cd, Cpath *p) +{ + p->namelen = Cgetc(cd); + if(p->namelen == 0) { + Crseek(cd, (Croffset(cd)+Blocksize-1)/Blocksize * Blocksize); + p->namelen = Cgetc(cd); + assert(p->namelen != 0); + } + + p->xlen = Cgetc(cd); + assert(p->xlen == 0); /* sanity, might not be true if we start using the extended fields */ + + Cread(cd, p->dloc, 4); + Cread(cd, p->parent, 2); + p->name[0] = '\0'; + Crseek(cd, Croffset(cd)+p->namelen+p->xlen+(p->namelen&1)); /* skip name, ext data */ +} + +static void +writepath(Cdimg *cd, Cdir *c, int parent, int size) +{ +/* + DO NOT UNCOMMENT THIS CODE. + This commented-out code is here only so that no one comes + along and adds it later. + + The ISO 9660 spec is silent about whether path table entries + need to be padded so that they never cross block boundaries. + It would be reasonable to assume that they are like every other + data structure in the bloody spec; this code pads them out. + + Empirically, though, they're NOT padded. Windows NT and + derivatives are the only known current operating systems + that actually read these things. + + int l; + + l = 1+1+4+2+c->namelen; + if(Cwoffset(cd)/Blocksize != (Cwoffset(cd)+l)/Blocksize) + Cpadblock(cd); +*/ + Cputc(cd, c->namelen); + Cputc(cd, 0); + Cwrite(cd, c->dloc + (size==Little ? 0 : 4), 4); + (size==Little ? Cputnl : Cputnm)(cd, parent, 2); + Cwrite(cd, c->name, c->namelen); + if(c->namelen & 1) + Cputc(cd, 0); +} + +static ulong* +addlength(ulong *a, ulong x, int n) +{ + if(n%128==0) + a = erealloc(a, (n+128)*sizeof a[0]); + a[n] = x; + return a; +} + +static ulong +writepathtable(Cdimg *cd, ulong vdblock, int size) +{ + int rp, wp; + uchar buf[Blocksize]; + ulong bk, end, i, *len, n, rdoff, start; + Cdir *c; + Cpath p; + + Creadblock(cd, buf, vdblock, Blocksize); + c = (Cdir*)(buf+offsetof(Cvoldesc, rootdir[0])); + + rp = 0; + wp = 0; + len = nil; + start = cd->nextblock*Blocksize; + Cwseek(cd, start); + Crseek(cd, start); + writepath(cd, c, 1, size); + len = addlength(len, little(c->dlen, 4), wp); + wp++; + + while(rp < wp) { + Crdpath(cd, &p); + n = (len[rp]+Blocksize-1)/Blocksize; + rp++; + bk = (size==Big ? big : little)(p.dloc, 4); + rdoff = Croffset(cd); + for(i=0; inamelen == 1 && c->name[0] == '\0') /* hit another directory; stop */ + break; + while(c->len && c->namelen && (uchar*)c+c->len < buf+Blocksize) { + if((c->flags & 0x02) && (c->namelen > 1 || c->name[0] > '\001')) { /* directory */ + writepath(cd, c, rp, size); + len = addlength(len, little(c->dlen, 4), wp); + wp++; + } + c = (Cdir*)((uchar*)c+c->len); + } + } + Crseek(cd, rdoff); + } + end = Cwoffset(cd); + Cpadblock(cd); + return end-start; +} + + +static void +writepathtablepair(Cdimg *cd, ulong vdblock) +{ + ulong bloc, lloc, sz, sz2; + + lloc = cd->nextblock; + sz = writepathtable(cd, vdblock, Little); + bloc = cd->nextblock; + sz2 = writepathtable(cd, vdblock, Big); + assert(sz == sz2); + setpathtable(cd, vdblock, sz, lloc, bloc); +} + +void +writepathtables(Cdimg *cd) +{ + cd->pathblock = cd->nextblock; + + writepathtablepair(cd, cd->iso9660pvd); + if(cd->flags & CDjoliet) + writepathtablepair(cd, cd->jolietsvd); +} -- cgit v1.2.3