123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- #include <u.h>
- #include <libc.h>
- #include <bio.h>
- #include <libsec.h>
- #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; i<n; i++) {
- Creadblock(cd, buf, bk+i, Blocksize);
- c = (Cdir*)buf;
- if(i != 0 && c->namelen == 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);
- }
|