xref: /plan9/sys/src/cmd/disk/rd9660.c (revision 14cc0f535177405a84c5b73603a98e5db6674719)
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
dumpbootvol(void * a)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
Dfmt(Fmt * fmt)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
bigend(void)136 bigend(void)
137 {
138 	longc = 'B';
139 }
140 
141 void
littleend(void)142 littleend(void)
143 {
144 	longc = 'L';
145 }
146 
147 int
Pfmt(Fmt * fmt)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
big(void * a,int n)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
little(void * a,int n)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
BLfmt(Fmt * fmt)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
Nfmt(Fmt * fmt)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
asciiTfmt(Fmt * fmt)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
runeTfmt(Fmt * fmt)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
ascii(void)266 ascii(void)
267 {
268 	fmtinstall('T', asciiTfmt);
269 }
270 
271 void
joliet(void)272 joliet(void)
273 {
274 	fmtinstall('T', runeTfmt);
275 }
276 
277 void
getsect(uchar * buf,int n)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
pathtable(Voldesc * v,int islittle)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
dump(void * root)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
main(int argc,char ** argv)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