|
|
1.1 root 1: #include "u.h"
2: #include <sys/types.h>
3: #include <sys/stat.h>
4: #include "libc.h"
5: #include "9p.h"
6: #include "stdio.h"
7: #include "setjmp.h"
8: #include "pwd.h"
9: #include "grp.h"
10:
11: #define DBG(f)
12:
13: struct group *getgrent(void);
14: struct passwd *getpwent(void);
15:
16: #ifdef SYSV
17: # include <dirent.h>
18: # define DTYPE struct dirent
19: # define SOCKETS
20: #endif
21: #ifdef V10
22: # include <ndir.h>
23: # define DTYPE struct direct
24: #endif
25: #ifdef BSD
26: # include <sys/dir.h>
27: # define DTYPE struct direct
28: # define SOCKETS
29: #endif
30: #ifdef SOCKETS
31: # define sendmsg __sendmsg
32: # include <sys/socket.h>
33: # include <netinet/in.h>
34: # include <netdb.h>
35: # undef sendmsg
36: char bsdhost[256];
37: void remotehostname(void);
38: #endif
39:
40: typedef struct File File;
41: typedef struct Rfile Rfile;
42: typedef struct Fd Fd;
43: typedef struct Pass Pass;
44:
45: struct Fd{
46: int ref;
47: Ulong offset;
48: int fd;
49: DIR *dir;
50: };
51:
52: struct Rfile{
53: int busy;
54: int uid;
55: int gid;
56: int rclose;
57: File *file;
58: Fd *fd;
59: };
60:
61: struct File{
62: int ref;
63: char *path;
64: char *name;
65: Qid qid;
66: struct stat stbuf;
67: };
68:
69: struct Pass{
70: int id;
71: int gid;
72: char *name;
73: Pass *next;
74: };
75:
76: char data[2][MAXMSG+MAXFDATA];
77: char tdata[MAXMSG+MAXFDATA];
78: char rdata[MAXFDATA];
79: Fcall rhdr;
80: Fcall thdr;
81: Rfile *rfile;
82: File *file0;
83: int nrfilealloc;
84: jmp_buf loopjmp;
85: Pass* uid[256];
86: Pass* gid[256];
87: int devallowed;
88: int connected;
89:
90: void io(void);
91: void error(char*);
92: char *mfmt(Fcall*);
93: void sendmsg(char*);
94: int okfid(int);
95: Rfile* rfilefid(void);
96: File* newfile(void);
97: void* erealloc(void*, unsigned);
98: char* estrdup(char*);
99: char* dostat(File*, char*);
100: char* bldpath(char*, char*, char*);
101: Ulong qid(struct stat*);
102: Ulong vers(struct stat*);
103: void errjmp(char*);
104: int omode(int);
105: char* id2name(Pass**, int);
106: Pass* name2pass(Pass**, char*);
107: void getpwdf(void);
108: void getgrpf(void);
109: void perm(Rfile*, int, struct stat*);
110: void parentwrperm(Rfile*);
111:
112: void rsession(void);
113: void rattach(void);
114: void rflush(void);
115: void rclone(void);
116: void rwalk(void);
117: void ropen(void);
118: void rcreate(void);
119: void rread(void);
120: void rwrite(void);
121: void rclunk(int);
122: void rstat(void);
123: void rwstat(void);
124: void rclwalk(void);
125:
126: char Eauth[] = "authentication failed";
127: char Eperm[] = "permission denied";
128: char Ebadfid[] = "fid unknown or out of range";
129: char Efidactive[] = "fid already in use";
130: char Eopen[] = "file is open";
131: char Emode[] = "invalid open mode";
132: char Especial[] = "no access to special file";
133: char Especial0[] = "already attached without access to special files";
134: char Especial1[] = "already attached with access to special files";
135: char Enotopen[] = "file is not open";
136: char Etoolarge[] = "i/o count too large";
137: char Ebaddir[] = "i/o error on directory";
138: char Eunknown[] = "unknown user or group";
139: char Euid[] = "can't set uid";
140: char Egid[] = "can't set gid";
141: char Eowner[] = "not owner";
142:
143: int
144: main(int argc, char *argv[])
145: {
146: freopen(LOG, "a", stderr);
147: setbuf(stderr, (void*)0);
148: DBG(fprintf(stderr, "u9fs\nkill %d\n", getpid()));
149: if(argc > 1)
150: if(chroot(argv[1]) == -1)
151: error("chroot failed");
152:
153: # ifdef SOCKETS
154: remotehostname();
155: # endif
156:
157: io();
158: return 0;
159: }
160:
161: void
162: io(void)
163: {
164: int m;
165: static int toggle, ndata;
166: char *datap;
167:
168: /*
169: * TCP does not preserve record boundaries; this dance works around
170: * the problem.
171: */
172: setjmp(loopjmp);
173:
174: /*
175: * Invariant: data[toggle] has ndata bytes already
176: */
177: loop:
178: datap = data[toggle];
179: toggle ^= 1;
180: for(;;){
181: if(ndata){
182: m = convM2S(datap, &rhdr, ndata);
183: /* m is number of bytes more than a full message */
184: if(m >= 0){
185: memmove(data[toggle], datap+(ndata-m), m);
186: ndata = m;
187: break;
188: }
189: }
190: m = read(0, datap+ndata, (MAXMSG+MAXFDATA)-ndata);
191: if(m <= 0)
192: error("read");
193: ndata += m;
194: }
195:
196: thdr.type = rhdr.type+1;
197: thdr.tag = rhdr.tag;
198: thdr.fid = rhdr.fid;
199: DBG(fprintf(stderr, ">> %s\n", mfmt(&rhdr)));
200: switch(rhdr.type){
201: case Tnop:
202: case Tflush: /* this is a synchronous fs; easy */
203: break;
204: case Tsession:
205: rsession();
206: break;
207: case Tattach:
208: rattach();
209: break;
210: case Tclone:
211: rclone();
212: break;
213: case Twalk:
214: rwalk();
215: break;
216: case Tstat:
217: rstat();
218: break;
219: case Twstat:
220: rwstat();
221: break;
222: case Topen:
223: ropen();
224: break;
225: case Tcreate:
226: rcreate();
227: break;
228: case Tread:
229: rread();
230: break;
231: case Twrite:
232: rwrite();
233: break;
234: case Tclunk:
235: rclunk(0);
236: break;
237: case Tremove:
238: rclunk(1);
239: break;
240: default:
241: fprintf(stderr, "unknown message %s\n", mfmt(&rhdr));
242: error("bad message");
243: }
244: sendmsg(0);
245: goto loop;
246: }
247:
248: void
249: rsession(void)
250: {
251: memset(thdr.authid, 0, sizeof(thdr.authid));
252: memset(thdr.authdom, 0, sizeof(thdr.authdom));
253: memset(thdr.chal, 0, sizeof(thdr.chal));
254: }
255:
256: void
257: rattach(void)
258: {
259: Rfile *rf;
260: char *err;
261: Pass *p;
262:
263: err = 0;
264: if(file0 == 0){
265: file0 = newfile();
266: file0->ref++; /* one extra to hold it up */
267: file0->path = estrdup("/");
268: file0->name = estrdup("/");
269: errjmp(dostat(file0, 0));
270: }
271: if(!okfid(rhdr.fid))
272: errjmp(Ebadfid);
273: if(strncmp(rhdr.aname, "device", 6) == 0){
274: if(connected && !devallowed)
275: errjmp(Especial0);
276: devallowed = 1;
277: }else{
278: if(connected && devallowed)
279: errjmp(Especial1);
280: }
281: getpwdf();
282: getgrpf();
283: rf = &rfile[rhdr.fid];
284: if(rf->busy)
285: errjmp(Efidactive);
286: rf->busy = 1;
287: rf->rclose = 0;
288: rf->file = file0;
289: file0->ref++;
290: p = name2pass(uid, rhdr.uname);
291: if(p == 0)
292: errjmp(Eunknown);
293: if(p->id == 0)
294: errjmp(Eperm);
295: # ifdef SOCKETS
296: if(ruserok(bsdhost, 0, rhdr.uname, rhdr.uname) < 0)
297: errjmp(Eperm);
298: # endif
299: rf->uid = p->id;
300: rf->gid = p->gid;
301: thdr.qid = file0->qid;
302: connected = 1;
303: }
304:
305: void
306: rclone(void)
307: {
308: Rfile *rf, *nrf;
309: File *f;
310:
311: rfilefid();
312: if(!okfid(rhdr.newfid))
313: errjmp(Ebadfid);
314: rf = &rfile[rhdr.fid];
315: nrf = &rfile[rhdr.newfid];
316: f = rf->file;
317: if(nrf->busy)
318: errjmp(Efidactive);
319: nrf->busy = 1;
320: nrf->file = f;
321: f->ref++;
322: nrf->fd = rf->fd;
323: nrf->uid = rf->uid;
324: nrf->gid = rf->gid;
325: nrf->rclose = rf->rclose;
326: if(nrf->fd){
327: if(nrf->fd->ref == 0)
328: error("clone fd count");
329: nrf->fd->ref++;
330: }
331: }
332:
333: void
334: rwalk(void)
335: {
336: char *err;
337: Rfile *rf;
338: File *of, *f;
339:
340: rf = rfilefid();
341: if(rf->fd)
342: errjmp(Eopen);
343: of = rf->file;
344: perm(rf, 1, 0);
345: f = newfile();
346: f->path = estrdup(of->path);
347: err = dostat(f, rhdr.name);
348: if(err){
349: f->ref = 0;
350: free(f->path);
351: errjmp(err);
352: }
353: if(of->ref <= 0)
354: error("walk ref count");
355: if(--of->ref == 0){
356: free(of->path);
357: free(of->name);
358: free(of);
359: }
360: rf->file = f;
361: thdr.qid = f->qid;
362: }
363:
364: void
365: ropen(void)
366: {
367: Rfile *rf;
368: File *f;
369: int fd;
370: DIR *dir;
371: int m, trunc;
372:
373: rf = rfilefid();
374: f = rf->file;
375: if(rf->fd)
376: error("open already open");
377: if(!devallowed && (f->stbuf.st_mode & S_IFCHR))
378: errjmp(Especial);
379: m = rhdr.mode & (16|3);
380: trunc = m & 16; /* OTRUNC */
381: switch(m){
382: case 0:
383: perm(rf, 4, 0);
384: break;
385: case 1:
386: case 1|16:
387: perm(rf, 2, 0);
388: break;
389: case 2:
390: case 0|16:
391: case 2|16:
392: perm(rf, 4, 0);
393: perm(rf, 2, 0);
394: break;
395: case 3:
396: perm(rf, 1, 0);
397: break;
398: default:
399: errjmp(Emode);
400: }
401:
402: m = omode(m & 3);
403: errno = 0;
404: if(f->qid.path & CHDIR){
405: if(rhdr.mode != 0) /* OREAD */
406: errjmp(Eperm);
407: dir = opendir(f->path);
408: if(dir == 0)
409: errjmp(sys_errlist[errno]);
410: fd = 0;
411: }else{
412: if(trunc){
413: fd = creat(f->path, 0666);
414: if(fd >= 0)
415: if(m != 1){
416: close(fd);
417: fd = open(f->path, m);
418: }
419: }else
420: fd = open(f->path, m);
421: if(fd < 0)
422: errjmp(sys_errlist[errno]);
423: dir = 0;
424: }
425: rf->rclose = rhdr.mode & 64; /* ORCLOSE */
426: rf->fd = erealloc(0, sizeof(Fd));
427: rf->fd->ref = 1;
428: rf->fd->fd = fd;
429: rf->fd->dir = dir;
430: rf->fd->offset = 0;
431: thdr.qid = f->qid;
432: }
433:
434: void
435: rcreate(void)
436: {
437: Rfile *rf;
438: File *f, *of;
439: char *path, *err;
440: int fd;
441: int m;
442: char name[NAMELEN];
443:
444: rf = rfilefid();
445: if(rf->fd)
446: errjmp(Eopen);
447: perm(rf, 2, 0);
448: path = bldpath(rf->file->path, rhdr.name, name);
449: m = omode(rhdr.mode&3);
450: errno = 0;
451: if(rhdr.perm & CHDIR){
452: if(m){
453: free(path);
454: errjmp(Eperm);
455: }
456: fd = mkdir(path, 0777);
457: if(fd < 0){
458: free(path);
459: errjmp(sys_errlist[errno]);
460: }
461: fd = open(path, 0);
462: free(path);
463: if(fd >= 0){
464: fchmod(fd, rhdr.perm&0777);
465: fchown(fd, rf->uid, rf->gid);
466: }
467: }else{
468: fd = creat(path, 0666);
469: if(fd >= 0){
470: if(m != 1){
471: close(fd);
472: fd = open(path, m);
473: }
474: fchmod(fd, rhdr.perm&0777);
475: fchown(fd, rf->uid, rf->gid);
476: }
477: free(path);
478: if(fd < 0)
479: errjmp(sys_errlist[errno]);
480: }
481: f = newfile();
482: of = rf->file;
483: f->path = estrdup(of->path);
484: err = dostat(f, rhdr.name);
485: if(err){
486: free(f->path);
487: free(f->name);
488: free(f);
489: errjmp(err);
490: }
491: if(!devallowed && (f->stbuf.st_mode & S_IFCHR)){
492: free(f->path);
493: free(f->name);
494: free(f);
495: errjmp(Especial);
496: }
497: if(--of->ref == 0){
498: free(of->path);
499: free(of->name);
500: free(of);
501: }
502: rf->file = f;
503: rf->rclose = rhdr.mode & 64; /* ORCLOSE */
504: rf->fd = erealloc(0, sizeof(Fd));
505: rf->fd->ref = 1;
506: rf->fd->fd = fd;
507: rf->fd->dir = 0;
508: rf->fd->offset = 0;
509: thdr.qid = f->qid;
510: }
511:
512: void
513: rread(void)
514: {
515: Rfile *rf;
516: File *f;
517: long n;
518: DTYPE *de;
519: Dir d;
520: struct stat stbuf;
521: char *path;
522:
523: rf = rfilefid();
524: if(rf->fd == 0)
525: errjmp(Enotopen);
526: if(rhdr.count > sizeof rdata)
527: errjmp(Etoolarge);
528: f = rf->file;
529: if(rf->fd->dir){
530: errno = 0;
531: rhdr.count = (rhdr.count/DIRLEN)*DIRLEN;
532: if(rf->fd->offset != rhdr.offset){
533: seekdir(rf->fd->dir, 0);
534: for(n=0; n<rhdr.offset; ){
535: de = readdir(rf->fd->dir);
536: if(de == 0)
537: break;
538: if(de->d_ino==0 || de->d_name[0]==0)
539: continue;
540: if(strcmp(de->d_name, ".")==0 || strcmp(de->d_name, "..")==0)
541: continue;
542: n += DIRLEN;
543: }
544: }
545: for(n=0; n<rhdr.count; ){
546: de = readdir(rf->fd->dir);
547: if(de == 0)
548: break;
549: if(de->d_ino==0 || de->d_name[0]==0)
550: continue;
551: if(strcmp(de->d_name, ".")==0 || strcmp(de->d_name, "..")==0)
552: continue;
553: strncpy(d.name, de->d_name, NAMELEN-1);
554: d.name[NAMELEN-1] = 0;
555: path = erealloc(0, strlen(f->path)+1+strlen(de->d_name)+1);
556: sprintf(path, "%s/%s", f->path, de->d_name);
557: memset(&stbuf, 0, sizeof stbuf);
558: if(stat(path, &stbuf) < 0){
559: fprintf(stderr, "dir: bad path %s\n", path);
560: /* but continue... probably a bad symlink */
561: }
562: free(path);
563: strncpy(d.uid, id2name(uid, stbuf.st_uid), NAMELEN);
564: strncpy(d.gid, id2name(gid, stbuf.st_gid), NAMELEN);
565: d.qid.path = qid(&stbuf);
566: d.qid.vers = vers(&stbuf);
567: d.mode = (d.qid.path&CHDIR)|(stbuf.st_mode&0777);
568: d.atime = stbuf.st_atime;
569: d.mtime = stbuf.st_mtime;
570: d.len.l.hlength = 0;
571: d.len.l.length = stbuf.st_size;
572: convD2M(&d, rdata+n);
573: n += DIRLEN;
574: }
575: }else{
576: errno = 0;
577: if(rf->fd->offset != rhdr.offset){
578: rf->fd->offset = rhdr.offset;
579: if(lseek(rf->fd->fd, rhdr.offset, 0) < 0)
580: errjmp(sys_errlist[errno]);
581: }
582: n = read(rf->fd->fd, rdata, rhdr.count);
583: if(n < 0)
584: errjmp(sys_errlist[errno]);
585: }
586: rf->fd->offset += n;
587: thdr.count = n;
588: thdr.data = rdata;
589: }
590:
591: void
592: rwrite(void)
593: {
594: Rfile *rf;
595: int n;
596:
597: rf = rfilefid();
598: if(rf->fd == 0)
599: errjmp(Enotopen);
600: if(rhdr.count > sizeof rdata)
601: errjmp(Etoolarge);
602: errno = 0;
603: if(rf->fd->offset != rhdr.offset){
604: rf->fd->offset = rhdr.offset;
605: if(lseek(rf->fd->fd, rhdr.offset, 0) < 0)
606: errjmp(sys_errlist[errno]);
607: }
608: n = write(rf->fd->fd, rhdr.data, rhdr.count);
609: if(n < 0)
610: errjmp(sys_errlist[errno]);
611: rf->fd->offset += n;
612: thdr.count = n;
613: }
614:
615: void
616: rstat(void)
617: {
618: Rfile *rf;
619: File *f;
620: Dir d;
621:
622: rf = rfilefid();
623: f = rf->file;
624: errjmp(dostat(f, 0));
625: strncpy(d.name, f->name, NAMELEN);
626: strncpy(d.uid, id2name(uid, f->stbuf.st_uid), NAMELEN);
627: strncpy(d.gid, id2name(gid, f->stbuf.st_gid), NAMELEN);
628: d.qid = f->qid;
629: d.mode = (f->qid.path&CHDIR)|(f->stbuf.st_mode&0777);
630: d.atime = f->stbuf.st_atime;
631: d.mtime = f->stbuf.st_mtime;
632: d.len.l.hlength = 0;
633: d.len.l.length = f->stbuf.st_size;
634: convD2M(&d, thdr.stat);
635: }
636:
637: void
638: rwstat(void)
639: {
640: Rfile *rf;
641: File *f;
642: Dir d;
643: Pass *p;
644: char *path, *dir, name[NAMELEN];
645:
646: rf = rfilefid();
647: f = rf->file;
648: errjmp(dostat(f, 0));
649: convM2D(rhdr.stat, &d);
650: errno = 0;
651: if(rf->uid != f->stbuf.st_uid)
652: errjmp(Eowner);
653: if(strcmp(d.name, f->name) != 0){
654: parentwrperm(rf);
655: dir = bldpath(f->path, "..", name);
656: path = erealloc(0, strlen(dir)+1+strlen(d.name)+1);
657: sprintf(path, "%s/%s", dir, d.name);
658: if(link(f->path, path) < 0){
659: free(path);
660: errjmp(sys_errlist[errno]);
661: }
662: if(unlink(f->path) < 0){
663: free(path);
664: errjmp(sys_errlist[errno]);
665: }
666: free(f->path);
667: free(f->name);
668: f->path = path;
669: f->name = estrdup(d.name);
670: }
671: if((d.mode&0777) != (f->stbuf.st_mode&0777)){
672: if(chmod(f->path, d.mode&0777) < 0)
673: errjmp(sys_errlist[errno]);
674: f->stbuf.st_mode &= ~0777;
675: f->stbuf.st_mode |= d.mode&0777;
676: }
677: p = name2pass(gid, d.gid);
678: if(p == 0)
679: errjmp(Eunknown);
680: if(p->id != f->stbuf.st_gid){
681: if(chown(f->path, f->stbuf.st_uid, p->id) < 0)
682: errjmp(sys_errlist[errno]);
683: f->stbuf.st_gid = p->id;
684: }
685: }
686:
687: void
688: rclunk(int rm)
689: {
690: int ret;
691: char *err;
692: Rfile *rf;
693: File *f;
694: Fd *fd;
695:
696: err = 0;
697: rf = rfilefid();
698: f = rf->file;
699: if(rm){
700: parentwrperm(rf);
701: if(f->qid.path & CHDIR)
702: ret = rmdir(f->path);
703: else
704: ret = unlink(f->path);
705: if(ret)
706: err = sys_errlist[errno];
707: }else if(rf->rclose){ /* ignore errors */
708: if(f->qid.path & CHDIR)
709: rmdir(f->path);
710: else
711: unlink(f->path);
712: }
713:
714: rf->busy = 0;
715: if(--f->ref == 0){
716: free(f->path);
717: free(f->name);
718: free(f);
719: }
720: fd = rf->fd;
721: if(fd){
722: if(fd->ref <= 0)
723: error("clunk fd count");
724: if(--fd->ref == 0){
725: if(fd->fd)
726: close(fd->fd);
727: if(fd->dir)
728: closedir(fd->dir);
729: free(fd);
730: }
731: rf->fd = 0;
732: }
733: if(err)
734: errjmp(err);
735: }
736:
737: char*
738: bldpath(char *a, char *elem, char *name)
739: {
740: char *path, *p;
741:
742: if(strcmp(elem, "..") == 0){
743: if(strcmp(a, "/") == 0){
744: path = estrdup(a);
745: strcpy(name, a);
746: }else{
747: p = strrchr(a, '/');
748: if(p == 0){
749: fprintf(stderr, "path: '%s'\n", path);
750: error("malformed path 1");
751: }
752: if(p == a) /* reduced to "/" */
753: p++;
754: path = erealloc(0, (p-a)+1);
755: memmove(path, a, (p-a));
756: path[(p-a)] = 0;
757: if(strcmp(path, "/") == 0)
758: p = path;
759: else{
760: p = strrchr(path, '/');
761: if(p == 0){
762: fprintf(stderr, "path: '%s'\n", path);
763: error("malformed path 2");
764: }
765: p++;
766: }
767: strcpy(name, p);
768: }
769: }else{
770: if(strcmp(a, "/") == 0)
771: a = "";
772: path = erealloc(0, strlen(a)+1+strlen(elem)+1);
773: sprintf(path, "%s/%s", a, elem);
774: strcpy(name, elem);
775: }
776: if(strlen(name) >= NAMELEN)
777: error("bldpath: name too long");
778: return path;
779: }
780:
781: char*
782: dostat(File *f, char *elem)
783: {
784: char *path;
785: struct stat stbuf;
786: char name[NAMELEN];
787:
788: if(elem)
789: path = bldpath(f->path, elem, name);
790: else
791: path = f->path;
792: errno = 0;
793: if(stat(path, &stbuf) < 0)
794: return sys_errlist[errno];
795: if(elem){
796: free(f->path);
797: f->path = path;
798: f->name = estrdup(name);
799: }
800: f->qid.path = qid(&stbuf);
801: f->qid.vers = vers(&stbuf);
802: f->stbuf = stbuf;
803: return 0;
804: }
805:
806: int
807: omode(int m)
808: {
809: switch(m){
810: case 0: /* OREAD */
811: case 3: /* OEXEC */
812: return 0;
813: case 1: /* OWRITE */
814: return 1;
815: case 2: /* ORDWR */
816: return 2;
817: }
818: errjmp(Emode);
819: return 0;
820: }
821:
822: void
823: sendmsg(char *err)
824: {
825: int n;
826:
827: if(err){
828: thdr.type = Rerror;
829: strncpy(thdr.ename, err, ERRLEN);
830: }
831: DBG(fprintf(stderr, "<< %s\n", mfmt(&thdr)));
832: n = convS2M(&thdr, tdata);
833: if(n == 0)
834: error("bad sendmsg format");
835: if(write(1, tdata, n) != n)
836: error("write error");
837: }
838:
839:
840: int
841: okfid(int fid)
842: {
843: enum{ Delta=10 };
844:
845: if(fid < 0){
846: fprintf(stderr, "u9fs: negative fid %d\n", fid);
847: return 0;
848: }
849: if(fid >= nrfilealloc){
850: fid += Delta;
851: rfile = erealloc(rfile, fid*sizeof(Rfile));
852: memset(rfile+nrfilealloc, 0, (fid-nrfilealloc)*sizeof(Rfile));
853: nrfilealloc = fid;
854: }
855: return 1;
856: }
857:
858: Rfile*
859: rfilefid(void)
860: {
861: Rfile *rf;
862:
863: if(!okfid(rhdr.fid))
864: errjmp(Ebadfid);
865: rf = &rfile[rhdr.fid];
866: if(rf->busy == 0)
867: errjmp(Ebadfid);
868: if(rf->file->ref <= 0)
869: error("ref count");
870: return rf;
871: }
872:
873: void
874: perm(Rfile *rf, int mask, struct stat *st)
875: {
876: if(st == 0)
877: st = &rf->file->stbuf;
878: /* plan 9 access semantics; simpler and more sensible */
879: if(rf->uid == st->st_uid)
880: if((st->st_mode>>6) & mask)
881: return;
882: if(rf->gid == st->st_gid)
883: if((st->st_mode>>3) & mask)
884: return;
885: if((st->st_mode>>0) & mask)
886: return;
887: errjmp(Eperm);
888: }
889:
890: void
891: parentwrperm(Rfile *rf)
892: {
893: Rfile trf;
894: struct stat st;
895: char *dirp, dir[512];
896:
897: dirp = bldpath(rf->file->path, "..", dir);
898: if(strlen(dirp) < sizeof dir){ /* ugly: avoid leaving dirp allocated */
899: strcpy(dir, dirp);
900: free(dirp);
901: dirp = dir;
902: }
903: if(stat(dirp, &st) < 0)
904: errjmp(Eperm);
905: trf.uid = rf->uid;
906: trf.gid = rf->gid;
907: perm(&trf, 2, &st);
908: }
909:
910: File*
911: newfile(void)
912: {
913: File *f;
914:
915: f = erealloc(0, sizeof(File));
916: memset(f, 0, sizeof(File));
917: f->ref = 1;
918: return f;
919: }
920:
921: /*
922: * qids: directory bit, seven bits of device, 24 bits of inode
923: */
924: Ulong
925: vers(struct stat *st)
926: {
927: return st->st_mtime;
928: }
929:
930: Ulong
931: qid(struct stat *st)
932: {
933: static int nqdev;
934: static Uchar *qdev;
935: Ulong q;
936: int dev;
937:
938: if(qdev == 0){
939: qdev = erealloc(0, 65536U);
940: memset(qdev, 0, 65536U);
941: }
942: q = 0;
943: if((st->st_mode&S_IFMT) == S_IFDIR)
944: q = CHDIR;
945: dev = st->st_dev & 0xFFFFUL;
946: if(qdev[dev] == 0){
947: if(++nqdev >= 128)
948: error("too many devices");
949: qdev[dev] = nqdev;
950: }
951: q |= qdev[dev]<<24;
952: q |= st->st_ino & 0x00FFFFFFUL;
953: return q;
954: }
955:
956: Pass*
957: name2pass(Pass **pw, char *name)
958: {
959: int i;
960: Pass *p;
961:
962: for(i=0; i<256; i++)
963: for(p = pw[i]; p; p = p->next)
964: if(strcmp(name, p->name) == 0)
965: return p;
966: return 0;
967: }
968:
969: char*
970: id2name(Pass **pw, int id)
971: {
972: int i;
973: Pass *p;
974: char *s;
975: static char buf[8];
976:
977: s = 0;
978: /* use last on list == first in file */
979: i = (id&0xFF) ^ ((id>>8)&0xFF);
980: for(p = pw[i]; p; p = p->next)
981: if(p->id == id)
982: s = p->name;
983: if(s)
984: return s;
985: sprintf(buf, "%d", id);
986: return buf;
987: }
988:
989: void
990: freepass(Pass **pass)
991: {
992: int i;
993: Pass *p, *np;
994:
995: for(i=0; i<256; i++){
996: for(p = pass[i]; p; p = np){
997: np = p->next;
998: free(p);
999: }
1000: pass[i] = 0;
1001: }
1002: }
1003:
1004: void
1005: getpwdf(void)
1006: {
1007: static mtime;
1008: struct stat stbuf;
1009: struct passwd *pw;
1010: int i;
1011: Pass *p;
1012:
1013: if(stat("/etc/passwd", &stbuf) < 0)
1014: error("can't read /etc/passwd");
1015: if(stbuf.st_mtime <= mtime)
1016: return;
1017: freepass(uid);
1018: while(pw = getpwent()){
1019: i = pw->pw_uid;
1020: i = (i&0xFF) ^ ((i>>8)&0xFF);
1021: p = erealloc(0, sizeof(Pass));
1022: p->next = uid[i];
1023: uid[i] = p;
1024: p->id = pw->pw_uid;
1025: p->gid = pw->pw_gid;
1026: p->name = estrdup(pw->pw_name);
1027: }
1028: setpwent();
1029: endpwent();
1030: }
1031:
1032: void
1033: getgrpf(void)
1034: {
1035: static mtime;
1036: struct stat stbuf;
1037: struct group *pw;
1038: int i;
1039: Pass *p;
1040:
1041: if(stat("/etc/group", &stbuf) < 0)
1042: error("can't read /etc/group");
1043: if(stbuf.st_mtime <= mtime)
1044: return;
1045: freepass(gid);
1046: while(pw = getgrent()){
1047: i = pw->gr_gid;
1048: i = (i&0xFF) ^ ((i>>8)&0xFF);
1049: p = erealloc(0, sizeof(Pass));
1050: p->next = gid[i];
1051: gid[i] = p;
1052: p->id = pw->gr_gid;
1053: p->gid = 0;
1054: p->name = estrdup(pw->gr_name);
1055: }
1056: setgrent();
1057: endgrent();
1058: }
1059:
1060: void
1061: error(char *s)
1062: {
1063: fprintf(stderr, "u9fs: %s\n", s);
1064: perror("unix error");
1065: exit(1);
1066: }
1067:
1068: void
1069: errjmp(char *s)
1070: {
1071: if(s == 0)
1072: return;
1073: sendmsg(s);
1074: longjmp(loopjmp, 1);
1075: }
1076:
1077: void*
1078: erealloc(void *p, unsigned n)
1079: {
1080: if(p == 0)
1081: p = malloc(n);
1082: else
1083: p = realloc(p, n);
1084: if(p == 0)
1085: error("realloc fail");
1086: return p;
1087: }
1088:
1089: char*
1090: estrdup(char *p)
1091: {
1092: p = strdup(p);
1093: if(p == 0)
1094: error("strdup fail");
1095: return p;
1096: }
1097:
1098: #ifdef SOCKETS
1099: void
1100: remotehostname(void)
1101: {
1102: struct sockaddr_in sock;
1103: struct hostent *hp;
1104: int len;
1105: int on = 1;
1106:
1107: len = sizeof sock;
1108: if(getpeername(0, &sock, &len) < 0)
1109: error("getpeername");
1110: hp = gethostbyaddr((char *)&sock.sin_addr, sizeof (struct in_addr),
1111: sock.sin_family);
1112: if(hp == 0)
1113: error("gethostbyaddr");
1114: strcpy(bsdhost, hp->h_name);
1115: fprintf(stderr, "bsdhost %s on %d\n", bsdhost, getpid());
1116:
1117: setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on));
1118: }
1119: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.