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/cmd/unix/drawterm/kern/devfs-posix.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	<sys/types.h>
3
#include	<sys/stat.h>
4
#include	<dirent.h>
5
#include	<fcntl.h>
6
#include	<errno.h>
7
#include	<stdio.h> /* for remove, rename */
8
#include	<limits.h>
9
 
10
#ifndef NAME_MAX
11
#	define NAME_MAX 256
12
#endif
13
#include	"lib.h"
14
#include	"dat.h"
15
#include	"fns.h"
16
#include	"error.h"
17
 
18
 
19
typedef	struct Ufsinfo	Ufsinfo;
20
 
21
enum
22
{
23
	NUID	= 256,
24
	NGID	= 256,
25
	MAXPATH	= 1024,
26
	MAXCOMP	= 128
27
};
28
 
29
struct Ufsinfo
30
{
31
	int	mode;
32
	int	fd;
33
	int	uid;
34
	int	gid;
35
	DIR*	dir;
36
	vlong	offset;
37
	QLock	oq;
38
	char nextname[NAME_MAX];
39
};
40
 
41
char	*base = "/";
42
 
43
static	Qid	fsqid(char*, struct stat *);
44
static	void	fspath(Chan*, char*, char*);
45
static	ulong	fsdirread(Chan*, uchar*, int, ulong);
46
static	int	fsomode(int);
47
 
48
/* clumsy hack, but not worse than the Path stuff in the last one */
49
static char*
50
uc2name(Chan *c)
51
{
52
	char *s;
53
 
54
	if(c->name == nil)
55
		return "/";
56
	s = c2name(c);
57
	if(s[0]=='#' && s[1]=='U')
58
		return s+2;
59
	return s;
60
}
61
 
62
static char*
63
lastelem(Chan *c)
64
{
65
	char *s, *t;
66
 
67
	s = uc2name(c);
68
	if((t = strrchr(s, '/')) == nil)
69
		return s;
70
	if(t[1] == 0)
71
		return t;
72
	return t+1;
73
}
74
 
75
static Chan*
76
fsattach(char *spec)
77
{
78
	Chan *c;
79
	struct stat stbuf;
80
	static int devno;
81
	Ufsinfo *uif;
82
 
83
	if(stat(base, &stbuf) < 0)
84
		error(strerror(errno));
85
 
86
	c = devattach('U', spec);
87
 
88
	uif = mallocz(sizeof(Ufsinfo), 1);
89
	uif->mode = stbuf.st_mode;
90
	uif->uid = stbuf.st_uid;
91
	uif->gid = stbuf.st_gid;
92
 
93
	c->aux = uif;
94
	c->dev = devno++;
95
	c->qid.type = QTDIR;
96
/*print("fsattach %s\n", c2name(c));*/
97
 
98
	return c;
99
}
100
 
101
static Chan*
102
fsclone(Chan *c, Chan *nc)
103
{
104
	Ufsinfo *uif;
105
 
106
	uif = mallocz(sizeof(Ufsinfo), 1);
107
	*uif = *(Ufsinfo*)c->aux;
108
	nc->aux = uif;
109
 
110
	return nc;
111
}
112
 
113
static int
114
fswalk1(Chan *c, char *name)
115
{
116
	struct stat stbuf;
117
	char path[MAXPATH];
118
	Ufsinfo *uif;
119
 
120
	fspath(c, name, path);
121
 
122
	/*print("** fs walk '%s' -> %s\n", path, name);  */
123
 
124
	if(stat(path, &stbuf) < 0)
125
		return 0;
126
 
127
	uif = c->aux;
128
 
129
	uif->mode = stbuf.st_mode;
130
	uif->uid = stbuf.st_uid;
131
	uif->gid = stbuf.st_gid;
132
 
133
	c->qid = fsqid(path, &stbuf);
134
 
135
	return 1;
136
}
137
 
138
extern Cname* addelem(Cname*, char*);
139
 
140
static Walkqid*
141
fswalk(Chan *c, Chan *nc, char **name, int nname)
142
{
143
	int i;
144
	Cname *cname;
145
	Walkqid *wq;
146
 
147
	if(nc != nil)
148
		panic("fswalk: nc != nil");
149
	wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid));
150
	nc = devclone(c);
151
	cname = c->name;
152
	incref(&cname->ref);
153
 
154
	fsclone(c, nc);
155
	wq->clone = nc;
156
	for(i=0; i<nname; i++){
157
		nc->name = cname;
158
		if(fswalk1(nc, name[i]) == 0)
159
			break;
160
		cname = addelem(cname, name[i]);
161
		wq->qid[i] = nc->qid;
162
	}
163
	nc->name = cname;
164
	if(i != nname){
165
		cclose(nc);
166
		wq->clone = nil;
167
	}
168
	wq->nqid = i;
169
	return wq;
170
}
171
 
172
static int
173
fsstat(Chan *c, uchar *buf, int n)
174
{
175
	Dir d;
176
	struct stat stbuf;
177
	char path[MAXPATH];
178
 
179
	if(n < BIT16SZ)
180
		error(Eshortstat);
181
 
182
	fspath(c, 0, path);
183
	if(stat(path, &stbuf) < 0)
184
		error(strerror(errno));
185
 
186
	d.name = lastelem(c);
187
	d.uid = "unknown";
188
	d.gid = "unknown";
189
	d.muid = "unknown";
190
	d.qid = c->qid;
191
	d.mode = (c->qid.type<<24)|(stbuf.st_mode&0777);
192
	d.atime = stbuf.st_atime;
193
	d.mtime = stbuf.st_mtime;
194
	d.length = stbuf.st_size;
195
	d.type = 'U';
196
	d.dev = c->dev;
197
	return convD2M(&d, buf, n);
198
}
199
 
200
static Chan*
201
fsopen(Chan *c, int mode)
202
{
203
	char path[MAXPATH];
204
	int m, isdir;
205
	Ufsinfo *uif;
206
 
207
/*print("fsopen %s\n", c2name(c));*/
208
	m = mode & (OTRUNC|3);
209
	switch(m) {
210
	case 0:
211
		break;
212
	case 1:
213
	case 1|16:
214
		break;
215
	case 2:	
216
	case 0|16:
217
	case 2|16:
218
		break;
219
	case 3:
220
		break;
221
	default:
222
		error(Ebadarg);
223
	}
224
 
225
	isdir = c->qid.type & QTDIR;
226
 
227
	if(isdir && mode != OREAD)
228
		error(Eperm);
229
 
230
	m = fsomode(m & 3);
231
	c->mode = openmode(mode);
232
 
233
	uif = c->aux;
234
 
235
	fspath(c, 0, path);
236
	if(isdir) {
237
		uif->dir = opendir(path);
238
		if(uif->dir == 0)
239
			error(strerror(errno));
240
	}	
241
	else {
242
		if(mode & OTRUNC)
243
			m |= O_TRUNC;
244
		uif->fd = open(path, m, 0666);
245
 
246
		if(uif->fd < 0)
247
			error(strerror(errno));
248
	}
249
	uif->offset = 0;
250
 
251
	c->offset = 0;
252
	c->flag |= COPEN;
253
	return c;
254
}
255
 
256
static void
257
fscreate(Chan *c, char *name, int mode, ulong perm)
258
{
259
	int fd, m;
260
	char path[MAXPATH];
261
	struct stat stbuf;
262
	Ufsinfo *uif;
263
 
264
	m = fsomode(mode&3);
265
 
266
	fspath(c, name, path);
267
 
268
	uif = c->aux;
269
 
270
	if(perm & DMDIR) {
271
		if(m)
272
			error(Eperm);
273
 
274
		if(mkdir(path, perm & 0777) < 0)
275
			error(strerror(errno));
276
 
277
		fd = open(path, 0);
278
		if(fd >= 0) {
279
			chmod(path, perm & 0777);
280
			chown(path, uif->uid, uif->uid);
281
		}
282
		close(fd);
283
 
284
		uif->dir = opendir(path);
285
		if(uif->dir == 0)
286
			error(strerror(errno));
287
	}
288
	else {
289
		fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0666);
290
		if(fd >= 0) {
291
			if(m != 1) {
292
				close(fd);
293
				fd = open(path, m);
294
			}
295
			chmod(path, perm & 0777);
296
			chown(path, uif->uid, uif->gid);
297
		}
298
		if(fd < 0)
299
			error(strerror(errno));
300
		uif->fd = fd;
301
	}
302
 
303
	if(stat(path, &stbuf) < 0)
304
		error(strerror(errno));
305
	c->qid = fsqid(path, &stbuf);
306
	c->offset = 0;
307
	c->flag |= COPEN;
308
	c->mode = openmode(mode);
309
}
310
 
311
static void
312
fsclose(Chan *c)
313
{
314
	Ufsinfo *uif;
315
 
316
	uif = c->aux;
317
 
318
	if(c->flag & COPEN) {
319
		if(c->qid.type & QTDIR)
320
			closedir(uif->dir);
321
		else
322
			close(uif->fd);
323
	}
324
 
325
	free(uif);
326
}
327
 
328
static long
329
fsread(Chan *c, void *va, long n, vlong offset)
330
{
331
	int fd, r;
332
	Ufsinfo *uif;
333
 
334
/*print("fsread %s\n", c2name(c));*/
335
	if(c->qid.type & QTDIR)
336
		return fsdirread(c, va, n, offset);
337
 
338
	uif = c->aux;
339
	qlock(&uif->oq);
340
	if(waserror()) {
341
		qunlock(&uif->oq);
342
		nexterror();
343
	}
344
	fd = uif->fd;
345
	if(uif->offset != offset) {
346
		r = lseek(fd, offset, 0);
347
		if(r < 0)
348
			error(strerror(errno));
349
		uif->offset = offset;
350
	}
351
 
352
	n = read(fd, va, n);
353
	if(n < 0)
354
		error(strerror(errno));
355
 
356
	uif->offset += n;
357
	qunlock(&uif->oq);
358
	poperror();
359
 
360
	return n;
361
}
362
 
363
static long
364
fswrite(Chan *c, void *va, long n, vlong offset)
365
{
366
	int fd, r;
367
	Ufsinfo *uif;
368
 
369
	uif = c->aux;
370
 
371
	qlock(&uif->oq);
372
	if(waserror()) {
373
		qunlock(&uif->oq);
374
		nexterror();
375
	}
376
	fd = uif->fd;
377
	if(uif->offset != offset) {
378
		r = lseek(fd, offset, 0);
379
		if(r < 0)
380
			error(strerror(errno));
381
		uif->offset = offset;
382
	}
383
 
384
	n = write(fd, va, n);
385
	if(n < 0)
386
		error(strerror(errno));
387
 
388
	uif->offset += n;
389
	qunlock(&uif->oq);
390
	poperror();
391
 
392
	return n;
393
}
394
 
395
static void
396
fsremove(Chan *c)
397
{
398
	int n;
399
	char path[MAXPATH];
400
 
401
	fspath(c, 0, path);
402
	if(c->qid.type & QTDIR)
403
		n = rmdir(path);
404
	else
405
		n = remove(path);
406
	if(n < 0)
407
		error(strerror(errno));
408
}
409
 
410
int
411
fswstat(Chan *c, uchar *buf, int n)
412
{
413
	Dir d;
414
	struct stat stbuf;
415
	char old[MAXPATH], new[MAXPATH];
416
	char strs[MAXPATH*3], *p;
417
	Ufsinfo *uif;
418
 
419
	if(convM2D(buf, n, &d, strs) != n)
420
		error(Ebadstat);
421
 
422
	fspath(c, 0, old);
423
	if(stat(old, &stbuf) < 0)
424
		error(strerror(errno));
425
 
426
	uif = c->aux;
427
 
428
	fspath(c, 0, old);
429
	if(~d.mode != 0 && (int)(d.mode&0777) != (int)(stbuf.st_mode&0777)) {
430
		if(chmod(old, d.mode&0777) < 0)
431
			error(strerror(errno));
432
		uif->mode &= ~0777;
433
		uif->mode |= d.mode&0777;
434
	}
435
 
436
	if(d.name[0] && strcmp(d.name, lastelem(c)) != 0) {
437
		fspath(c, 0, old);
438
		strcpy(new, old);
439
		p = strrchr(new, '/');
440
		strcpy(p+1, d.name);
441
		if(rename(old, new) < 0)
442
			error(strerror(errno));
443
	}
444
 
445
/*
446
	p = name2pass(gid, d.gid);
447
	if(p == 0)
448
		error(Eunknown);
449
 
450
	if(p->id != stbuf.st_gid) {
451
		if(chown(old, stbuf.st_uid, p->id) < 0)
452
			error(strerror(errno));
453
 
454
		uif->gid = p->id;
455
	}
456
*/
457
	return n;
458
}
459
 
460
static Qid
461
fsqid(char *p, struct stat *st)
462
{
463
	Qid q;
464
	int dev;
465
	ulong h;
466
	static int nqdev;
467
	static uchar *qdev;
468
 
469
	if(qdev == 0)
470
		qdev = mallocz(65536U, 1);
471
 
472
	q.type = 0;
473
	if((st->st_mode&S_IFMT) ==  S_IFDIR)
474
		q.type = QTDIR;
475
 
476
	dev = st->st_dev & 0xFFFFUL;
477
	if(qdev[dev] == 0)
478
		qdev[dev] = ++nqdev;
479
 
480
	h = 0;
481
	while(*p != '\0')
482
		h += *p++ * 13;
483
 
484
	q.path = (vlong)qdev[dev]<<32;
485
	q.path |= h;
486
	q.vers = st->st_mtime;
487
 
488
	return q;
489
}
490
 
491
static void
492
fspath(Chan *c, char *ext, char *path)
493
{
494
	strcpy(path, base);
495
	strcat(path, "/");
496
	strcat(path, uc2name(c));
497
	if(ext){
498
		strcat(path, "/");
499
		strcat(path, ext);
500
	}
501
	cleanname(path);
502
}
503
 
504
static int
505
isdots(char *name)
506
{
507
	if(name[0] != '.')
508
		return 0;
509
	if(name[1] == '\0')
510
		return 1;
511
	if(name[1] != '.')
512
		return 0;
513
	if(name[2] == '\0')
514
		return 1;
515
	return 0;
516
}
517
 
518
static int
519
p9readdir(char *name, Ufsinfo *uif)
520
{
521
	struct dirent *de;
522
 
523
	if(uif->nextname[0]){
524
		strcpy(name, uif->nextname);
525
		uif->nextname[0] = 0;
526
		return 1;
527
	}
528
 
529
	de = readdir(uif->dir);
530
	if(de == NULL)
531
		return 0;
532
 
533
	strcpy(name, de->d_name);
534
	return 1;
535
}
536
 
537
static ulong
538
fsdirread(Chan *c, uchar *va, int count, ulong offset)
539
{
540
	int i;
541
	Dir d;
542
	long n;
543
	char de[NAME_MAX];
544
	struct stat stbuf;
545
	char path[MAXPATH], dirpath[MAXPATH];
546
	Ufsinfo *uif;
547
 
548
/*print("fsdirread %s\n", c2name(c));*/
549
	i = 0;
550
	uif = c->aux;
551
 
552
	errno = 0;
553
	if(uif->offset != offset) {
554
		if(offset != 0)
555
			error("bad offset in fsdirread");
556
		uif->offset = offset;  /* sync offset */
557
		uif->nextname[0] = 0;
558
		rewinddir(uif->dir);
559
	}
560
 
561
	fspath(c, 0, dirpath);
562
 
563
	while(i+BIT16SZ < count) {
564
		if(!p9readdir(de, uif))
565
			break;
566
 
567
		if(de[0]==0 || isdots(de))
568
			continue;
569
 
570
		d.name = de;
571
		sprint(path, "%s/%s", dirpath, de);
572
		memset(&stbuf, 0, sizeof stbuf);
573
 
574
		if(stat(path, &stbuf) < 0) {
575
			/* fprint(2, "dir: bad path %s\n", path); */
576
			/* but continue... probably a bad symlink */
577
		}
578
 
579
		d.uid = "unknown";
580
		d.gid = "unknown";
581
		d.muid = "unknown";
582
		d.qid = fsqid(path, &stbuf);
583
		d.mode = (d.qid.type<<24)|(stbuf.st_mode&0777);
584
		d.atime = stbuf.st_atime;
585
		d.mtime = stbuf.st_mtime;
586
		d.length = stbuf.st_size;
587
		d.type = 'U';
588
		d.dev = c->dev;
589
		n = convD2M(&d, (uchar*)va+i, count-i);
590
		if(n == BIT16SZ){
591
			strcpy(uif->nextname, de);
592
			break;
593
		}
594
		i += n;
595
	}
596
/*print("got %d\n", i);*/
597
	uif->offset += i;
598
	return i;
599
}
600
 
601
static int
602
fsomode(int m)
603
{
604
	switch(m) {
605
	case 0:			/* OREAD */
606
	case 3:			/* OEXEC */
607
		return 0;
608
	case 1:			/* OWRITE */
609
		return 1;
610
	case 2:			/* ORDWR */
611
		return 2;
612
	}
613
	error(Ebadarg);
614
	return 0;
615
}
616
 
617
Dev fsdevtab = {
618
	'U',
619
	"fs",
620
 
621
	devreset,
622
	devinit,
623
	devshutdown,
624
	fsattach,
625
	fswalk,
626
	fsstat,
627
	fsopen,
628
	fscreate,
629
	fsclose,
630
	fsread,
631
	devbread,
632
	fswrite,
633
	devbwrite,
634
	fsremove,
635
	fswstat,
636
};