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/kfs/con.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	"all.h"
2
#include	"9p1.h"
3
 
4
static	char	elem[NAMELEN];
5
static	Filsys*	cur_fs;
6
static	char	conline[100];
7
 
8
void
9
consserve(void)
10
{
11
	con_session();
12
	cmd_exec("cfs");
13
	cmd_exec("user");
14
}
15
 
16
int
17
cmd_exec(char *arg)
18
{
19
	char *s, *c;
20
	int i;
21
 
22
	for(i=0; s = command[i].string; i++) {
23
		for(c=arg; *s; c++)
24
			if(*c != *s++)
25
				goto brk;
26
		if(*c == '\0' || *c == ' ' || *c == '\t'){
27
			cons.arg = c;
28
			(*command[i].func)();
29
			return 1;
30
		}
31
	brk:;
32
	}
33
	return 0;
34
}
35
 
36
void
37
cmd_check(void)
38
{
39
	char *s;
40
	int flags;
41
 
42
	flags = 0;
43
	for(s = cons.arg; *s; s++){
44
		while(*s == ' ' || *s == '\t')
45
			s++;
46
		if(*s == '\0')
47
			break;
48
		switch(*s){
49
		/* rebuild the free list */
50
		case 'f':	flags |= Cfree;			break;
51
		/* fix bad tags */
52
		case 't':	flags |= Ctag;			break;
53
		/* fix bad tags and clear the contents of the block */
54
		case 'c':	flags |= Cream;			break;
55
		/* delete all redundant references to a block */
56
		case 'd':	flags |= Cbad;			break;
57
		/* read and check tags on all blocks */
58
		case 'r':	flags |= Crdall;		break;
59
		/* write all of the blocks you touch */
60
		case 'w':	flags |= Ctouch;		break;
61
		/* print all directories as they are read */
62
		case 'p':	flags |= Cpdir;			break;
63
		/* print all files as they are read */
64
		case 'P':	flags |= Cpfile;		break;
65
		/* quiet, just report really nasty stuff */
66
		case 'q':	flags |= Cquiet;		break;
67
		}
68
	}
69
	check(cur_fs, flags);
70
}
71
 
72
enum
73
{
74
	Sset	= (1<<0),
75
	Setc	= (1<<1),
76
};
77
void
78
cmd_stats(void)
79
{
80
	cprint("work stats\n");
81
	cprint("	work = %A rps\n", (Filta){&cons.work, 1});
82
	cprint("	rate = %A tBps\n", (Filta){&cons.rate, 1000});
83
	cprint("	hits = %A iops\n", (Filta){&cons.bhit, 1});
84
	cprint("	read = %A iops\n", (Filta){&cons.bread, 1});
85
	cprint("	init = %A iops\n", (Filta){&cons.binit, 1});
86
/*	for(i = 0; i < MAXTAG; i++)
87
		cprint("	tag %G = %A iops\n", i, (Filta){&cons.tags[i], 1});
88
*/
89
}
90
 
91
void
92
cmd_sync(void)
93
{
94
	rlock(&mainlock);
95
	syncall();
96
	runlock(&mainlock);
97
}
98
 
99
void
100
cmd_halt(void)
101
{
102
	wlock(&mainlock);
103
	syncall();
104
	superok(cur_fs->dev, superaddr(cur_fs->dev), 1);
105
	print("kfs: file system halted\n");
106
}
107
 
108
void
109
cmd_start(void)
110
{
111
	superok(cur_fs->dev, superaddr(cur_fs->dev), 0);
112
	wunlock(&mainlock);
113
	print("kfs: file system started\n");
114
}
115
 
116
void
117
cmd_help(void)
118
{
119
	int i;
120
 
121
	for(i=0; command[i].string; i++)
122
		cprint("	%s %s\n", command[i].string, command[i].args);
123
	cprint("check options:\n"
124
		" r	read all blocks\n"
125
		" f	rebuild the free list\n"
126
		" t	fix all bad tags\n"
127
		" c	fix bad tags and zero the blocks\n"
128
		" d	delete all redundant references to blocks\n"
129
		" p	print directories as they are checked\n"
130
		" P	print all files as they are checked\n"
131
		" w	write all blocks that are read\n");
132
}
133
 
134
void
135
cmd_create(void)
136
{
137
	int uid, gid, err;
138
	long perm;
139
	char oelem[NAMELEN];
140
	char name[NAMELEN];
141
 
142
	if(err = con_clone(FID1, FID2)){
143
		cprint("clone failed: %s\n", errstring[err]);
144
		return;
145
	}
146
	if(skipbl(1)){
147
		cprint("skipbl\n");
148
		return;
149
	}
150
	oelem[0] = 0;
151
	while(nextelem()) {
152
		if(oelem[0])
153
			if(err = con_walk(FID2, oelem)){
154
				cprint("walk failed: %s\n", errstring[err]);
155
				return;
156
			}
157
		memmove(oelem, elem, NAMELEN);
158
	}
159
	if(skipbl(1))
160
		return;
161
	uid = strtouid(cname(name));
162
	if(uid == 0){
163
		cprint("unknown user %s\n", name);
164
		return;
165
	}
166
	gid = strtouid(cname(name));
167
	if(gid == 0){
168
		cprint("unknown group %s\n", name);
169
		return;
170
	}
171
	perm = number(0777, 8);
172
	skipbl(0);
173
	for(; *cons.arg; cons.arg++){
174
		if(*cons.arg == 'l')
175
			perm |= PLOCK;
176
		else
177
		if(*cons.arg == 'a')
178
			perm |= PAPND;
179
		else
180
		if(*cons.arg == 'd')
181
			perm |= PDIR;
182
		else
183
			break;
184
	}
185
	err = con_create(FID2, elem, uid, gid, perm, 0);
186
	if(err)
187
		cprint("can't create %s: %s\n", elem, errstring[err]);
188
}
189
 
190
void
191
cmd_clri(void)
192
{
193
	if(con_clone(FID1, FID2))
194
		return;
195
	if(skipbl(1))
196
		return;
197
	while(nextelem())
198
		if(con_walk(FID2, elem)){
199
			cprint("can't walk %s\n", elem);
200
			return;
201
		}
202
	con_clri(FID2);
203
}
204
 
205
void
206
cmd_rename(void)
207
{
208
	ulong perm;
209
	Dentry d;
210
	char stat[DIRREC];
211
	char oelem[NAMELEN], noelem[NAMELEN], nxelem[NAMELEN];
212
	int err;
213
 
214
	if(con_clone(FID1, FID2))
215
		return;
216
	if(skipbl(1))
217
		return;
218
	oelem[0] = 0;
219
	while(nextelem()) {
220
		if(oelem[0])
221
			if(con_walk(FID2, oelem)){
222
				cprint("file does not exits");
223
				return;
224
			}
225
		memmove(oelem, elem, NAMELEN);
226
	}
227
	if(skipbl(1))
228
		return;
229
	if(cons.arg[0]=='/'){
230
		if(con_clone(FID1, FID3))
231
			return;
232
		noelem[0] = 0;
233
		while(nextelem()){
234
			if(noelem[0])
235
				if(con_walk(FID3, noelem)){
236
					cprint("target path %s does not exist", noelem);
237
					return;
238
				}
239
			memmove(noelem, elem, NAMELEN);
240
		}
241
		if(!con_walk(FID3, elem)){
242
			cprint("target %s already exists\n", elem);
243
			return;
244
		}
245
		if(con_walk(FID2, oelem)){
246
			cprint("src %s does not exist\n", oelem);
247
			return;
248
		}
249
		/*
250
		 * we know the target does not exist,
251
		 * the source does exist.
252
		 * to do the rename, create the target and then
253
		 * copy the directory entry directly.  then remove the source.
254
		 */
255
		if(err = con_stat(FID2, stat)){
256
			cprint("can't stat file: %s\n", errstring[err]);
257
			return;
258
		}
259
		convM2D9p1(stat, &d);
260
		perm = (d.mode&0777)|((d.mode&0x7000)<<17);
261
		if(err = con_create(FID3, elem, d.uid, d.gid, perm, (d.mode&DDIR)?OREAD:ORDWR)){
262
			cprint("can't create %s: %s\n", elem, errstring[err]);
263
			return;
264
		}
265
		if(err = con_swap(FID2, FID3)){
266
			cprint("can't swap data: %s\n", errstring[err]);
267
			return;
268
		}
269
		if(err = con_remove(FID2)){
270
			cprint("can't remove file: %s\n", errstring[err]);
271
			return;
272
		}		
273
	}else{
274
		cname(nxelem);
275
		if(strchr(nxelem, '/')){
276
			cprint("bad rename target: not full path, but contains slashes\n");
277
			return;
278
		}
279
		if(!con_walk(FID2, nxelem))
280
			cprint("file %s already exists\n", nxelem);
281
		else if(con_walk(FID2, oelem))
282
			cprint("file does not already exist\n");
283
		else if(err = con_stat(FID2, stat))
284
			cprint("can't stat file: %s\n", errstring[err]);
285
		else{
286
			convM2D9p1(stat, &d);
287
			strncpy(d.name, nxelem, NAMELEN);
288
			convD2M9p1(&d, stat);
289
			if(err = con_wstat(FID2, stat))
290
				cprint("can't move file: %s\n", errstring[err]);
291
		}
292
	}	
293
}
294
 
295
void
296
cmd_remove(void)
297
{
298
	if(con_clone(FID1, FID2))
299
		return;
300
	if(skipbl(1))
301
		return;
302
	while(nextelem())
303
		if(con_walk(FID2, elem)){
304
			cprint("can't walk %s\n", elem);
305
			return;
306
		}
307
	con_remove(FID2);
308
}
309
 
310
void
311
cmd_cfs(void)
312
{
313
	Filsys *fs;
314
 
315
	if(*cons.arg != ' ') {
316
		fs = &filesys[0];		/* default */
317
	} else {
318
		if(skipbl(1)){
319
			cprint("skipbl\n");
320
			return;
321
		}
322
		if(!nextelem())
323
			fs = &filesys[0];	/* default */
324
		else
325
			fs = fsstr(elem);
326
	}
327
	if(fs == 0) {
328
		cprint("unknown file system %s\n", elem);
329
		return;
330
	}
331
	if(con_attach(FID1, "adm", fs->name))
332
		panic("FID1 attach to root");
333
	cur_fs = fs;
334
}
335
 
336
/*
337
 * find out the length of a file
338
 * given the mesg version of a stat buffer
339
 * we call this because convM2D is different
340
 * for the file system than in the os
341
 */
342
static uvlong
343
statlen(char *ap)
344
{
345
	uchar *p;
346
	ulong ll, hl;
347
 
348
	p = (uchar*)ap;
349
	p += 3*28+5*4;
350
	ll = p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24);
351
	hl = p[4] | (p[5]<<8) | (p[6]<<16) | (p[7]<<24);
352
	return ll | ((uvlong) hl << 32);
353
}
354
 
355
int
356
adduser(char *user, int isgroup)
357
{
358
	char stat[DIRREC];
359
	char msg[100];
360
	Uid *u;
361
	int i, c, nu;
362
 
363
	/*
364
	 * check uniq of name
365
	 * and get next uid
366
	 */
367
	cmd_exec("cfs");
368
	cmd_exec("user");
369
	if(isgroup)
370
		nu = 9000;
371
	else
372
		nu = 0;
373
	for(i=0, u=uid; i<conf.nuid; i++,u++) {
374
		c = u->uid;
375
		if(c == 0)
376
			break;
377
		if(strcmp(uidspace+u->offset, user) == 0)
378
			return 1;
379
		if(c >= 9000 && !isgroup)
380
			continue;
381
		if(c > nu)
382
			nu = c;
383
	}
384
	nu++;
385
	if(isgroup){
386
		if(nu >= 0x10000) {
387
			cprint("out of group ids\n");
388
			return 0;
389
		}
390
	} else {
391
		if(nu >= 9000) {
392
			cprint("out of user ids\n");
393
			return 0;
394
		}
395
	}
396
 
397
	/*
398
	 * write onto adm/users
399
	 */
400
	if(con_clone(FID1, FID2)
401
	|| con_path(FID2, "/adm/users")
402
	|| con_open(FID2, 1)) {
403
		cprint("can't open /adm/users\n");
404
		return 0;
405
	}
406
 
407
	sprint(msg, "%d:%s:%s:\n", nu, user, user);
408
	cprint("add user %s", msg);
409
	c = strlen(msg);
410
	i = con_stat(FID2, stat);
411
	if(i){
412
		cprint("can't stat /adm/users: %s\n", errstring[i]);
413
		return 0;
414
	}
415
	i = con_write(FID2, msg, statlen(stat), c);
416
	if(i != c){
417
		cprint("short write on /adm/users: %d %d\n", c, i);
418
		return 0;
419
	}
420
	return 1;
421
}
422
 
423
void
424
cmd_newuser(void)
425
{
426
	char user[NAMELEN], param[NAMELEN], msg[100];
427
	int i, c;
428
 
429
	/*
430
	 * get uid
431
	 */
432
	cname(user);
433
	cname(param);
434
	for(i=0; i<NAMELEN; i++) {
435
		c = user[i];
436
		if(c == 0)
437
			break;
438
		if(c >= '0' && c <= '9'
439
		|| c >= 'a' && c <= 'z'
440
		|| c >= 'A' && c <= 'Z')
441
			continue;
442
		cprint("bad character in name: 0x%x\n", c);
443
		return;
444
	}
445
	if(i < 2) {
446
		cprint("name too short: %s\n", user);
447
		return;
448
	}
449
	if(i >= NAMELEN) {
450
		cprint("name too long: %s\n", user);
451
		return;
452
	}
453
 
454
	switch(param[0]){
455
	case 0:
456
		if(!adduser(user, 0))
457
			return;
458
		cmd_exec("user");
459
		break;
460
	case ':':
461
		adduser(user, 1);
462
		cmd_exec("user");
463
		return;
464
	case '#':
465
		adduser(user, 0);
466
		cmd_exec("user");
467
		return;
468
	}
469
 
470
	/*
471
	 * create directories
472
	 */
473
	cmd_exec("user");
474
	sprint(msg, "create /usr/%s %s %s 775 d", user, user, user);
475
	cmd_exec(msg);
476
	sprint(msg, "create /usr/%s/tmp %s %s 775 d", user, user, user);
477
	cmd_exec(msg);
478
	sprint(msg, "create /usr/%s/lib %s %s 775 d", user, user, user);
479
	cmd_exec(msg);
480
	sprint(msg, "create /usr/%s/bin %s %s 775 d", user, user, user);
481
	cmd_exec(msg);
482
	sprint(msg, "create /usr/%s/bin/rc %s %s 775 d", user, user, user);
483
	cmd_exec(msg);
484
	sprint(msg, "create /usr/%s/bin/mips %s %s 775 d", user, user, user);
485
	cmd_exec(msg);
486
	sprint(msg, "create /usr/%s/bin/386 %s %s 775 d", user, user, user);
487
	cmd_exec(msg);
488
	sprint(msg, "create /usr/%s/bin/power %s %s 775 d", user, user, user);
489
	cmd_exec(msg);
490
	sprint(msg, "create /usr/%s/bin/alpha %s %s 775 d", user, user, user);
491
	cmd_exec(msg);
492
}
493
 
494
void
495
cmd_checkuser(void)
496
{
497
	uchar buf[DIRREC], *p;
498
	static char utime[4];
499
 
500
	if(con_clone(FID1, FID2)
501
	|| con_path(FID2, "/adm/users")
502
	|| con_open(FID2, 0)
503
	|| con_stat(FID2, (char*)buf))
504
		return;
505
	p = buf + 3*NAMELEN + 4*4;
506
	if(memcmp(utime, p, 4) == 0)
507
		return;
508
	memmove(utime, p, 4);
509
	cmd_user();
510
}
511
 
512
void
513
cmd_allow(void)
514
{
515
	wstatallow = 1;
516
}
517
 
518
void
519
cmd_disallow(void)
520
{
521
	wstatallow = 0;
522
}
523
 
524
void
525
cmd_chat(void)
526
{
527
	chat = 1 - chat;
528
}
529
 
530
void
531
cmd_atime(void)
532
{
533
	noatime = !noatime;
534
	if(noatime)
535
		cprint("atimes will not be updated\n");
536
	else
537
		cprint("atimes will be updated\n");
538
}
539
 
540
void
541
cmd_noneattach(void)
542
{
543
	allownone = !allownone;
544
	if(allownone) 
545
		cprint("none can attach to new connections\n");
546
	else
547
		cprint("none can only attach on authenticated connections\n");
548
}
549
 
550
void
551
cmd_listen(void)
552
{
553
	char addr[NAMELEN];
554
 
555
	if(skipbl(0))
556
		strcpy(addr, "tcp!*!564");	/* 9fs */
557
	else
558
		cname(addr);
559
 
560
	if(netserve(addr))
561
		cprint("announce %s failed\n", addr);
562
	else
563
		cprint("announce %s\n", addr);
564
}
565
 
566
void
567
cmd_nowritegroup(void)
568
{
569
	writegroup = 0;
570
}
571
 
572
Command	command[] =
573
{
574
	"allow",	cmd_allow,	"",
575
	"allowoff",	cmd_disallow,	"",
576
	"atime",		cmd_atime,	"",
577
	"cfs",		cmd_cfs,	"[filesys]",
578
	"chat",		cmd_chat,	"",
579
	"check",	cmd_check,	"[cdfpPqrtw]",
580
	"clri",		cmd_clri,	"filename",
581
	"create",	cmd_create,	"filename user group perm [ald]",
582
	"disallow",	cmd_disallow,	"",
583
	"halt",		cmd_halt,	"",
584
	"help",		cmd_help,	"",
585
	"listen",		cmd_listen,	"[address]",
586
	"newuser",	cmd_newuser,	"username",
587
	"noneattach",	cmd_noneattach,	"",
588
	"nowritegroup",	cmd_nowritegroup,	"",
589
	"remove",	cmd_remove,	"filename",
590
	"rename",	cmd_rename,	"file newname",
591
	"start",	cmd_start, "",
592
	"stats",	cmd_stats,	"[fw]",
593
	"sync",		cmd_sync,	"",
594
	"user",		cmd_user,	"",
595
 
596
};
597
 
598
int
599
skipbl(int err)
600
{
601
	if(*cons.arg != ' ') {
602
		if(err)
603
			cprint("syntax error\n");
604
		return 1;
605
	}
606
	while(*cons.arg == ' ')
607
		cons.arg++;
608
	return 0;
609
}
610
 
611
char*
612
_cname(char *name)
613
{
614
	int i, c;
615
 
616
	memset(name, 0, NAMELEN);
617
	for(i=0;; i++) {
618
		c = *cons.arg;
619
		switch(c) {
620
		case ' ':
621
		case '\t':
622
		case '\n':
623
		case '\0':
624
			return name;
625
		}
626
		if(i < NAMELEN-1)
627
			name[i] = c;
628
		cons.arg++;
629
	}
630
}
631
 
632
char*
633
cname(char *name)
634
{
635
	skipbl(0);
636
	return _cname(name);
637
}
638
 
639
int
640
nextelem(void)
641
{
642
	char *e;
643
	int i, c;
644
 
645
	e = elem;
646
	while(*cons.arg == '/')
647
		cons.arg++;
648
	c = *cons.arg;
649
	if(c == 0 || c == ' ')
650
		return 0;
651
	for(i = 0; c = *cons.arg; i++) {
652
		if(c == ' ' || c == '/')
653
			break;
654
		if(i == NAMELEN) {
655
			cprint("path name component too long\n");
656
			return 0;
657
		}
658
		*e++ = c;
659
		cons.arg++;
660
	}
661
	*e = 0;
662
	return 1;
663
}
664
 
665
long
666
number(int d, int base)
667
{
668
	int c, sign, any;
669
	long n;
670
 
671
	sign = 0;
672
	any = 0;
673
	n = 0;
674
 
675
	c = *cons.arg;
676
	while(c == ' ') {
677
		cons.arg++;
678
		c = *cons.arg;
679
	}
680
	if(c == '-') {
681
		sign = 1;
682
		cons.arg++;
683
		c = *cons.arg;
684
	}
685
	while((c >= '0' && c <= '9') ||
686
	      (base == 16 && c >= 'a' && c <= 'f') ||
687
	      (base == 16 && c >= 'A' && c <= 'F')) {
688
		n *= base;
689
		if(c >= 'a' && c <= 'f')
690
			n += c - 'a' + 10;
691
		else
692
		if(c >= 'A' && c <= 'F')
693
			n += c - 'A' + 10;
694
		else
695
			n += c - '0';
696
		cons.arg++;
697
		c = *cons.arg;
698
		any = 1;
699
	}
700
	if(!any)
701
		return d;
702
	if(sign)
703
		n = -n;
704
	return n;
705
}