henesyinit from p9fd787fda5 years agoHistory
141 lines · 3.0 KB · C
RawDownload
#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 voidCrdpath(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 voidwritepath(Cdimg *cd, Cdir *c, int parent, int size){	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 ulongwritepathtable(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 voidwritepathtablepair(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);} voidwritepathtables(Cdimg *cd){	cd->pathblock = cd->nextblock; 	writepathtablepair(cd, cd->iso9660pvd);	if(cd->flags & CDjoliet)		writepathtablepair(cd, cd->jolietsvd);}