|
|
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: if(rf->fd->offset != rhdr.offset){
532: seekdir(rf->fd->dir, 0);
533: for(n=0; n<rhdr.offset; ){
534: de = readdir(rf->fd->dir);
535: if(de == 0)
536: break;
537: if(de->d_ino==0 || de->d_name[0]==0)
538: continue;
539: if(strcmp(de->d_name, ".")==0 || strcmp(de->d_name, "..")==0)
540: continue;
541: n += DIRLEN;
542: }
543: }
544: for(n=0; n<rhdr.count; ){
545: de = readdir(rf->fd->dir);
546: if(de == 0)
547: break;
548: if(de->d_ino==0 || de->d_name[0]==0)
549: continue;
550: if(strcmp(de->d_name, ".")==0 || strcmp(de->d_name, "..")==0)
551: continue;
552: strncpy(d.name, de->d_name, NAMELEN-1);
553: d.name[NAMELEN-1] = 0;
554: path = erealloc(0, strlen(f->path)+1+strlen(de->d_name)+1);
555: sprintf(path, "%s/%s", f->path, de->d_name);
556: memset(&stbuf, 0, sizeof stbuf);
557: if(stat(path, &stbuf) < 0){
558: fprintf(stderr, "dir: bad path %s\n", path);
559: /* but continue... probably a bad symlink */
560: }
561: free(path);
562: strncpy(d.uid, id2name(uid, stbuf.st_uid), NAMELEN);
563: strncpy(d.gid, id2name(gid, stbuf.st_gid), NAMELEN);
564: d.qid.path = qid(&stbuf);
565: d.qid.vers = vers(&stbuf);
566: d.mode = (d.qid.path&CHDIR)|(stbuf.st_mode&0777);
567: d.atime = stbuf.st_atime;
568: d.mtime = stbuf.st_mtime;
569: d.len.l.hlength = 0;
570: d.len.l.length = stbuf.st_size;
571: convD2M(&d, rdata+n);
572: n += DIRLEN;
573: }
574: }else{
575: errno = 0;
576: if(rf->fd->offset != rhdr.offset){
577: rf->fd->offset = rhdr.offset;
578: if(lseek(rf->fd->fd, rhdr.offset, 0) < 0)
579: errjmp(sys_errlist[errno]);
580: }
581: n = read(rf->fd->fd, rdata, rhdr.count);
582: if(n < 0)
583: errjmp(sys_errlist[errno]);
584: }
585: rf->fd->offset += n;
586: thdr.count = n;
587: thdr.data = rdata;
588: }
589:
590: void
591: rwrite(void)
592: {
593: Rfile *rf;
594: int n;
595:
596: rf = rfilefid();
597: if(rf->fd == 0)
598: errjmp(Enotopen);
599: if(rhdr.count > sizeof rdata)
600: errjmp(Etoolarge);
601: errno = 0;
602: if(rf->fd->offset != rhdr.offset){
603: rf->fd->offset = rhdr.offset;
604: if(lseek(rf->fd->fd, rhdr.offset, 0) < 0)
605: errjmp(sys_errlist[errno]);
606: }
607: n = write(rf->fd->fd, rhdr.data, rhdr.count);
608: if(n < 0)
609: errjmp(sys_errlist[errno]);
610: rf->fd->offset += n;
611: thdr.count = n;
612: }
613:
614: void
615: rstat(void)
616: {
617: Rfile *rf;
618: File *f;
619: Dir d;
620:
621: rf = rfilefid();
622: f = rf->file;
623: errjmp(dostat(f, 0));
624: strncpy(d.name, f->name, NAMELEN);
625: strncpy(d.uid, id2name(uid, f->stbuf.st_uid), NAMELEN);
626: strncpy(d.gid, id2name(gid, f->stbuf.st_gid), NAMELEN);
627: d.qid = f->qid;
628: d.mode = (f->qid.path&CHDIR)|(f->stbuf.st_mode&0777);
629: d.atime = f->stbuf.st_atime;
630: d.mtime = f->stbuf.st_mtime;
631: d.len.l.hlength = 0;
632: d.len.l.length = f->stbuf.st_size;
633: convD2M(&d, thdr.stat);
634: }
635:
636: void
637: rwstat(void)
638: {
639: Rfile *rf;
640: File *f;
641: Dir d;
642: Pass *p;
643: char *path, *dir, name[NAMELEN];
644:
645: rf = rfilefid();
646: f = rf->file;
647: errjmp(dostat(f, 0));
648: convM2D(rhdr.stat, &d);
649: errno = 0;
650: if(rf->uid != f->stbuf.st_uid)
651: errjmp(Eowner);
652: if(strcmp(d.name, f->name) != 0){
653: parentwrperm(rf);
654: dir = bldpath(f->path, "..", name);
655: path = erealloc(0, strlen(dir)+1+strlen(d.name)+1);
656: sprintf(path, "%s/%s", dir, d.name);
657: if(link(f->path, path) < 0){
658: free(path);
659: errjmp(sys_errlist[errno]);
660: }
661: if(unlink(f->path) < 0){
662: free(path);
663: errjmp(sys_errlist[errno]);
664: }
665: free(f->path);
666: free(f->name);
667: f->path = path;
668: f->name = estrdup(d.name);
669: }
670: if((d.mode&0777) != (f->stbuf.st_mode&0777)){
671: if(chmod(f->path, d.mode&0777) < 0)
672: errjmp(sys_errlist[errno]);
673: f->stbuf.st_mode &= ~0777;
674: f->stbuf.st_mode |= d.mode&0777;
675: }
676: p = name2pass(gid, d.gid);
677: if(p == 0)
678: errjmp(Eunknown);
679: if(p->id != f->stbuf.st_gid){
680: if(chown(f->path, f->stbuf.st_uid, p->id) < 0)
681: errjmp(sys_errlist[errno]);
682: f->stbuf.st_gid = p->id;
683: }
684: }
685:
686: void
687: rclunk(int rm)
688: {
689: int ret;
690: char *err;
691: Rfile *rf;
692: File *f;
693: Fd *fd;
694:
695: err = 0;
696: rf = rfilefid();
697: f = rf->file;
698: if(rm){
699: parentwrperm(rf);
700: if(f->qid.path & CHDIR)
701: ret = rmdir(f->path);
702: else
703: ret = unlink(f->path);
704: if(ret)
705: err = sys_errlist[errno];
706: }else if(rf->rclose){ /* ignore errors */
707: if(f->qid.path & CHDIR)
708: rmdir(f->path);
709: else
710: unlink(f->path);
711: }
712:
713: rf->busy = 0;
714: if(--f->ref == 0){
715: free(f->path);
716: free(f->name);
717: free(f);
718: }
719: fd = rf->fd;
720: if(fd){
721: if(fd->ref <= 0)
722: error("clunk fd count");
723: if(--fd->ref == 0){
724: if(fd->fd)
725: close(fd->fd);
726: if(fd->dir)
727: closedir(fd->dir);
728: free(fd);
729: }
730: rf->fd = 0;
731: }
732: if(err)
733: errjmp(err);
734: }
735:
736: char*
737: bldpath(char *a, char *elem, char *name)
738: {
739: char *path, *p;
740:
741: if(strcmp(elem, "..") == 0){
742: if(strcmp(a, "/") == 0){
743: path = estrdup(a);
744: strcpy(name, a);
745: }else{
746: p = strrchr(a, '/');
747: if(p == 0){
748: fprintf(stderr, "path: '%s'\n", path);
749: error("malformed path 1");
750: }
751: if(p == a) /* reduced to "/" */
752: p++;
753: path = erealloc(0, (p-a)+1);
754: memmove(path, a, (p-a));
755: path[(p-a)] = 0;
756: if(strcmp(path, "/") == 0)
757: p = path;
758: else{
759: p = strrchr(path, '/');
760: if(p == 0){
761: fprintf(stderr, "path: '%s'\n", path);
762: error("malformed path 2");
763: }
764: p++;
765: }
766: strcpy(name, p);
767: }
768: }else{
769: if(strcmp(a, "/") == 0)
770: a = "";
771: path = erealloc(0, strlen(a)+1+strlen(elem)+1);
772: sprintf(path, "%s/%s", a, elem);
773: strcpy(name, elem);
774: }
775: if(strlen(name) >= NAMELEN)
776: error("bldpath: name too long");
777: return path;
778: }
779:
780: char*
781: dostat(File *f, char *elem)
782: {
783: char *path;
784: struct stat stbuf;
785: char name[NAMELEN];
786:
787: if(elem)
788: path = bldpath(f->path, elem, name);
789: else
790: path = f->path;
791: errno = 0;
792: if(stat(path, &stbuf) < 0)
793: return sys_errlist[errno];
794: if(elem){
795: free(f->path);
796: f->path = path;
797: f->name = estrdup(name);
798: }
799: f->qid.path = qid(&stbuf);
800: f->qid.vers = vers(&stbuf);
801: f->stbuf = stbuf;
802: return 0;
803: }
804:
805: int
806: omode(int m)
807: {
808: switch(m){
809: case 0: /* OREAD */
810: case 3: /* OEXEC */
811: return 0;
812: case 1: /* OWRITE */
813: return 1;
814: case 2: /* ORDWR */
815: return 2;
816: }
817: errjmp(Emode);
818: return 0;
819: }
820:
821: void
822: sendmsg(char *err)
823: {
824: int n;
825:
826: if(err){
827: thdr.type = Rerror;
828: strncpy(thdr.ename, err, ERRLEN);
829: }
830: DBG(fprintf(stderr, "<< %s\n", mfmt(&thdr)));
831: n = convS2M(&thdr, tdata);
832: if(n == 0)
833: error("bad sendmsg format");
834: if(write(1, tdata, n) != n)
835: error("write error");
836: }
837:
838:
839: int
840: okfid(int fid)
841: {
842: enum{ Delta=10 };
843:
844: if(fid < 0){
845: fprintf(stderr, "u9fs: negative fid %d\n", fid);
846: return 0;
847: }
848: if(fid >= nrfilealloc){
849: fid += Delta;
850: rfile = erealloc(rfile, fid*sizeof(Rfile));
851: memset(rfile+nrfilealloc, 0, (fid-nrfilealloc)*sizeof(Rfile));
852: nrfilealloc = fid;
853: }
854: return 1;
855: }
856:
857: Rfile*
858: rfilefid(void)
859: {
860: Rfile *rf;
861:
862: if(!okfid(rhdr.fid))
863: errjmp(Ebadfid);
864: rf = &rfile[rhdr.fid];
865: if(rf->busy == 0)
866: errjmp(Ebadfid);
867: if(rf->file->ref <= 0)
868: error("ref count");
869: return rf;
870: }
871:
872: void
873: perm(Rfile *rf, int mask, struct stat *st)
874: {
875: if(st == 0)
876: st = &rf->file->stbuf;
877: /* plan 9 access semantics; simpler and more sensible */
878: if(rf->uid == st->st_uid)
879: if((st->st_mode>>6) & mask)
880: return;
881: if(rf->gid == st->st_gid)
882: if((st->st_mode>>3) & mask)
883: return;
884: if((st->st_mode>>0) & mask)
885: return;
886: errjmp(Eperm);
887: }
888:
889: void
890: parentwrperm(Rfile *rf)
891: {
892: Rfile trf;
893: struct stat st;
894: char *dirp, dir[512];
895:
896: dirp = bldpath(rf->file->path, "..", dir);
897: if(strlen(dirp) < sizeof dir){ /* ugly: avoid leaving dirp allocated */
898: strcpy(dir, dirp);
899: free(dirp);
900: dirp = dir;
901: }
902: if(stat(dirp, &st) < 0)
903: errjmp(Eperm);
904: trf.uid = rf->uid;
905: trf.gid = rf->gid;
906: perm(&trf, 2, &st);
907: }
908:
909: File*
910: newfile(void)
911: {
912: File *f;
913:
914: f = erealloc(0, sizeof(File));
915: memset(f, 0, sizeof(File));
916: f->ref = 1;
917: return f;
918: }
919:
920: /*
921: * qids: directory bit, seven bits of device, 24 bits of inode
922: */
923: Ulong
924: vers(struct stat *st)
925: {
926: return st->st_mtime;
927: }
928:
929: Ulong
930: qid(struct stat *st)
931: {
932: static int nqdev;
933: static Uchar *qdev;
934: Ulong q;
935: int dev;
936:
937: if(qdev == 0){
938: qdev = erealloc(0, 65536U);
939: memset(qdev, 0, 65536U);
940: }
941: q = 0;
942: if((st->st_mode&S_IFMT) == S_IFDIR)
943: q = CHDIR;
944: dev = st->st_dev & 0xFFFFUL;
945: if(qdev[dev] == 0){
946: if(++nqdev >= 128)
947: error("too many devices");
948: qdev[dev] = nqdev;
949: }
950: q |= qdev[dev]<<24;
951: q |= st->st_ino & 0x00FFFFFFUL;
952: return q;
953: }
954:
955: Pass*
956: name2pass(Pass **pw, char *name)
957: {
958: int i;
959: Pass *p;
960:
961: for(i=0; i<256; i++)
962: for(p = pw[i]; p; p = p->next)
963: if(strcmp(name, p->name) == 0)
964: return p;
965: return 0;
966: }
967:
968: char*
969: id2name(Pass **pw, int id)
970: {
971: int i;
972: Pass *p;
973: char *s;
974: static char buf[8];
975:
976: s = 0;
977: /* use last on list == first in file */
978: i = (id&0xFF) ^ ((id>>8)&0xFF);
979: for(p = pw[i]; p; p = p->next)
980: if(p->id == id)
981: s = p->name;
982: if(s)
983: return s;
984: sprintf(buf, "%d", id);
985: return buf;
986: }
987:
988: void
989: freepass(Pass **pass)
990: {
991: int i;
992: Pass *p, *np;
993:
994: for(i=0; i<256; i++){
995: for(p = pass[i]; p; p = np){
996: np = p->next;
997: free(p);
998: }
999: pass[i] = 0;
1000: }
1001: }
1002:
1003: void
1004: getpwdf(void)
1005: {
1006: static mtime;
1007: struct stat stbuf;
1008: struct passwd *pw;
1009: int i;
1010: Pass *p;
1011:
1012: if(stat("/etc/passwd", &stbuf) < 0)
1013: error("can't read /etc/passwd");
1014: if(stbuf.st_mtime <= mtime)
1015: return;
1016: freepass(uid);
1017: while(pw = getpwent()){
1018: i = pw->pw_uid;
1019: i = (i&0xFF) ^ ((i>>8)&0xFF);
1020: p = erealloc(0, sizeof(Pass));
1021: p->next = uid[i];
1022: uid[i] = p;
1023: p->id = pw->pw_uid;
1024: p->gid = pw->pw_gid;
1025: p->name = estrdup(pw->pw_name);
1026: }
1027: setpwent();
1028: endpwent();
1029: }
1030:
1031: void
1032: getgrpf(void)
1033: {
1034: static mtime;
1035: struct stat stbuf;
1036: struct group *pw;
1037: int i;
1038: Pass *p;
1039:
1040: if(stat("/etc/group", &stbuf) < 0)
1041: error("can't read /etc/group");
1042: if(stbuf.st_mtime <= mtime)
1043: return;
1044: freepass(gid);
1045: while(pw = getgrent()){
1046: i = pw->gr_gid;
1047: i = (i&0xFF) ^ ((i>>8)&0xFF);
1048: p = erealloc(0, sizeof(Pass));
1049: p->next = gid[i];
1050: gid[i] = p;
1051: p->id = pw->gr_gid;
1052: p->gid = 0;
1053: p->name = estrdup(pw->gr_name);
1054: }
1055: setgrent();
1056: endgrent();
1057: }
1058:
1059: void
1060: error(char *s)
1061: {
1062: fprintf(stderr, "u9fs: %s\n", s);
1063: perror("unix error");
1064: exit(1);
1065: }
1066:
1067: void
1068: errjmp(char *s)
1069: {
1070: if(s == 0)
1071: return;
1072: sendmsg(s);
1073: longjmp(loopjmp, 1);
1074: }
1075:
1076: void*
1077: erealloc(void *p, unsigned n)
1078: {
1079: if(p == 0)
1080: p = malloc(n);
1081: else
1082: p = realloc(p, n);
1083: if(p == 0)
1084: error("realloc fail");
1085: return p;
1086: }
1087:
1088: char*
1089: estrdup(char *p)
1090: {
1091: p = strdup(p);
1092: if(p == 0)
1093: error("strdup fail");
1094: return p;
1095: }
1096:
1097: #ifdef SOCKETS
1098: void
1099: remotehostname(void)
1100: {
1101: struct sockaddr_in sock;
1102: struct hostent *hp;
1103: int len;
1104: int on = 1;
1105:
1106: len = sizeof sock;
1107: if(getpeername(0, &sock, &len) < 0)
1108: error("getpeername");
1109: hp = gethostbyaddr((char *)&sock.sin_addr, sizeof (struct in_addr),
1110: sock.sin_family);
1111: if(hp == 0)
1112: error("gethostbyaddr");
1113: strcpy(bsdhost, hp->h_name);
1114: fprintf(stderr, "bsdhost %s on %d\n", bsdhost, getpid());
1115:
1116: setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on));
1117: }
1118: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.