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_posix/sys/src/games/music/jukefs/fs.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 <thread.h>
4
#include <bio.h>
5
#include <fcall.h>
6
#include "object.h"
7
 
8
extern int debug;
9
 
10
extern int mfd[];
11
 
12
enum {
13
	DbgFs = 0x1000
14
};
15
 
16
typedef struct Fid Fid;
17
 
18
enum {
19
	Busy =	0x01,
20
	Open =	0x02,
21
	Endf =	0x04,
22
};
23
 
24
struct Fid
25
{
26
	QLock;
27
	Qid	qid;
28
	int	fid;
29
	ushort	flags;
30
	vlong	offset;		// offset of data[0]
31
	Fid	*next;
32
};
33
 
34
Fcall	thdr;
35
Fcall	rhdr;
36
 
37
enum {
38
	/* Files making up an object */
39
	Qchildren,		/* Each of these must be in dirtab */
40
	Qdigest,
41
	Qfiles,
42
	Qfulltext,
43
	Qkey,
44
	Qminiparentage,
45
	Qparent,
46
	Qparentage,
47
	Qtext,
48
	Qtype,
49
 
50
	/* Other files */
51
	Qtop,	/* Must follow Qtype */
52
	Qclassical,
53
	Qdir,
54
	Qroot,
55
	Qctl,
56
};
57
 
58
#define PATH(id, f)	(((id)<<8) | (f))
59
#define FILE(p)		((p) & 0xff)
60
#define NUM(p)		((p) >> 8)
61
 
62
char *dirtab[] =
63
{
64
[Qchildren]	"children",
65
[Qdigest]	"digest",
66
[Qdir]		".",
67
[Qfiles]	"files",
68
[Qfulltext]	"fulltext",
69
[Qkey]		"key",
70
[Qminiparentage]"miniparentage",
71
[Qparent]	"parent",
72
[Qparentage]	"parentage",
73
[Qtext]		"text",
74
[Qtype]		"type",
75
[Qtop]		nil,
76
};
77
 
78
char	*rflush(Fid*), *rauth(Fid*),
79
	*rattach(Fid*), *rwalk(Fid*),
80
	*ropen(Fid*), *rcreate(Fid*),
81
	*rread(Fid*), *rwrite(Fid*), *rclunk(Fid*),
82
	*rremove(Fid*), *rstat(Fid*), *rwstat(Fid*),
83
	*rversion(Fid*);
84
 
85
char 	*(*fcalls[])(Fid*) = {
86
	[Tflush]	rflush,
87
	[Tversion]	rversion,
88
	[Tauth]		rauth,
89
	[Tattach]	rattach,
90
	[Twalk]		rwalk,
91
	[Topen]		ropen,
92
	[Tcreate]	rcreate,
93
	[Tread]		rread,
94
	[Twrite]	rwrite,
95
	[Tclunk]	rclunk,
96
	[Tremove]	rremove,
97
	[Tstat]		rstat,
98
	[Twstat]	rwstat,
99
};
100
 
101
int	messagesize = 8*1024+IOHDRSZ;
102
uchar	mdata[8*1024+IOHDRSZ];
103
uchar	mbuf[8*1024+IOHDRSZ];
104
char	bigbuf[1<<23];	/* 8 megabytes */
105
Fid	*fids;
106
 
107
char	Eperm[] =	"permission denied";
108
char	Enotdir[] =	"not a directory";
109
char	Enoauth[] =	"no authentication required";
110
char	Enotexist[] =	"file does not exist";
111
char	Einuse[] =	"file in use";
112
char	Eexist[] =	"file exists";
113
char	Enotowner[] =	"not owner";
114
char	Eisopen[] = 	"file already open for I/O";
115
char	Excl[] = 	"exclusive use file already open";
116
char	Ename[] = 	"illegal name";
117
char	Ebadctl[] =	"unknown control message";
118
 
119
Fid *newfid(int fid);
120
 
121
static int
122
lookup(char *cmd, char *list[])
123
{
124
	int i;
125
 
126
	for (i = 0; list[i] != nil; i++)
127
		if (strcmp(cmd, list[i]) == 0)
128
			return i;
129
	return -1;
130
}
131
 
132
char*
133
rversion(Fid *)
134
{
135
	Fid *f;
136
 
137
	if(thdr.msize < 256)
138
		return "max messagesize too small";
139
	if(thdr.msize < messagesize)
140
		messagesize = thdr.msize;
141
	rhdr.msize = messagesize;
142
	if(strncmp(thdr.version, "9P2000", 6) != 0)
143
		return "unknown 9P version";
144
	else
145
		rhdr.version = "9P2000";
146
	for(f = fids; f; f = f->next)
147
		if(f->flags & Busy)
148
			rclunk(f);
149
	return nil;
150
}
151
 
152
char*
153
rauth(Fid*)
154
{
155
	return Enoauth;
156
}
157
 
158
char*
159
rflush(Fid *)
160
{
161
	return 0;
162
}
163
 
164
char*
165
rattach(Fid *f)
166
{
167
	f->flags |= Busy;
168
	f->qid.type = QTDIR;
169
	f->qid.vers = 0;
170
	f->qid.path = PATH(0, Qtop);
171
	rhdr.qid = f->qid;
172
	return 0;
173
}
174
 
175
static Fid*
176
doclone(Fid *f, int nfid)
177
{
178
	Fid *nf;
179
 
180
	nf = newfid(nfid);
181
	nf->qid = f->qid;
182
	if(nf->flags & Busy)
183
		return nil;
184
	nf->flags |= Busy;
185
	nf->flags &= ~Open;
186
	return nf;
187
}
188
 
189
char*
190
dowalk(Fid *f, char *name)
191
{
192
	int t, n, m;
193
	char *rv, *p;
194
 
195
	t = FILE(f->qid.path);	/* Type */
196
 
197
	rv = Enotexist;
198
 
199
	if(strcmp(name, ".") == 0 && f->qid.type == QTDIR)
200
		return nil;
201
	if(strcmp(name, "..") == 0){
202
		switch(t){
203
		case Qtop:
204
		case Qclassical:
205
			f->qid.path = PATH(0, Qtop);
206
			f->qid.type = QTDIR;
207
			f->qid.vers = 0;
208
			rv = nil;
209
			break;
210
		case Qdir:
211
		case Qroot:
212
			f->qid.path = PATH(0, Qclassical);
213
			f->qid.type = QTDIR;
214
			f->qid.vers = 0;
215
			rv = nil;
216
			break;
217
		}
218
		return rv;
219
	}
220
	switch(t){
221
	case Qtop:
222
		/* Contains classical */
223
		if(strcmp(name, "juke") == 0){
224
			f->qid.path = PATH(root->tabno, Qclassical);
225
			f->qid.type = QTDIR;
226
			f->qid.vers = 0;
227
			rv = nil;
228
			break;
229
		}
230
		break;
231
	case Qclassical:
232
		/* main dir, contains `root' and object dirs */
233
		if(strcmp(name, "root") == 0){
234
			f->qid.path = PATH(root->tabno, Qroot);
235
			f->qid.type = QTDIR;
236
			f->qid.vers = 0;
237
			rv = nil;
238
			break;
239
		}
240
		if(strcmp(name, "ctl") == 0){
241
			f->qid.path = PATH(root->tabno, Qctl);
242
			f->qid.type = QTFILE;
243
			f->qid.vers = 0;
244
			rv = nil;
245
			break;
246
		}
247
		n = strtol(name, &p, 0);
248
		if(*p)
249
			break;	/* Not a number */
250
		if(n < 0 || n >= notab)
251
			break;	/* Outside range */
252
		if(otab[n] == nil)
253
			break;	/* Not in object table */
254
		f->qid.path = PATH(n, Qdir);
255
		f->qid.type = QTDIR;
256
		f->qid.vers = 0;
257
		rv = nil;
258
		break;
259
	case Qroot:	/* Root of the object hierarchy */
260
	case Qdir:	/* Object directory */
261
		if((m = lookup(name, dirtab)) < 0)
262
			break;
263
		n = NUM(f->qid.path);
264
		f->qid.path = PATH(n, m);
265
		f->qid.type = QTFILE;
266
		f->qid.vers = 0;
267
		rv = nil;
268
		break;
269
	}
270
	return rv;
271
}
272
 
273
char*
274
rwalk(Fid *f)
275
{
276
	Fid *nf;
277
	char *rv;
278
	int i;
279
 
280
	if(f->flags & Open)
281
		return Eisopen;
282
 
283
	rhdr.nwqid = 0;
284
	nf = nil;
285
 
286
	/* clone if requested */
287
	if(thdr.newfid != thdr.fid){
288
		nf = doclone(f, thdr.newfid);
289
		if(nf == nil)
290
			return "new fid in use";
291
		f = nf;
292
	}
293
 
294
	/* if it's just a clone, return */
295
	if(thdr.nwname == 0 && nf != nil)
296
		return nil;
297
 
298
	/* walk each element */
299
	rv = nil;
300
	for(i = 0; i < thdr.nwname; i++){
301
		rv = dowalk(f, thdr.wname[i]);
302
		if(rv != nil){
303
			if(nf != nil)	
304
				rclunk(nf);
305
			break;
306
		}
307
		rhdr.wqid[i] = f->qid;
308
	}
309
	rhdr.nwqid = i;
310
 
311
	/* we only error out if no walk  */
312
	if(i > 0)
313
		rv = nil;
314
 
315
	return rv;
316
}
317
 
318
char *
319
ropen(Fid *f)
320
{
321
	if(f->flags & Open)
322
		return Eisopen;
323
 
324
	if(thdr.mode != OREAD && FILE(f->qid.path) != Qctl)
325
		return Eperm;
326
	rhdr.iounit = 0;
327
	rhdr.qid = f->qid;
328
	f->flags |= Open;
329
	f->flags &= ~Endf;
330
	return nil;
331
}
332
 
333
char *
334
rcreate(Fid*)
335
{
336
	return Eperm;
337
}
338
 
339
static long
340
fileinfo(char *buf, int bufsize, int onum, int t)
341
{
342
	long n;
343
 
344
	n = 0;
345
	switch(t){
346
	case Qchildren:
347
		n = printchildren(buf, bufsize, otab[onum]);
348
		break;
349
	case Qdigest:
350
		n = printdigest(buf, bufsize, otab[onum]);
351
		break;
352
	case Qfulltext:
353
		n = printfulltext(buf, bufsize, otab[onum]);
354
		break;
355
	case Qkey:
356
		n = printkey(buf, bufsize, otab[onum]);
357
		break;
358
	case Qparent:
359
		n = printparent(buf, bufsize, otab[onum]);
360
		break;
361
	case Qtext:
362
		n = printtext(buf, bufsize, otab[onum]);
363
		break;
364
	case Qtype:
365
		n = printtype(buf, bufsize, otab[onum]);
366
		break;
367
	case Qfiles:
368
		n = printfiles(buf, bufsize, otab[onum]);
369
		break;
370
	case Qparentage:
371
		n = printparentage(buf, bufsize, otab[onum]);
372
		break;
373
	case Qminiparentage:
374
		n = printminiparentage(buf, bufsize, otab[onum]);
375
		break;
376
	default:
377
		sysfatal("rread: %d", t);
378
	}
379
	return n;
380
}
381
 
382
static void
383
mkstat(Dir *d, int n, int t)
384
{
385
	static char buf[16];
386
 
387
	d->uid = user;
388
	d->gid = user;
389
	d->muid = user;
390
	d->qid.vers = 0;
391
	d->qid.type = QTFILE;
392
	d->type = 0;
393
	d->dev = 0;
394
	d->atime = time(0);
395
	d->mtime = d->atime;
396
	switch(t){
397
	case Qtop:
398
		d->name = ".";
399
		d->mode = DMDIR|0555;
400
		d->atime = d->mtime = time(0);
401
		d->length = 0;
402
		d->qid.path = PATH(0, Qtop);
403
		d->qid.type = QTDIR;
404
		break;
405
	case Qclassical:
406
		d->name = "juke";
407
		d->mode = DMDIR|0555;
408
		d->atime = d->mtime = time(0);
409
		d->length = 0;
410
		d->qid.path = PATH(0, Qclassical);
411
		d->qid.type = QTDIR;
412
		break;
413
	case Qdir:
414
		snprint(buf, sizeof buf, "%d", n);
415
		d->name = buf;
416
		d->mode = DMDIR|0555;
417
		d->length = 0;
418
		d->qid.path = PATH(n, Qdir);
419
		d->qid.type = QTDIR;
420
		break;
421
	case Qroot:
422
		d->name = "root";
423
		d->mode = DMDIR|0555;
424
		d->length = 0;
425
		d->qid.path = PATH(0, Qroot);
426
		d->qid.type = QTDIR;
427
		break;
428
	case Qctl:
429
		d->name = "ctl";
430
		d->mode = 0666;
431
		d->length = 0;
432
		d->qid.path = PATH(0, Qctl);
433
		break;
434
		d->name = "ctl";
435
		d->mode = 0666;
436
		d->length = 0;
437
		d->qid.path = PATH(0, Qctl);
438
		break;
439
	case Qchildren:
440
	case Qdigest:
441
	case Qfiles:
442
	case Qfulltext:
443
	case Qkey:
444
	case Qminiparentage:
445
	case Qparent:
446
	case Qparentage:
447
	case Qtext:
448
	case Qtype:
449
		d->name = dirtab[t];
450
		d->mode = 0444;
451
		d->length = fileinfo(bigbuf, sizeof bigbuf, n, t);
452
		d->qid.path = PATH(n, t);
453
		break;
454
	default:
455
		sysfatal("mkstat: %d", t);
456
	}
457
}
458
 
459
int
460
readtopdir(Fid*, uchar *buf, long off, int cnt, int blen)
461
{
462
	int m, n;
463
	Dir d;
464
 
465
	n = 0;
466
	mkstat(&d, 0, Qclassical);
467
	m = convD2M(&d, &buf[n], blen);
468
	if(off <= 0){
469
		if(m <= BIT16SZ || m > cnt)
470
			return n;
471
		n += m;
472
	}
473
	return n;
474
}
475
 
476
int
477
readclasdir(Fid*, uchar *buf, long off, int cnt, int blen)
478
{
479
	int m, n;
480
	long pos;
481
	Dir d;
482
	Fid *fid;
483
 
484
	n = 0;
485
	pos = 0;
486
	mkstat(&d, 0, Qctl);
487
	m = convD2M(&d, &buf[n], blen);
488
	if(off <= pos){
489
		if(m <= BIT16SZ || m > cnt)
490
			return 0;
491
		n += m;
492
		cnt -= m;
493
	}
494
	pos += m;
495
	mkstat(&d, 0, Qroot);
496
	m = convD2M(&d, &buf[n], blen);
497
	if(off <= pos){
498
		if(m <= BIT16SZ || m > cnt)
499
			return n;
500
		n += m;
501
		cnt -= m;
502
	}
503
	pos += m;
504
	for (fid = fids; fid; fid = fid->next){
505
		if(FILE(fid->qid.path) != Qdir)
506
			continue;
507
		mkstat(&d, NUM(fid->qid.path), Qdir);
508
		m = convD2M(&d, &buf[n], blen-n);
509
		if(off <= pos){
510
			if(m <= BIT16SZ || m > cnt)
511
				break;
512
			n += m;
513
			cnt -= m;
514
		}
515
		pos += m;
516
	}
517
	return n;
518
}
519
 
520
int
521
readdir(Fid *f, uchar *buf, long off, int cnt, int blen)
522
{
523
	int i, m, n;
524
	long pos;
525
	Dir d;
526
 
527
	n = 0;
528
	pos = 0;
529
	for (i = 0; i < Qtop; i++){
530
		mkstat(&d, NUM(f->qid.path), i);
531
		m = convD2M(&d, &buf[n], blen-n);
532
		if(off <= pos){
533
			if(m <= BIT16SZ || m > cnt)
534
				break;
535
			n += m;
536
			cnt -= m;
537
		}
538
		pos += m;
539
	}
540
	return n;
541
}
542
 
543
void
544
readbuf(char *s, long n)
545
{
546
	rhdr.count = thdr.count;
547
	if(thdr.offset >= n){
548
		rhdr.count = 0;
549
		return;
550
	}
551
	if(thdr.offset+rhdr.count > n)
552
		rhdr.count = n - thdr.offset;
553
	rhdr.data = s + thdr.offset;
554
}
555
 
556
char*
557
rread(Fid *f)
558
{
559
	long off;
560
	int n, cnt, t;
561
 
562
	rhdr.count = 0;
563
	off = thdr.offset;
564
	cnt = thdr.count;
565
 
566
	if(cnt > messagesize - IOHDRSZ)
567
		cnt = messagesize - IOHDRSZ;
568
 
569
	rhdr.data = (char*)mbuf;
570
 
571
	n = 0;
572
	t = FILE(f->qid.path);
573
	switch(t){
574
	case Qtop:
575
		n = readtopdir(f, mbuf, off, cnt, messagesize - IOHDRSZ);
576
		rhdr.count = n;
577
		return nil;
578
	case Qclassical:
579
		n = readclasdir(f, mbuf, off, cnt, messagesize - IOHDRSZ);
580
		rhdr.count = n;
581
		return nil;
582
	case Qdir:
583
	case Qroot:
584
		n = readdir(f, mbuf, off, cnt, messagesize - IOHDRSZ);
585
		rhdr.count = n;
586
		return nil;
587
	case Qctl:
588
		snprint(bigbuf, sizeof bigbuf, "%d objects in tree (%d holes)\n", notab, hotab);
589
		break;
590
	case Qchildren:
591
	case Qdigest:
592
	case Qfiles:
593
	case Qfulltext:
594
	case Qkey:
595
	case Qminiparentage:
596
	case Qparent:
597
	case Qparentage:
598
	case Qtext:
599
	case Qtype:
600
		n = fileinfo(bigbuf, sizeof bigbuf, NUM(f->qid.path), t);
601
		break;
602
	default:
603
		sysfatal("rread: %d", t);
604
	}
605
	readbuf(bigbuf, n);
606
	return nil;
607
}
608
 
609
char*
610
rwrite(Fid *f)
611
{
612
	long cnt;
613
	char *p;
614
 
615
	if(FILE(f->qid.path) != Qctl)
616
		return Eperm;
617
	rhdr.count = 0;
618
	cnt = thdr.count;
619
	if(p = strchr(thdr.data, '\n'))
620
		*p = '\0';
621
	if(strncmp(thdr.data, "quit", cnt) == 0)
622
		threadexitsall(nil);
623
	else if(strncmp(thdr.data, "reread", cnt) == 0)
624
		reread();
625
	else
626
		return "illegal command";
627
	rhdr.count = thdr.count;
628
	return nil;
629
}
630
 
631
char *
632
rclunk(Fid *f)
633
{
634
	f->flags &= ~(Open|Busy);
635
	return 0;
636
}
637
 
638
char *
639
rremove(Fid *)
640
{
641
	return Eperm;
642
}
643
 
644
char *
645
rstat(Fid *f)
646
{
647
	Dir d;
648
 
649
	mkstat(&d, NUM(f->qid.path), FILE(f->qid.path));
650
	rhdr.nstat = convD2M(&d, mbuf, messagesize - IOHDRSZ);
651
	rhdr.stat = mbuf;
652
	return 0;
653
}
654
 
655
char *
656
rwstat(Fid*)
657
{
658
	return Eperm;
659
}
660
 
661
Fid *
662
newfid(int fid)
663
{
664
	Fid *f, *ff;
665
 
666
	ff = nil;
667
	for(f = fids; f; f = f->next)
668
		if(f->fid == fid){
669
			return f;
670
		}else if(ff == nil && (f->flags & Busy) == 0)
671
			ff = f;
672
	if(ff == nil){
673
		ff = malloc(sizeof *ff);
674
		if (ff == nil)
675
			sysfatal("malloc: %r");
676
		memset(ff, 0, sizeof *ff);
677
		ff->next = fids;
678
		fids = ff;
679
	}
680
	ff->fid = fid;
681
	return ff;
682
}
683
 
684
void
685
io(void *)
686
{
687
	char *err, e[32];
688
	int n;
689
	extern int p[];
690
	Fid *f;
691
 
692
	threadsetname("file server");
693
	close(p[1]);
694
	for(;;){
695
		/*
696
		 * reading from a pipe or a network device
697
		 * will give an error after a few eof reads
698
		 * however, we cannot tell the difference
699
		 * between a zero-length read and an interrupt
700
		 * on the processes writing to us,
701
		 * so we wait for the error
702
		 */
703
		n = read9pmsg(mfd[0], mdata, messagesize);
704
		if(n == 0)
705
			continue;
706
		if(n < 0){
707
			rerrstr(e, sizeof e);
708
			if (strcmp(e, "interrupted") == 0){
709
				if (debug & DbgFs) fprint(2, "read9pmsg interrupted\n");
710
				continue;
711
			}
712
			return;
713
		}
714
		if(convM2S(mdata, n, &thdr) == 0)
715
			continue;
716
 
717
		if(debug & DbgFs)
718
			fprint(2, "io:<-%F\n", &thdr);
719
 
720
		rhdr.data = (char*)mbuf;
721
 
722
		if(!fcalls[thdr.type])
723
			err = "bad fcall type";
724
		else {
725
			f = newfid(thdr.fid);
726
			err = (*fcalls[thdr.type])(f);
727
		}
728
		if(err){
729
			rhdr.type = Rerror;
730
			rhdr.ename = err;
731
		}else{
732
			rhdr.type = thdr.type + 1;
733
			rhdr.fid = thdr.fid;
734
		}
735
		rhdr.tag = thdr.tag;
736
		if(debug & DbgFs)
737
			fprint(2, "io:->%F\n", &rhdr);/**/
738
		n = convS2M(&rhdr, mdata, messagesize);
739
		if(write(mfd[1], mdata, n) != n)
740
			sysfatal("mount write");
741
	}
742
	threadexitsall("die yankee pig dog");
743
}
744
 
745
int
746
newid(void)
747
{
748
	int rv;
749
	static int id;
750
	static Lock idlock;
751
 
752
	lock(&idlock);
753
	rv = ++id;
754
	unlock(&idlock);
755
 
756
	return rv;
757
}