Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_unix/sys/src/cmd/disk/9660/cdrdwr.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <bio.h>
4
#include <libsec.h>
5
 
6
#include "iso9660.h"
7
 
8
static int readisodesc(Cdimg*, Voldesc*);
9
static int readjolietdesc(Cdimg*, Voldesc*);
10
 
11
/*
12
 * It's not strictly conforming; instead it's enough to
13
 * get us up and running; presumably the real CD writing
14
 * will take care of being conforming.
15
 *
16
 * Things not conforming include:
17
 *	- no path table
18
 *	- root directories are of length zero
19
 */
20
Cdimg*
21
createcd(char *file, Cdinfo info)
22
{
23
	int fd, xfd;
24
	Cdimg *cd;
25
 
26
	if(access(file, AEXIST) == 0){
27
		werrstr("file already exists");
28
		return nil;
29
	}
30
 
31
	if((fd = create(file, ORDWR, 0666)) < 0)
32
		return nil;
33
 
34
	cd = emalloc(sizeof *cd);
35
	cd->file = atom(file);
36
 
37
	Binit(&cd->brd, fd, OREAD);
38
 
39
	if((xfd = open(file, ORDWR)) < 0)
40
		sysfatal("can't open file again: %r");
41
	Binit(&cd->bwr, xfd, OWRITE);
42
 
43
	Crepeat(cd, 0, 16*Blocksize);
44
	Cputisopvd(cd, info);
45
	if(info.flags & CDbootable){
46
		cd->bootimage = info.bootimage;
47
		cd->loader = info.loader;
48
		cd->flags |= info.flags & (CDbootable|CDbootnoemu);
49
		Cputbootvol(cd);
50
	}
51
 
52
	if(readisodesc(cd, &cd->iso) < 0)
53
		assert(0);
54
	if(info.flags & CDplan9)
55
		cd->flags |= CDplan9;
56
	else if(info.flags & CDrockridge)
57
		cd->flags |= CDrockridge;
58
	if(info.flags & CDjoliet) {
59
		Cputjolietsvd(cd, info);
60
		if(readjolietdesc(cd, &cd->joliet) < 0)
61
			assert(0);
62
		cd->flags |= CDjoliet;
63
	}
64
	Cputendvd(cd);
65
 
66
	if(info.flags & CDdump){
67
		cd->nulldump = Cputdumpblock(cd);
68
		cd->flags |= CDdump;
69
	}
70
	if(cd->flags & CDbootable){
71
		Cputbootcat(cd);
72
		Cupdatebootvol(cd);
73
	}
74
 
75
	if(info.flags & CDconform)
76
		cd->flags |= CDconform;
77
 
78
	cd->flags |= CDnew;
79
	cd->nextblock = Cwoffset(cd) / Blocksize;
80
	assert(cd->nextblock != 0);
81
 
82
	return cd;
83
}
84
 
85
Cdimg*
86
opencd(char *file, Cdinfo info)
87
{
88
	int fd, xfd;
89
	Cdimg *cd;
90
	Dir *d;
91
 
92
	if((fd = open(file, ORDWR)) < 0) {
93
		if(access(file, AEXIST) == 0)
94
			return nil;
95
		return createcd(file, info);
96
	}
97
 
98
	if((d = dirfstat(fd)) == nil) {
99
		close(fd);
100
		return nil;
101
	}
102
	if(d->length == 0 || d->length % Blocksize) {
103
		werrstr("bad length %lld", d->length);
104
		close(fd);
105
		free(d);
106
		return nil;
107
	}
108
 
109
	cd = emalloc(sizeof *cd);
110
	cd->file = atom(file);
111
	cd->nextblock = d->length / Blocksize;
112
	assert(cd->nextblock != 0);
113
	free(d);
114
 
115
	Binit(&cd->brd, fd, OREAD);
116
 
117
	if((xfd = open(file, ORDWR)) < 0)
118
		sysfatal("can't open file again: %r");
119
	Binit(&cd->bwr, xfd, OWRITE);
120
 
121
	if(readisodesc(cd, &cd->iso) < 0) {
122
		free(cd);
123
		close(fd);
124
		close(xfd);
125
		return nil;
126
	}
127
 
128
	/* lowercase because of isostring */
129
	if(strstr(cd->iso.systemid, "iso9660") == nil 
130
	&& strstr(cd->iso.systemid, "utf8") == nil) {
131
		werrstr("unknown systemid %s", cd->iso.systemid);
132
		free(cd);
133
		close(fd);
134
		close(xfd);
135
		return nil;
136
	}
137
 
138
	if(strstr(cd->iso.systemid, "plan 9"))
139
		cd->flags |= CDplan9;
140
	if(strstr(cd->iso.systemid, "iso9660"))
141
		cd->flags |= CDconform;
142
	if(strstr(cd->iso.systemid, "rrip"))
143
		cd->flags |= CDrockridge;
144
	if(strstr(cd->iso.systemid, "boot"))
145
		cd->flags |= CDbootable;
146
	if(readjolietdesc(cd, &cd->joliet) == 0)
147
		cd->flags |= CDjoliet;
148
	if(hasdump(cd))
149
		cd->flags |= CDdump;
150
 
151
	return cd;
152
}
153
 
154
ulong
155
big(void *a, int n)
156
{
157
	uchar *p;
158
	ulong v;
159
	int i;
160
 
161
	p = a;
162
	v = 0;
163
	for(i=0; i<n; i++)
164
		v = (v<<8) | *p++;
165
	return v;
166
}
167
 
168
ulong
169
little(void *a, int n)
170
{
171
	uchar *p;
172
	ulong v;
173
	int i;
174
 
175
	p = a;
176
	v = 0;
177
	for(i=0; i<n; i++)
178
		v |= (*p++<<(i*8));
179
	return v;
180
}
181
 
182
void
183
Creadblock(Cdimg *cd, void *buf, ulong block, ulong len)
184
{
185
	assert(block != 0);	/* nothing useful there */
186
 
187
	Bflush(&cd->bwr);
188
	if(Bseek(&cd->brd, (vlong)block * Blocksize, 0) !=
189
	    (vlong)block * Blocksize)
190
		sysfatal("error seeking to block %lud", block);
191
	if(Bread(&cd->brd, buf, len) != len)
192
		sysfatal("error reading %lud bytes at block %lud: %r %lld",
193
			len, block, Bseek(&cd->brd, 0, 2));
194
}
195
 
196
int
197
parsedir(Cdimg *cd, Direc *d, uchar *buf, int len, char *(*cvtname)(uchar*, int))
198
{
199
	enum { NAMELEN = 28 };
200
	char name[NAMELEN];
201
	uchar *p;
202
	Cdir *c;
203
 
204
	memset(d, 0, sizeof *d);
205
 
206
	c = (Cdir*)buf;
207
 
208
	if(c->len > len) {
209
		werrstr("buffer too small");
210
		return -1;
211
	}
212
 
213
	if(c->namelen == 1 && c->name[0] == '\0')
214
		d->name = atom(".");
215
	else if(c->namelen == 1 && c->name[0] == '\001')
216
		d->name = atom("..");
217
	else if(cvtname)
218
		d->name = cvtname(c->name, c->namelen);
219
 
220
	d->block = little(c->dloc, 4);
221
	d->length = little(c->dlen, 4);
222
 
223
	if(c->flags & 2)
224
		d->mode |= DMDIR;
225
 
226
/*BUG: do we really need to parse the plan 9 fields? */
227
	/* plan 9 use fields */
228
	if((cd->flags & CDplan9) && cvtname == isostring
229
	&& (c->namelen != 1 || c->name[0] > 1)) {
230
		p = buf+33+c->namelen;
231
		if((p-buf)&1)
232
			p++;
233
		assert(p < buf+c->len);
234
		assert(*p < NAMELEN);
235
		if(*p != 0) {
236
			memmove(name, p+1, *p);
237
			name[*p] = '\0';
238
			d->confname = d->name;
239
			d->name = atom(name);
240
		}
241
		p += *p+1;
242
		assert(*p < NAMELEN);
243
		memmove(name, p+1, *p);
244
		name[*p] = '\0';
245
		d->uid = atom(name);
246
		p += *p+1;
247
		assert(*p < NAMELEN);
248
		memmove(name, p+1, *p);
249
		name[*p] = '\0';
250
		d->gid = atom(name);
251
		p += *p+1;
252
		if((p-buf)&1)
253
			p++;
254
		d->mode = little(p, 4);
255
	}
256
 
257
	// BUG: rock ridge extensions
258
	return 0;
259
}
260
 
261
void
262
setroot(Cdimg *cd, ulong block, ulong dloc, ulong dlen)
263
{
264
	assert(block != 0);
265
 
266
	Cwseek(cd, (vlong)block * Blocksize + offsetof(Cvoldesc, rootdir[0]) +
267
		offsetof(Cdir, dloc[0]));
268
	Cputn(cd, dloc, 4);
269
	Cputn(cd, dlen, 4);
270
}
271
 
272
void
273
setvolsize(Cdimg *cd, uvlong block, ulong size)
274
{
275
	assert(block != 0);
276
 
277
	Cwseek(cd, block * Blocksize + offsetof(Cvoldesc, volsize[0]));
278
	Cputn(cd, size, 4);			/* size in blocks */
279
}
280
 
281
void
282
setpathtable(Cdimg *cd, ulong block, ulong sz, ulong lloc, ulong bloc)
283
{
284
	assert(block != 0);
285
 
286
	Cwseek(cd, (vlong)block * Blocksize + offsetof(Cvoldesc, pathsize[0]));
287
	Cputn(cd, sz, 4);
288
	Cputnl(cd, lloc, 4);
289
	Cputnl(cd, 0, 4);
290
	Cputnm(cd, bloc, 4);
291
	Cputnm(cd, 0, 4);
292
	assert(Cwoffset(cd) == (vlong)block * Blocksize +
293
		offsetof(Cvoldesc, rootdir[0]));
294
}
295
 
296
 
297
static void
298
parsedesc(Voldesc *v, Cvoldesc *cv, char *(*string)(uchar*, int))
299
{
300
	v->systemid = string(cv->systemid, sizeof cv->systemid);
301
 
302
	v->pathsize = little(cv->pathsize, 4);
303
	v->lpathloc = little(cv->lpathloc, 4);
304
	v->mpathloc = little(cv->mpathloc, 4);
305
 
306
	v->volumeset = string(cv->volumeset, sizeof cv->volumeset);
307
	v->publisher = string(cv->publisher, sizeof cv->publisher);
308
	v->preparer = string(cv->preparer, sizeof cv->preparer);
309
	v->application = string(cv->application, sizeof cv->application);
310
 
311
	v->abstract = string(cv->abstract, sizeof cv->abstract);
312
	v->biblio = string(cv->biblio, sizeof cv->biblio);
313
	v->notice = string(cv->notice, sizeof cv->notice);
314
}
315
 
316
static int
317
readisodesc(Cdimg *cd, Voldesc *v)
318
{
319
	static uchar magic[] = { 0x01, 'C', 'D', '0', '0', '1', 0x01, 0x00 };
320
	Cvoldesc cv;
321
 
322
	memset(v, 0, sizeof *v);
323
 
324
	Creadblock(cd, &cv, 16, sizeof cv);
325
	if(memcmp(cv.magic, magic, sizeof magic) != 0) {
326
		werrstr("bad pvd magic");
327
		return -1;
328
	}
329
 
330
	if(little(cv.blocksize, 2) != Blocksize) {
331
		werrstr("block size not %d", Blocksize);
332
		return -1;
333
	}
334
 
335
	cd->iso9660pvd = 16;
336
	parsedesc(v, &cv, isostring);
337
 
338
	return parsedir(cd, &v->root, cv.rootdir, sizeof cv.rootdir, isostring);
339
}
340
 
341
static int
342
readjolietdesc(Cdimg *cd, Voldesc *v)
343
{
344
	int i;
345
	static uchar magic[] = { 0x02, 'C', 'D', '0', '0', '1', 0x01, 0x00 };
346
	Cvoldesc cv;
347
 
348
	memset(v, 0, sizeof *v);
349
 
350
	for(i=16; i<24; i++) {
351
		Creadblock(cd, &cv, i, sizeof cv);
352
		if(memcmp(cv.magic, magic, sizeof magic) != 0)
353
			continue;
354
		if(cv.charset[0] != 0x25 || cv.charset[1] != 0x2F
355
		|| (cv.charset[2] != 0x40 && cv.charset[2] != 0x43 && cv.charset[2] != 0x45))
356
			continue;
357
		break;
358
	}
359
 
360
	if(i==24) {
361
		werrstr("could not find Joliet SVD");
362
		return -1;
363
	}
364
 
365
	if(little(cv.blocksize, 2) != Blocksize) {
366
		werrstr("block size not %d", Blocksize);
367
		return -1;
368
	}
369
 
370
	cd->jolietsvd = i;
371
	parsedesc(v, &cv, jolietstring);
372
 
373
	return parsedir(cd, &v->root, cv.rootdir, sizeof cv.rootdir, jolietstring);
374
}
375
 
376
/*
377
 * CD image buffering routines.
378
 */
379
void
380
Cputc(Cdimg *cd, int c)
381
{
382
	assert(Boffset(&cd->bwr) >= 16*Blocksize || c == 0);
383
 
384
if(Boffset(&cd->bwr) == 0x9962)
385
if(c >= 256) abort();
386
	if(Bputc(&cd->bwr, c) < 0)
387
		sysfatal("Bputc: %r");
388
	Bflush(&cd->brd);
389
}
390
 
391
void
392
Cputnl(Cdimg *cd, uvlong val, int size)
393
{
394
	switch(size) {
395
	default:
396
		sysfatal("bad size %d in Cputnl", size);
397
	case 2:
398
		if(val >= (1<<16))
399
			sysfatal("value %llud too big for size %d in Cputnl",
400
				val, size);
401
		Cputc(cd, val);
402
		Cputc(cd, val>>8);
403
		break;
404
	case 4:
405
		if(val >= (1ULL<<32))
406
			sysfatal("value %llud too big for size %d in Cputnl",
407
				val, size);
408
		Cputc(cd, val);
409
		Cputc(cd, val>>8);
410
		Cputc(cd, val>>16);
411
		Cputc(cd, val>>24);
412
		break;
413
	case 8:
414
		Cputc(cd, val);
415
		Cputc(cd, val>>8);
416
		Cputc(cd, val>>16);
417
		Cputc(cd, val>>24);
418
		Cputc(cd, val>>32);
419
		Cputc(cd, val>>40);
420
		Cputc(cd, val>>48);
421
		Cputc(cd, val>>56);
422
		break;
423
	}
424
}
425
 
426
void
427
Cputnm(Cdimg *cd, uvlong val, int size)
428
{
429
	switch(size) {
430
	default:
431
		sysfatal("bad size %d in Cputnm", size);
432
	case 2:
433
		if(val >= (1<<16))
434
			sysfatal("value %llud too big for size %d in Cputnl",
435
				val, size);
436
		Cputc(cd, val>>8);
437
		Cputc(cd, val);
438
		break;
439
	case 4:
440
		if(val >= (1ULL<<32))
441
			sysfatal("value %llud too big for size %d in Cputnl",
442
				val, size);
443
		Cputc(cd, val>>24);
444
		Cputc(cd, val>>16);
445
		Cputc(cd, val>>8);
446
		Cputc(cd, val);
447
		break;
448
	case 8:
449
		Cputc(cd, val>>56);
450
		Cputc(cd, val>>48);
451
		Cputc(cd, val>>40);
452
		Cputc(cd, val>>32);
453
		Cputc(cd, val>>24);
454
		Cputc(cd, val>>16);
455
		Cputc(cd, val>>8);
456
		Cputc(cd, val);
457
		break;
458
	}
459
}
460
 
461
void
462
Cputn(Cdimg *cd, uvlong val, int size)
463
{
464
	Cputnl(cd, val, size);
465
	Cputnm(cd, val, size);
466
}
467
 
468
/*
469
 * ASCII/UTF string writing
470
 */
471
void
472
Crepeat(Cdimg *cd, int c, int n)
473
{
474
	while(n-- > 0)
475
		Cputc(cd, c);
476
}
477
 
478
void
479
Cputs(Cdimg *cd, char *s, int size)
480
{
481
	int n;
482
 
483
	if(s == nil) {
484
		Crepeat(cd, ' ', size);
485
		return;
486
	}
487
 
488
	for(n=0; n<size && *s; n++)
489
		Cputc(cd, *s++);
490
	if(n<size)
491
		Crepeat(cd, ' ', size-n);
492
}
493
 
494
void
495
Cwrite(Cdimg *cd, void *buf, int n)
496
{
497
	assert(Boffset(&cd->bwr) >= 16*Blocksize);
498
 
499
	if(Bwrite(&cd->bwr, buf, n) != n)
500
		sysfatal("Bwrite: %r");
501
	Bflush(&cd->brd);
502
}
503
 
504
void
505
Cputr(Cdimg *cd, Rune r)
506
{
507
	Cputc(cd, r>>8);
508
	Cputc(cd, r);
509
}
510
 
511
void
512
Crepeatr(Cdimg *cd, Rune r, int n)
513
{
514
	int i;
515
 
516
	for(i=0; i<n; i++)
517
		Cputr(cd, r);
518
}
519
 
520
void
521
Cputrs(Cdimg *cd, Rune *s, int osize)
522
{
523
	int n, size;
524
 
525
	size = osize/2;
526
	if(s == nil)
527
		Crepeatr(cd, (Rune)' ', size);
528
	else {
529
		for(n=0; *s && n<size; n++)
530
			Cputr(cd, *s++);
531
		if(n<size)
532
			Crepeatr(cd, ' ', size-n);
533
	}
534
	if(osize&1)
535
		Cputc(cd, 0);	/* what else can we do? */
536
}
537
 
538
void
539
Cputrscvt(Cdimg *cd, char *s, int size)
540
{
541
	Rune r[256];
542
 
543
	strtorune(r, s);
544
	Cputrs(cd, strtorune(r, s), size);
545
}
546
 
547
void
548
Cpadblock(Cdimg *cd)
549
{
550
	int n;
551
	ulong nb;
552
 
553
	n = Blocksize - (Boffset(&cd->bwr) % Blocksize);
554
	if(n != Blocksize)
555
		Crepeat(cd, 0, n);
556
 
557
	nb = Boffset(&cd->bwr)/Blocksize;
558
	assert(nb != 0);
559
	if(nb > cd->nextblock)
560
		cd->nextblock = nb;
561
}
562
 
563
void
564
Cputdate(Cdimg *cd, ulong ust)
565
{
566
	Tm *tm;
567
 
568
	if(ust == 0) {
569
		Crepeat(cd, 0, 7);
570
		return;
571
	}
572
	tm = gmtime(ust);
573
	Cputc(cd, tm->year);
574
	Cputc(cd, tm->mon+1);
575
	Cputc(cd, tm->mday);
576
	Cputc(cd, tm->hour);
577
	Cputc(cd, tm->min);
578
	Cputc(cd, tm->sec);
579
	Cputc(cd, 0);
580
}
581
 
582
void
583
Cputdate1(Cdimg *cd, ulong ust)
584
{
585
	Tm *tm;
586
	char str[20];
587
 
588
	if(ust == 0) {
589
		Crepeat(cd, '0', 16);
590
		Cputc(cd, 0);
591
		return;
592
	}
593
	tm = gmtime(ust);
594
	sprint(str, "%.4d%.2d%.2d%.2d%.2d%.4d",
595
		tm->year+1900,
596
		tm->mon+1,
597
		tm->mday,
598
		tm->hour,
599
		tm->min,
600
		tm->sec*100);
601
	Cputs(cd, str, 16);
602
	Cputc(cd, 0);
603
}
604
 
605
void
606
Cwseek(Cdimg *cd, vlong offset)
607
{
608
	Bseek(&cd->bwr, offset, 0);
609
}
610
 
611
uvlong
612
Cwoffset(Cdimg *cd)
613
{
614
	return Boffset(&cd->bwr);
615
}
616
 
617
void
618
Cwflush(Cdimg *cd)
619
{
620
	Bflush(&cd->bwr);
621
}
622
 
623
uvlong
624
Croffset(Cdimg *cd)
625
{
626
	return Boffset(&cd->brd);
627
}
628
 
629
void
630
Crseek(Cdimg *cd, vlong offset)
631
{
632
	Bseek(&cd->brd, offset, 0);
633
}
634
 
635
int
636
Cgetc(Cdimg *cd)
637
{
638
	int c;
639
 
640
	Cwflush(cd);
641
	if((c = Bgetc(&cd->brd)) == Beof) {
642
		fprint(2, "getc at %llud\n", Croffset(cd));
643
		assert(0);
644
		//sysfatal("Bgetc: %r");
645
	}
646
	return c;
647
}
648
 
649
void
650
Cread(Cdimg *cd, void *buf, int n)
651
{
652
	Cwflush(cd);
653
	if(Bread(&cd->brd, buf, n) != n)
654
		sysfatal("Bread: %r");
655
}
656
 
657
char*
658
Crdline(Cdimg *cd, int c)
659
{
660
	Cwflush(cd);
661
	return Brdline(&cd->brd, c);
662
}
663
 
664
int
665
Clinelen(Cdimg *cd)
666
{
667
	return Blinelen(&cd->brd);
668
}
669