ref: a3f2d6d23ed1be69fee607bdedadc0438fd01305
dir: /sys/src/cmd/disk/rd9660.c/
/* * dump a 9660 cd image for a little while. * for debugging. */ #include <u.h> #include <libc.h> #include <bio.h> #include <disk.h> Biobuf *b; #pragma varargck type "s" uchar* #pragma varargck type "L" uchar* #pragma varargck type "B" uchar* #pragma varargck type "N" uchar* #pragma varargck type "T" uchar* #pragma varargck type "D" uchar* typedef struct Voldesc Voldesc; struct Voldesc { uchar magic[8]; /* 0x01, "CD001", 0x01, 0x00 */ uchar systemid[32]; /* system identifier */ uchar volumeid[32]; /* volume identifier */ uchar unused[8]; /* character set in secondary desc */ uchar volsize[8]; /* volume size */ uchar charset[32]; uchar volsetsize[4]; /* volume set size = 1 */ uchar volseqnum[4]; /* volume sequence number = 1 */ uchar blocksize[4]; /* logical block size */ uchar pathsize[8]; /* path table size */ uchar lpathloc[4]; /* Lpath */ uchar olpathloc[4]; /* optional Lpath */ uchar mpathloc[4]; /* Mpath */ uchar ompathloc[4]; /* optional Mpath */ uchar rootdir[34]; /* root directory */ uchar volsetid[128]; /* volume set identifier */ uchar publisher[128]; uchar prepid[128]; /* data preparer identifier */ uchar applid[128]; /* application identifier */ uchar notice[37]; /* copyright notice file */ uchar abstract[37]; /* abstract file */ uchar biblio[37]; /* bibliographic file */ uchar cdate[17]; /* creation date */ uchar mdate[17]; /* modification date */ uchar xdate[17]; /* expiration date */ uchar edate[17]; /* effective date */ uchar fsvers; /* file system version = 1 */ }; void dumpbootvol(void *a) { Voldesc *v; v = a; print("magic %.2ux %.5s %.2ux %2ux\n", v->magic[0], v->magic+1, v->magic[6], v->magic[7]); if(v->magic[0] == 0xFF) return; print("system %.32T\n", v->systemid); print("volume %.32T\n", v->volumeid); print("volume size %.4N\n", v->volsize); print("charset %.2ux %.2ux %.2ux %.2ux %.2ux %.2ux %.2ux %.2ux\n", v->charset[0], v->charset[1], v->charset[2], v->charset[3], v->charset[4], v->charset[5], v->charset[6], v->charset[7]); print("volume set size %.2N\n", v->volsetsize); print("volume sequence number %.2N\n", v->volseqnum); print("logical block size %.2N\n", v->blocksize); print("path size %.4L\n", v->pathsize); print("lpath loc %.4L\n", v->lpathloc); print("opt lpath loc %.4L\n", v->olpathloc); print("mpath loc %.4B\n", v->mpathloc); print("opt mpath loc %.4B\n", v->ompathloc); print("rootdir %D\n", v->rootdir); print("volume set identifier %.128T\n", v->volsetid); print("publisher %.128T\n", v->publisher); print("preparer %.128T\n", v->prepid); print("application %.128T\n", v->applid); print("notice %.37T\n", v->notice); print("abstract %.37T\n", v->abstract); print("biblio %.37T\n", v->biblio); print("creation date %.17s\n", v->cdate); print("modification date %.17s\n", v->mdate); print("expiration date %.17s\n", v->xdate); print("effective date %.17s\n", v->edate); print("fs version %d\n", v->fsvers); } typedef struct Cdir Cdir; struct Cdir { uchar len; uchar xlen; uchar dloc[8]; uchar dlen[8]; uchar date[7]; uchar flags; uchar unitsize; uchar gapsize; uchar volseqnum[4]; uchar namelen; uchar name[1]; /* chumminess */ }; #pragma varargck type "D" Cdir* int Dfmt(Fmt *fmt) { char buf[128]; Cdir *c; c = va_arg(fmt->args, Cdir*); if(c->namelen == 1 && c->name[0] == '\0' || c->name[0] == '\001') { snprint(buf, sizeof buf, ".%s dloc %.4N dlen %.4N", c->name[0] ? "." : "", c->dloc, c->dlen); } else { snprint(buf, sizeof buf, "%.*T dloc %.4N dlen %.4N", c->namelen, c->name, c->dloc, c->dlen); } fmtstrcpy(fmt, buf); return 0; } typedef struct Path Path; struct Path { uchar namelen; uchar xlen; uchar dloc[4]; uchar parent[2]; uchar name[1]; /* chumminess */ }; #pragma varargck type "P" Path* char longc, shortc; void bigend(void) { longc = 'B'; } void littleend(void) { longc = 'L'; } int Pfmt(Fmt *fmt) { char xfmt[128], buf[128]; Path *p; p = va_arg(fmt->args, Path*); sprint(xfmt, "data=%%.4%c up=%%.2%c name=%%.*T (%%d)", longc, longc); snprint(buf, sizeof buf, xfmt, p->dloc, p->parent, p->namelen, p->name, p->namelen); fmtstrcpy(fmt, buf); return 0; } ulong big(void *a, int n) { uchar *p; ulong v; int i; p = a; v = 0; for(i=0; i<n; i++) v = (v<<8) | *p++; return v; } ulong little(void *a, int n) { uchar *p; ulong v; int i; p = a; v = 0; for(i=0; i<n; i++) v |= (*p++<<(i*8)); return v; } /* numbers in big or little endian. */ int BLfmt(Fmt *fmt) { ulong v; uchar *p; char buf[20]; p = va_arg(fmt->args, uchar*); if(!(fmt->flags&FmtPrec)) { fmtstrcpy(fmt, "*BL*"); return 0; } if(fmt->r == 'B') v = big(p, fmt->prec); else v = little(p, fmt->prec); sprint(buf, "0x%.*lux", fmt->prec*2, v); fmt->flags &= ~FmtPrec; fmtstrcpy(fmt, buf); return 0; } /* numbers in both little and big endian */ int Nfmt(Fmt *fmt) { char buf[100]; uchar *p; p = va_arg(fmt->args, uchar*); sprint(buf, "%.*L %.*B", fmt->prec, p, fmt->prec, p+fmt->prec); fmt->flags &= ~FmtPrec; fmtstrcpy(fmt, buf); return 0; } int asciiTfmt(Fmt *fmt) { char *p, buf[256]; int i; p = va_arg(fmt->args, char*); for(i=0; i<fmt->prec; i++) buf[i] = *p++; buf[i] = '\0'; for(p=buf+strlen(buf); p>buf && p[-1]==' '; p--) ; p[0] = '\0'; fmt->flags &= ~FmtPrec; fmtstrcpy(fmt, buf); return 0; } int runeTfmt(Fmt *fmt) { Rune buf[256], *r; int i; uchar *p; p = va_arg(fmt->args, uchar*); for(i=0; i*2+2<=fmt->prec; i++, p+=2) buf[i] = (p[0]<<8)|p[1]; buf[i] = L'\0'; for(r=buf+i; r>buf && r[-1]==L' '; r--) ; r[0] = L'\0'; fmt->flags &= ~FmtPrec; return fmtprint(fmt, "%S", buf); } void ascii(void) { fmtinstall('T', asciiTfmt); } void joliet(void) { fmtinstall('T', runeTfmt); } void getsect(uchar *buf, int n) { if(Bseek(b, n*2048, 0) != n*2048 || Bread(b, buf, 2048) != 2048) sysfatal("reading block %ux", n); } void pathtable(Voldesc *v, int islittle) { int i, j, n, sz, addr; ulong (*word)(void*, int); uchar x[2048], *p, *ep; Path *pt; print(">>> entire %s path table\n", islittle ? "little" : "big"); littleend(); if(islittle) { littleend(); word = little; }else{ bigend(); word = big; } sz = little(v->pathsize, 4); /* little, not word */ addr = word(islittle ? v->lpathloc : v->mpathloc, 4); j = 0; n = 1; while(sz > 0){ getsect(x, addr); p = x; ep = x+sz; if(ep > x+2048) ep = x+2048; for(i=0; p<ep; i++) { pt = (Path*)p; if(pt->namelen==0) break; print("0x%.4x %4d+%-4ld %P\n", n, j, p-x, pt); n++; p += 8+pt->namelen+(pt->namelen&1); } sz -= 2048; addr++; j++; } } void dump(void *root) { Voldesc *v; Cdir *c; long rootdirloc; uchar x[2048]; int i; uchar *p; dumpbootvol(root); v = (Voldesc*)root; c = (Cdir*)v->rootdir; rootdirloc = little(c->dloc, 4); print(">>> sed 5q root directory\n"); getsect(x, rootdirloc); p = x; for(i=0; i<5 && (p-x)<little(c->dlen, 4); i++) { print("%D\n", p); p += ((Cdir*)p)->len; } pathtable(v, 1); pathtable(v, 0); } void main(int argc, char **argv) { uchar root[2048], jroot[2048]; if(argc != 2) sysfatal("usage: %s file", argv[0]); b = Bopen(argv[1], OREAD); if(b == nil) sysfatal("bopen %r"); fmtinstall('L', BLfmt); fmtinstall('B', BLfmt); fmtinstall('N', Nfmt); fmtinstall('D', Dfmt); fmtinstall('P', Pfmt); getsect(root, 16); ascii(); dump(root); getsect(jroot, 17); joliet(); dump(jroot); exits(0); }