1 /* 2 * dump a 9660 cd image for a little while. 3 * for debugging. 4 */ 5 #include <u.h> 6 #include <libc.h> 7 #include <bio.h> 8 #include <disk.h> 9 10 Biobuf *b; 11 12 #pragma varargck type "s" uchar* 13 #pragma varargck type "L" uchar* 14 #pragma varargck type "B" uchar* 15 #pragma varargck type "N" uchar* 16 #pragma varargck type "T" uchar* 17 #pragma varargck type "D" uchar* 18 19 typedef struct Voldesc Voldesc; 20 struct Voldesc { 21 uchar magic[8]; /* 0x01, "CD001", 0x01, 0x00 */ 22 uchar systemid[32]; /* system identifier */ 23 uchar volumeid[32]; /* volume identifier */ 24 uchar unused[8]; /* character set in secondary desc */ 25 uchar volsize[8]; /* volume size */ 26 uchar charset[32]; 27 uchar volsetsize[4]; /* volume set size = 1 */ 28 uchar volseqnum[4]; /* volume sequence number = 1 */ 29 uchar blocksize[4]; /* logical block size */ 30 uchar pathsize[8]; /* path table size */ 31 uchar lpathloc[4]; /* Lpath */ 32 uchar olpathloc[4]; /* optional Lpath */ 33 uchar mpathloc[4]; /* Mpath */ 34 uchar ompathloc[4]; /* optional Mpath */ 35 uchar rootdir[34]; /* root directory */ 36 uchar volsetid[128]; /* volume set identifier */ 37 uchar publisher[128]; 38 uchar prepid[128]; /* data preparer identifier */ 39 uchar applid[128]; /* application identifier */ 40 uchar notice[37]; /* copyright notice file */ 41 uchar abstract[37]; /* abstract file */ 42 uchar biblio[37]; /* bibliographic file */ 43 uchar cdate[17]; /* creation date */ 44 uchar mdate[17]; /* modification date */ 45 uchar xdate[17]; /* expiration date */ 46 uchar edate[17]; /* effective date */ 47 uchar fsvers; /* file system version = 1 */ 48 }; 49 50 void 51 dumpbootvol(void *a) 52 { 53 Voldesc *v; 54 55 v = a; 56 print("magic %.2ux %.5s %.2ux %2ux\n", 57 v->magic[0], v->magic+1, v->magic[6], v->magic[7]); 58 if(v->magic[0] == 0xFF) 59 return; 60 61 print("system %.32T\n", v->systemid); 62 print("volume %.32T\n", v->volumeid); 63 print("volume size %.4N\n", v->volsize); 64 print("charset %.2ux %.2ux %.2ux %.2ux %.2ux %.2ux %.2ux %.2ux\n", 65 v->charset[0], v->charset[1], v->charset[2], v->charset[3], 66 v->charset[4], v->charset[5], v->charset[6], v->charset[7]); 67 print("volume set size %.2N\n", v->volsetsize); 68 print("volume sequence number %.2N\n", v->volseqnum); 69 print("logical block size %.2N\n", v->blocksize); 70 print("path size %.4L\n", v->pathsize); 71 print("lpath loc %.4L\n", v->lpathloc); 72 print("opt lpath loc %.4L\n", v->olpathloc); 73 print("mpath loc %.4B\n", v->mpathloc); 74 print("opt mpath loc %.4B\n", v->ompathloc); 75 print("rootdir %D\n", v->rootdir); 76 print("volume set identifier %.128T\n", v->volsetid); 77 print("publisher %.128T\n", v->publisher); 78 print("preparer %.128T\n", v->prepid); 79 print("application %.128T\n", v->applid); 80 print("notice %.37T\n", v->notice); 81 print("abstract %.37T\n", v->abstract); 82 print("biblio %.37T\n", v->biblio); 83 print("creation date %.17s\n", v->cdate); 84 print("modification date %.17s\n", v->mdate); 85 print("expiration date %.17s\n", v->xdate); 86 print("effective date %.17s\n", v->edate); 87 print("fs version %d\n", v->fsvers); 88 } 89 90 typedef struct Cdir Cdir; 91 struct Cdir { 92 uchar len; 93 uchar xlen; 94 uchar dloc[8]; 95 uchar dlen[8]; 96 uchar date[7]; 97 uchar flags; 98 uchar unitsize; 99 uchar gapsize; 100 uchar volseqnum[4]; 101 uchar namelen; 102 uchar name[1]; /* chumminess */ 103 }; 104 #pragma varargck type "D" Cdir* 105 106 int 107 Dfmt(Fmt *fmt) 108 { 109 char buf[128]; 110 Cdir *c; 111 112 c = va_arg(fmt->args, Cdir*); 113 if(c->namelen == 1 && c->name[0] == '\0' || c->name[0] == '\001') { 114 snprint(buf, sizeof buf, ".%s dloc %.4N dlen %.4N", 115 c->name[0] ? "." : "", c->dloc, c->dlen); 116 } else { 117 snprint(buf, sizeof buf, "%.*T dloc %.4N dlen %.4N", c->namelen, c->name, 118 c->dloc, c->dlen); 119 } 120 fmtstrcpy(fmt, buf); 121 return 0; 122 } 123 124 typedef struct Path Path; 125 struct Path { 126 uchar namelen; 127 uchar xlen; 128 uchar dloc[4]; 129 uchar parent[2]; 130 uchar name[1]; /* chumminess */ 131 }; 132 #pragma varargck type "P" Path* 133 134 char longc, shortc; 135 void 136 bigend(void) 137 { 138 longc = 'B'; 139 } 140 141 void 142 littleend(void) 143 { 144 longc = 'L'; 145 } 146 147 int 148 Pfmt(Fmt *fmt) 149 { 150 char xfmt[128], buf[128]; 151 Path *p; 152 153 p = va_arg(fmt->args, Path*); 154 sprint(xfmt, "data=%%.4%c up=%%.2%c name=%%.*T (%%d)", longc, longc); 155 snprint(buf, sizeof buf, xfmt, p->dloc, p->parent, p->namelen, p->name, p->namelen); 156 fmtstrcpy(fmt, buf); 157 return 0; 158 } 159 160 ulong 161 big(void *a, int n) 162 { 163 uchar *p; 164 ulong v; 165 int i; 166 167 p = a; 168 v = 0; 169 for(i=0; i<n; i++) 170 v = (v<<8) | *p++; 171 return v; 172 } 173 174 ulong 175 little(void *a, int n) 176 { 177 uchar *p; 178 ulong v; 179 int i; 180 181 p = a; 182 v = 0; 183 for(i=0; i<n; i++) 184 v |= (*p++<<(i*8)); 185 return v; 186 } 187 188 /* numbers in big or little endian. */ 189 int 190 BLfmt(Fmt *fmt) 191 { 192 ulong v; 193 uchar *p; 194 char buf[20]; 195 196 p = va_arg(fmt->args, uchar*); 197 198 if(!(fmt->flags&FmtPrec)) { 199 fmtstrcpy(fmt, "*BL*"); 200 return 0; 201 } 202 203 if(fmt->r == 'B') 204 v = big(p, fmt->prec); 205 else 206 v = little(p, fmt->prec); 207 208 sprint(buf, "0x%.*lux", fmt->prec*2, v); 209 fmt->flags &= ~FmtPrec; 210 fmtstrcpy(fmt, buf); 211 return 0; 212 } 213 214 /* numbers in both little and big endian */ 215 int 216 Nfmt(Fmt *fmt) 217 { 218 char buf[100]; 219 uchar *p; 220 221 p = va_arg(fmt->args, uchar*); 222 223 sprint(buf, "%.*L %.*B", fmt->prec, p, fmt->prec, p+fmt->prec); 224 fmt->flags &= ~FmtPrec; 225 fmtstrcpy(fmt, buf); 226 return 0; 227 } 228 229 int 230 asciiTfmt(Fmt *fmt) 231 { 232 char *p, buf[256]; 233 int i; 234 235 p = va_arg(fmt->args, char*); 236 for(i=0; i<fmt->prec; i++) 237 buf[i] = *p++; 238 buf[i] = '\0'; 239 for(p=buf+strlen(buf); p>buf && p[-1]==' '; p--) 240 ; 241 p[0] = '\0'; 242 fmt->flags &= ~FmtPrec; 243 fmtstrcpy(fmt, buf); 244 return 0; 245 } 246 247 int 248 runeTfmt(Fmt *fmt) 249 { 250 Rune buf[256], *r; 251 int i; 252 uchar *p; 253 254 p = va_arg(fmt->args, uchar*); 255 for(i=0; i*2+2<=fmt->prec; i++, p+=2) 256 buf[i] = (p[0]<<8)|p[1]; 257 buf[i] = L'\0'; 258 for(r=buf+i; r>buf && r[-1]==L' '; r--) 259 ; 260 r[0] = L'\0'; 261 fmt->flags &= ~FmtPrec; 262 return fmtprint(fmt, "%S", buf); 263 } 264 265 void 266 ascii(void) 267 { 268 fmtinstall('T', asciiTfmt); 269 } 270 271 void 272 joliet(void) 273 { 274 fmtinstall('T', runeTfmt); 275 } 276 277 void 278 getsect(uchar *buf, int n) 279 { 280 if(Bseek(b, n*2048, 0) != n*2048 || Bread(b, buf, 2048) != 2048) 281 sysfatal("reading block %ux", n); 282 } 283 284 void 285 pathtable(Voldesc *v, int islittle) 286 { 287 int i, j, n, sz, addr; 288 ulong (*word)(void*, int); 289 uchar x[2048], *p, *ep; 290 Path *pt; 291 292 print(">>> entire %s path table\n", islittle ? "little" : "big"); 293 littleend(); 294 if(islittle) { 295 littleend(); 296 word = little; 297 }else{ 298 bigend(); 299 word = big; 300 } 301 sz = little(v->pathsize, 4); /* little, not word */ 302 addr = word(islittle ? v->lpathloc : v->mpathloc, 4); 303 j = 0; 304 n = 1; 305 while(sz > 0){ 306 getsect(x, addr); 307 p = x; 308 ep = x+sz; 309 if(ep > x+2048) 310 ep = x+2048; 311 for(i=0; p<ep; i++) { 312 pt = (Path*)p; 313 if(pt->namelen==0) 314 break; 315 print("0x%.4x %4d+%-4ld %P\n", n, j, p-x, pt); 316 n++; 317 p += 8+pt->namelen+(pt->namelen&1); 318 } 319 sz -= 2048; 320 addr++; 321 j++; 322 } 323 } 324 325 void 326 dump(void *root) 327 { 328 Voldesc *v; 329 Cdir *c; 330 long rootdirloc; 331 uchar x[2048]; 332 int i; 333 uchar *p; 334 335 dumpbootvol(root); 336 v = (Voldesc*)root; 337 c = (Cdir*)v->rootdir; 338 rootdirloc = little(c->dloc, 4); 339 print(">>> sed 5q root directory\n"); 340 getsect(x, rootdirloc); 341 p = x; 342 for(i=0; i<5 && (p-x)<little(c->dlen, 4); i++) { 343 print("%D\n", p); 344 p += ((Cdir*)p)->len; 345 } 346 347 pathtable(v, 1); 348 pathtable(v, 0); 349 } 350 351 void 352 main(int argc, char **argv) 353 { 354 uchar root[2048], jroot[2048]; 355 356 if(argc != 2) 357 sysfatal("usage: %s file", argv[0]); 358 359 b = Bopen(argv[1], OREAD); 360 if(b == nil) 361 sysfatal("bopen %r"); 362 363 fmtinstall('L', BLfmt); 364 fmtinstall('B', BLfmt); 365 fmtinstall('N', Nfmt); 366 fmtinstall('D', Dfmt); 367 fmtinstall('P', Pfmt); 368 369 getsect(root, 16); 370 ascii(); 371 dump(root); 372 373 getsect(jroot, 17); 374 joliet(); 375 dump(jroot); 376 exits(0); 377 } 378