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/write.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 void
9
writelittlebig4(uchar *buf, ulong x)
10
{
11
	buf[0] = buf[7] = x;
12
	buf[1] = buf[6] = x>>8;
13
	buf[2] = buf[5] = x>>16;
14
	buf[3] = buf[4] = x>>24;
15
}
16
 
17
void
18
rewritedot(Cdimg *cd, Direc *d)
19
{
20
	uchar buf[Blocksize];
21
	Cdir *c;
22
 
23
	Creadblock(cd, buf, d->block, Blocksize);
24
	c = (Cdir*)buf;
25
	assert(c->len != 0);
26
	assert(c->namelen == 1 && c->name[0] == '\0');	/* dot */
27
	writelittlebig4(c->dloc, d->block);
28
	writelittlebig4(c->dlen, d->length);
29
 
30
	Cwseek(cd, (vlong)d->block * Blocksize);
31
	Cwrite(cd, buf, Blocksize);
32
}
33
 
34
void
35
rewritedotdot(Cdimg *cd, Direc *d, Direc *dparent)
36
{
37
	uchar buf[Blocksize];
38
	Cdir *c;
39
 
40
	Creadblock(cd, buf, d->block, Blocksize);
41
	c = (Cdir*)buf;
42
	assert(c->len != 0);
43
	assert(c->namelen == 1 && c->name[0] == '\0');	/* dot */
44
 
45
	c = (Cdir*)(buf+c->len);
46
	assert(c->len != 0);
47
	assert(c->namelen == 1 && c->name[0] == '\001');	/* dotdot*/
48
 
49
	writelittlebig4(c->dloc, dparent->block);
50
	writelittlebig4(c->dlen, dparent->length);
51
 
52
	Cwseek(cd, (vlong)d->block * Blocksize);
53
	Cwrite(cd, buf, Blocksize);
54
}
55
 
56
/*
57
 * Write each non-directory file.  We copy the file to
58
 * the cd image, and then if it turns out that we've
59
 * seen this stream of bits before, we push the next block
60
 * pointer back.  This ensures consistency between the MD5s
61
 * and the data on the CD image.  MD5 summing on one pass
62
 * and copying on another would not ensure this.
63
 */
64
void
65
writefiles(Dump *d, Cdimg *cd, Direc *direc)
66
{
67
	int i;
68
	uchar buf[8192], digest[MD5dlen];
69
	ulong length, n, start;
70
	Biobuf *b;
71
	DigestState *s;
72
	Dumpdir *dd;
73
 
74
	if(direc->mode & DMDIR) {
75
		for(i=0; i<direc->nchild; i++)
76
			writefiles(d, cd, &direc->child[i]);
77
		return;
78
	}
79
 
80
	assert(direc->block == 0);
81
 
82
	if((b = Bopen(direc->srcfile, OREAD)) == nil){
83
		fprint(2, "warning: cannot open '%s': %r\n", direc->srcfile);
84
		direc->block = 0;
85
		direc->length = 0;
86
		return;
87
	}
88
 
89
	start = cd->nextblock;
90
	assert(start != 0);
91
	if(blocksize && start%blocksize)
92
		start += blocksize-start%blocksize;
93
 
94
	Cwseek(cd, (vlong)start * Blocksize);
95
 
96
	s = md5(nil, 0, nil, nil);
97
	length = 0;
98
	while((n = Bread(b, buf, sizeof buf)) > 0) {
99
		md5(buf, n, nil, s);
100
		Cwrite(cd, buf, n);
101
		length += n;
102
	}
103
	md5(nil, 0, digest, s);
104
	Bterm(b);
105
	Cpadblock(cd);
106
 
107
	if(length != direc->length) {
108
		fprint(2, "warning: %s changed size underfoot\n", direc->srcfile);
109
		direc->length = length;
110
	}
111
 
112
	if(length == 0)
113
		direc->block = 0;
114
	else if((dd = lookupmd5(d, digest))) {
115
		assert(dd->length == length);
116
		assert(dd->block != 0);
117
		direc->block = dd->block;
118
		cd->nextblock = start;
119
	} else {
120
		direc->block = start;
121
		if(chatty > 1)
122
			fprint(2, "lookup %.16H %lud (%s) failed\n", digest, length, direc->name);
123
		insertmd5(d, atom(direc->name), digest, start, length);
124
	}
125
}
126
 
127
/*
128
 * Write a directory tree.  We work from the leaves, 
129
 * and patch the dotdot pointers afterward.
130
 */
131
static void
132
_writedirs(Cdimg *cd, Direc *d, int (*put)(Cdimg*, Direc*, int, int, int), int level)
133
{
134
	int i, l, ll;
135
	ulong start, next;
136
 
137
	if((d->mode & DMDIR) == 0)
138
		return;
139
 
140
	if(chatty)
141
		fprint(2, "%*s%s\n", 4*level, "", d->name);
142
 
143
	for(i=0; i<d->nchild; i++)
144
		_writedirs(cd, &d->child[i], put, level+1);
145
 
146
	l = 0;
147
	l += put(cd, d, (level == 0) ? DTrootdot : DTdot, 0, l);
148
	l += put(cd, nil, DTdotdot, 0, l);
149
	for(i=0; i<d->nchild; i++)
150
		l += put(cd, &d->child[i], DTiden, 0, l);
151
 
152
	start = cd->nextblock;
153
	cd->nextblock += (l+Blocksize-1)/Blocksize;
154
	next = cd->nextblock;
155
 
156
	Cwseek(cd, (vlong)start * Blocksize);
157
	ll = 0;
158
	ll += put(cd, d, (level == 0) ? DTrootdot : DTdot, 1, ll);
159
	ll += put(cd, nil, DTdotdot, 1, ll);
160
	for(i=0; i<d->nchild; i++)
161
		ll += put(cd, &d->child[i], DTiden, 1, ll);
162
	assert(ll == l);
163
	Cpadblock(cd);
164
	assert(Cwoffset(cd) == (vlong)next * Blocksize);
165
 
166
	d->block = start;
167
	d->length = (vlong)(next - start) * Blocksize;
168
	rewritedot(cd, d);
169
	rewritedotdot(cd, d, d);
170
 
171
	for(i=0; i<d->nchild; i++)
172
		if(d->child[i].mode & DMDIR)
173
			rewritedotdot(cd, &d->child[i], d);
174
}
175
 
176
void
177
writedirs(Cdimg *cd, Direc *d, int (*put)(Cdimg*, Direc*, int, int, int))
178
{
179
	/*
180
	 * If we're writing a mk9660 image, then the root really
181
	 * is the root, so start at level 0.  If we're writing a dump image,
182
	 * then the "root" is really going to be two levels down once
183
	 * we patch in the dump hierarchy above it, so start at level non-zero.
184
	 */
185
	if(chatty)
186
		fprint(2, ">>> writedirs\n");
187
	_writedirs(cd, d, put, mk9660 ? 0 : 1);
188
}
189
 
190
 
191
/*
192
 * Write the dump tree.  This is like writedirs but once we get to
193
 * the roots of the individual days we just patch the parent dotdot blocks.
194
 */
195
static void
196
_writedumpdirs(Cdimg *cd, Direc *d, int (*put)(Cdimg*, Direc*, int, int, int), int level)
197
{
198
	int i;
199
	ulong start;
200
 
201
	switch(level) {
202
	case 0:
203
		/* write root, list of years, also conform.map */
204
		for(i=0; i<d->nchild; i++)
205
			if(d->child[i].mode & DMDIR)
206
				_writedumpdirs(cd, &d->child[i], put, level+1);
207
		chat("write dump root dir at %lud\n", cd->nextblock);
208
		goto Writedir;
209
 
210
	case 1:	/* write year, list of days */
211
		for(i=0; i<d->nchild; i++)
212
			_writedumpdirs(cd, &d->child[i], put, level+1);
213
		chat("write dump %s dir at %lud\n", d->name, cd->nextblock);
214
		goto Writedir;
215
 
216
	Writedir:
217
		start = cd->nextblock;
218
		Cwseek(cd, (vlong)start * Blocksize);
219
 
220
		put(cd, d, (level == 0) ? DTrootdot : DTdot, 1, Cwoffset(cd));
221
		put(cd, nil, DTdotdot, 1, Cwoffset(cd));
222
		for(i=0; i<d->nchild; i++)
223
			put(cd, &d->child[i], DTiden, 1, Cwoffset(cd));
224
		Cpadblock(cd);
225
 
226
		d->block = start;
227
		d->length = (vlong)(cd->nextblock - start) * Blocksize;
228
 
229
		rewritedot(cd, d);
230
		rewritedotdot(cd, d, d);
231
 
232
		for(i=0; i<d->nchild; i++)
233
			if(d->child[i].mode & DMDIR)
234
				rewritedotdot(cd, &d->child[i], d);
235
		break;
236
 
237
	case 2:	/* write day: already written, do nothing */
238
		break;
239
 
240
	default:
241
		assert(0);
242
	}
243
}
244
 
245
void
246
writedumpdirs(Cdimg *cd, Direc *d, int (*put)(Cdimg*, Direc*, int, int, int))
247
{
248
	_writedumpdirs(cd, d, put, 0);
249
}
250
 
251
static int
252
Cputplan9(Cdimg *cd, Direc *d, int dot, int dowrite)
253
{
254
	int l, n;
255
 
256
	if(dot != DTiden)
257
		return 0;
258
 
259
	l = 0;
260
	if(d->flags & Dbadname) {
261
		n = strlen(d->name);
262
		l += 1+n;
263
		if(dowrite) {
264
			Cputc(cd, n);
265
			Cputs(cd, d->name, n);
266
		}
267
	} else {
268
		l++;
269
		if(dowrite)
270
			Cputc(cd, 0);
271
	}
272
 
273
	n = strlen(d->uid);
274
	l += 1+n;
275
	if(dowrite) {
276
		Cputc(cd, n);
277
		Cputs(cd, d->uid, n);
278
	}
279
 
280
	n = strlen(d->gid);
281
	l += 1+n;
282
	if(dowrite) {
283
		Cputc(cd, n);
284
		Cputs(cd, d->gid, n);
285
	}
286
 
287
	if(l & 1) {
288
		l++;
289
		if(dowrite)
290
			Cputc(cd, 0);
291
	}
292
	l += 8;
293
	if(dowrite)
294
		Cputn(cd, d->mode, 4);
295
 
296
	return l;
297
}
298
 
299
/*
300
 * Write a directory entry.
301
 */
302
static int
303
genputdir(Cdimg *cd, Direc *d, int dot, int joliet, int dowrite, int offset)
304
{
305
	int f, n, l, lp;
306
	vlong o;
307
 
308
	f = 0;
309
	if(dot != DTiden || (d->mode & DMDIR))
310
		f |= 2;
311
 
312
	n = 1;
313
	if(dot == DTiden) {
314
		if(joliet)
315
			n = 2*utflen(d->confname);
316
		else
317
			n = strlen(d->confname);
318
	}
319
 
320
	l = 33+n;
321
	if(l & 1)
322
		l++;
323
	assert(l <= 255);
324
 
325
	if(joliet == 0) {
326
		if(cd->flags & CDplan9)
327
			l += Cputplan9(cd, d, dot, 0);
328
		else if(cd->flags & CDrockridge)
329
			l += Cputsysuse(cd, d, dot, 0, l);
330
		assert(l <= 255);
331
	}
332
 
333
	if(dowrite == 0) {
334
		if(Blocksize - offset%Blocksize < l)
335
			l += Blocksize - offset%Blocksize;
336
		return l;
337
	}
338
 
339
	assert(offset%Blocksize == Cwoffset(cd)%Blocksize);
340
 
341
	o = Cwoffset(cd);
342
	lp = 0;
343
	if(Blocksize - Cwoffset(cd)%Blocksize < l) {
344
		lp = Blocksize - Cwoffset(cd)%Blocksize;
345
		Cpadblock(cd);
346
	}
347
 
348
	Cputc(cd, l);			/* length of directory record */
349
	Cputc(cd, 0);			/* extended attribute record length */
350
	if(d) {
351
		if((d->mode & DMDIR) == 0)
352
			assert(d->length == 0 || d->block >= 18);
353
 
354
		Cputn(cd, d->block, 4);		/* location of extent */
355
		Cputn(cd, d->length, 4);		/* data length */
356
	} else {
357
		Cputn(cd, 0, 4);
358
		Cputn(cd, 0, 4);
359
	}
360
	Cputdate(cd, d ? d->mtime : now);		/* recorded date */
361
	Cputc(cd, f);			/* file flags */
362
	Cputc(cd, 0);			/* file unit size */
363
	Cputc(cd, 0);			/* interleave gap size */
364
	Cputn(cd, 1, 2);	       	/* volume sequence number */
365
	Cputc(cd, n);			/* length of file identifier */
366
 
367
	if(dot == DTiden) {		/* identifier */
368
		if(joliet)
369
			Cputrscvt(cd, d->confname, n);
370
		else
371
			Cputs(cd, d->confname, n);
372
	}else
373
	if(dot == DTdotdot)
374
		Cputc(cd, 1);
375
	else
376
		Cputc(cd, 0);
377
 
378
	if(Cwoffset(cd) & 1)			/* pad */
379
		Cputc(cd, 0);
380
 
381
	if(joliet == 0) {
382
		if(cd->flags & CDplan9)
383
			Cputplan9(cd, d, dot, 1);
384
		else if(cd->flags & CDrockridge)
385
			Cputsysuse(cd, d, dot, 1, Cwoffset(cd)-(o+lp));
386
	}
387
 
388
	assert(o+lp+l == Cwoffset(cd));
389
	return lp+l;
390
}
391
 
392
int
393
Cputisodir(Cdimg *cd, Direc *d, int dot, int dowrite, int offset)
394
{
395
	return genputdir(cd, d, dot, 0, dowrite, offset);
396
}
397
 
398
int
399
Cputjolietdir(Cdimg *cd, Direc *d, int dot, int dowrite, int offset)
400
{
401
	return genputdir(cd, d, dot, 1, dowrite, offset);
402
}
403
 
404
void
405
Cputendvd(Cdimg *cd)
406
{
407
	Cputc(cd, 255);				/* volume descriptor set terminator */
408
	Cputs(cd, "CD001", 5);			/* standard identifier */
409
	Cputc(cd, 1);				/* volume descriptor version */
410
	Cpadblock(cd);
411
}