|
|
1.1 root 1: #include "fserv.h"
2: #include "errno.h"
3: #include "sys/neta.h"
4: extern char *buf, *nbuf;
5: extern int dtime, myfd, wrcnt, rdcnt, lflag;
6: extern struct rcva y, nilrcv;
7:
8: doput(x)
9: struct senda *x;
10: {
11: y.trannum = x->trannum;
12: if(x->tag == 0) {
13: debug("\tput got 0");
14: respond(EIO);
15: dumpstate();
16: leave(9);
17: }
18: clrnetf(x->tag);
19: respond(errno);
20: }
21:
22: doget(x)
23: struct senda *x;
24: { netf *p;
25: y.trannum = x->trannum;
26: p = getnetf(x->dev, x->ino);
27: if(p == 0) {
28: debug("\tget didn't %d %d", x->dev, x->ino);
29: respond(errno);
30: dumpstate();
31: return;
32: }
33: if(p->fd == -1 && xstat(p->name, &p->statb) < 0
34: || p->fd != -1 && fstat(p->fd, &p->statb) < 0) {
35: respond(errno);
36: return;
37: }
38: debug2("\tget %d %d 0%o %d %d %s\n", p->dev, p->ino,
39: p->statb.st_mode, p->statb.st_uid, p->statb.st_gid, p->name);
40: y.mode = p->statb.st_mode;
41: y.tag = p->tag;
42: y.nlink = p->statb.st_nlink;
43: y.uid = hostuid(&p->statb);
44: y.gid = hostgid(&p->statb);
45: y.size = p->statb.st_size;
46: respond(0);
47: }
48:
49: dofree(x) /* means rmt thinks nlink == 0 */
50: struct senda *x;
51: {
52: y.trannum = x->trannum;
53: respond(0);
54: }
55:
56: doupdat(x)
57: struct senda *x;
58: { netf *p;
59: int i;
60: y.trannum = x->trannum;
61: p = gettag(x->tag);
62: if(p == 0) {
63: respond(errno);
64: return;
65: }
66: debug2("\tupdat 0%o %d %d\n", p->statb.st_mode, p->statb.st_uid, p->statb.st_gid);
67: debug2("\t\t0%o %d %d\n", x->mode, x->uid, x->gid);
68: x->ta += dtime;
69: x->tm += dtime;
70: if(p->name == 0) { /* of course this can't happen */
71: debug("\tname 0 tag %d\n", p->tag);
72: respond(EIO);
73: dumpstate();
74: return;
75: }
76: debug2("\t%s\n", p->name);
77: if(x->ta == dtime)
78: x->ta = p->statb.st_atime;
79: if(x->tm == dtime)
80: x->tm = p->statb.st_mtime;
81: utime(p->name, &x->ta);
82: errno = 0; /* p->name may be wrong, so times off [bug] */
83: if(x->mode != p->statb.st_mode) {
84: i = 1;
85: if(isowner(x, &p->statb))
86: fchmod(p->fd, x->mode);
87: else
88: errno = EPERM;
89: perror("\tfchmod");
90: }
91: if(x->uid == 0 && (hostuid(&p->statb) != x->newuid
92: || hostgid(&p->statb) != x->newgid)) {
93: i = 1;
94: if(isowner(x, &p->statb))
95: fchown(p->fd, myuid(x->newuid, x->newgid),
96: mygid(x->newuid, x->newgid));
97: else
98: errno = EPERM;
99: if(errno)
100: perror("\tfchown");
101: debug1("\tupdat %d %d\n", p->statb.st_uid, p->statb.st_gid);
102: }
103: if(i)
104: fstat(p->fd, &p->statb);
105: y.mode = p->statb.st_mode;
106: y.nlink = p->statb.st_nlink;
107: y.uid = hostuid(&p->statb);
108: y.gid = hostgid(&p->statb);
109: y.size = p->statb.st_size;
110: if(hisdev(p->statb.st_dev) != p->dev || p->ino != p->statb.st_ino) {
111: debug("\tdev oops\n");
112: dumpstate();
113: }
114: respond(errno);
115: }
116:
117: doread(x)
118: struct senda *x;
119: { netf *p;
120: int n, offset = 0;
121: y.trannum = x->trannum;
122: p = gettag(x->tag);
123: if(p == 0) {
124: if(errno == 0)
125: errno = EIO;
126: respond(errno);
127: return;
128: }
129: if(ftype(p) == S_IFLNK) {
130: n = readlink(p->name, buf, x->count);
131: offset = x->offset;
132: debug2("readlink %s %d %d\n", p->name, n, x->count);
133: offset = x->offset;
134: if(n < offset)
135: offset = n;
136: }
137: else {
138: if(opennf(p, 0)) {
139: respond(errno);
140: return;
141: }
142: if(lseek(p->fd, x->offset, 0) < 0)
143: perror("\tread lseek");
144: getbuf(x->count);
145: n = read(p->fd, buf, x->count);
146: }
147: debug1("\tread got %d wanted %d\n", n, x->count);
148: if(n < 0) {
149: y.errno = errno;
150: y.count = n;
151: respond(0);
152: return;
153: }
154: y.count = n - offset;
155: respond(0);
156: (void) write(myfd, buf + offset, (unsigned) n - offset);
157: wrcnt += n;
158: }
159:
160: dowrite(x)
161: struct senda *x;
162: { netf *p;
163: int n;
164: y.trannum = x->trannum;
165: if(x->count == 0)
166: respond(0);
167: getbuf(x->count);
168: if((n = read(myfd, buf, x->count)) != x->count) {
169: debug("\twrite expected %d got %d\n", x->count, n);
170: rdcnt += n;
171: if(errno == 0)
172: errno = EIO;
173: respond(errno);
174: dumpstate();
175: return;
176: }
177: wrcnt += n;
178: debug1("\twrite %d\n", x->count);
179: p = gettag(x->tag);
180: if(p == 0) {
181: respond(errno);
182: return;
183: }
184: if(opennf(p, 1)) {
185: respond(errno);
186: return;
187: }
188: n = lseek(p->fd, x->offset, 0);
189: if(n < 0) {
190: debug("\twrite lseek %d\n", errno);
191: dumpstate();
192: }
193: if((n = write(p->fd, buf, x->count)) != x->count) {
194: debug("\twrite failed %d %d\n", n, p->fd);
195: if(errno == 0)
196: errno = EIO;
197: dumpstate();
198: }
199: respond(errno);
200: }
201:
202: dotrunc(x)
203: struct senda *x;
204: {
205: y.trannum = x->trannum;
206: truncnf(x->tag);
207: respond(errno);
208: }
209:
210: dostat(x)
211: struct senda *x;
212: { netf *p;
213: y.trannum = x->trannum;
214: debug2("\tstat %d\n", x->tag);
215: p = gettag(x->tag);
216: if(p == 0) {
217: respond(errno);
218: return;
219: }
220: debug2("\tlstat %s ", p->name);
221: if(p->fd == -1 && xstat(p->name, &p->statb) < 0
222: || p->fd != -1 && fstat(p->fd, &p->statb) < 0) {
223: respond(errno);
224: return;
225: }
226: debug2("0%o %d %d\n", p->statb.st_mode, p->statb.st_uid, p->statb.st_gid);
227: y.mode = p->statb.st_mode;
228: y.nlink = p->statb.st_nlink;
229: y.uid = hostuid(&p->statb);
230: y.gid = hostgid(&p->statb);
231: debug2("\thostuid(%d) = %d\n", p->statb.st_uid, y.uid);
232: debug2("\tgid %d\n", y.gid);
233: y.size = p->statb.st_size;
234: y.tm[0] = p->statb.st_atime;
235: y.tm[1] = p->statb.st_mtime;
236: y.tm[2] = p->statb.st_ctime;
237: if(hisdev(p->statb.st_dev) != p->dev || p->ino != p->statb.st_ino) {
238: debug("\toops dev or ino\n");
239: dumpstate();
240: }
241: respond(0);
242: }
243:
244: donami(x)
245: struct senda *x;
246: { netf *p, *q;
247: int fd, i, nlink = 0;
248: y.trannum = x->trannum;
249: getbuf(x->count);
250: if((i = read(myfd, buf, x->count)) != x->count) {
251: rdcnt += i;
252: if(errno == 0)
253: errno = EIO;
254: respond(errno);
255: return;
256: }
257: rdcnt += i;
258: p = gettag(x->tag);
259: if(p == 0) {
260: respond(errno);
261: return;
262: }
263: debug1("\tcdir %s 0%o %d %d\n", p->name, p->statb.st_mode,
264: p->statb.st_uid, p->statb.st_gid);
265: if(ftype(p) != S_IFDIR) {
266: respond(ENOTDIR);
267: return;
268: }
269: if(noaccess(x, &p->statb, S_IEXEC)) {
270: respond(EACCES);
271: return;
272: }
273: fixnbuf(p->name, x->count, buf, x->flags);
274: debug2("\tnami %s (%d)\n", nbuf, x->flags);
275: again:
276: q = 0;
277: if(x->flags == NDEL)
278: q = oldnetf(nbuf);
279: if(q == 0)
280: q = newnetf(nbuf, -1, 0);
281: if(q != 0) {
282: debug2("\tfound\n");
283: errno = 0;
284: if(lflag && ftype(q) == S_IFLNK)
285: if(lcllink(q)) {
286: if(nlink++ > 4) {
287: errno = ELOOP;
288: goto bad;
289: }
290: goto again;
291: }
292: y.ino = q->ino;
293: y.tag = q->tag;
294: y.dev = q->dev;
295: y.mode = q->statb.st_mode;
296: y.nlink = q->statb.st_nlink;
297: y.uid = hostuid(&q->statb);
298: y.gid = hostgid(&q->statb);
299: y.size = q->statb.st_size;
300: if(isroot(q) && strncmp(buf, ".", x->count)) {
301: debug2("NROOT %s\n", buf);
302: y.flags = NROOT;
303: }
304: if(x->flags == NDEL) {
305: if(noaccess(x, &p->statb, S_IWRITE)) {
306: debug1("\tnodelete\n");
307: respond(EPERM);
308: return;
309: }
310: if(y.dev != x->dev)
311: errno = EBUSY;
312: if(y.flags == NROOT)
313: errno = EPERM;
314: (void) unlink(nbuf);
315: debug1("\tunlink %s %d\n", nbuf, errno);
316: }
317: if(x->flags == NCREAT && noaccess(x, &q->statb, S_IWRITE)) {
318: debug1("\tnocreat\n");
319: respond(EPERM);
320: return;
321: }
322: respond(errno);
323: return;
324: }
325: else {
326: y.flags = NOMATCH;
327: if(x->flags == NLINK) {
328: if(noaccess(x, &p->statb, S_IWRITE)) {
329: debug1("\tnolink %d %d %d\n", x->uid,
330: p->statb.st_uid, p->statb.st_gid);
331: respond(EPERM);
332: return;
333: }
334: q = gettag(x->tag);
335: p = getnetf(x->dev, x->ino);
336: if(q == 0 || p == 0) {
337: debug1("\tno link p 0x%x q 0x%x", p, q);
338: respond(EXDEV);
339: return;
340: }
341: debug1("\tlink %d %d %d %s %s",
342: x->dev, x->ino, q->dev, p->name, nbuf);
343: if(q->dev != p->dev)
344: errno = EXDEV;
345: i = link(p->name, nbuf);
346: if(i != -1)
347: errno = 0;
348: else
349: debug("\tlink %d", errno);
350: }
351: else if(x->flags == NCREAT) {
352: debug1("\tnami creat 0%o %s\n", x->mode, nbuf);
353: if(noaccess(x, &p->statb, S_IWRITE)) {
354: debug1("\tnoaccess\n");
355: respond(EACCES);
356: return;
357: }
358: switch(x->mode & S_IFMT) {
359: case 0:
360: case S_IFREG:
361: fd = creat(nbuf, x->mode);
362: if(fd != -1) {
363: q = newnetf(nbuf, fd, 1);
364: y.ino = q->ino;
365: y.dev = q->dev;
366: errno = 0;
367: chown(nbuf, myuid(x->uid, x->gid),
368: mygid(x->uid, x->gid));
369: debug1("\tchown %d %d\n",
370: myuid(x->uid, x->gid),
371: mygid(x->uid, x->gid));
372: (void) fstat(fd, &q->statb);
373: }
374: break;
375: case S_IFDIR:
376: if(x->uid != 0) {
377: debug1("\tsuser %d\n", x->uid);
378: respond(EPERM);
379: return;
380: }
381: i = mknod(nbuf, x->mode, 0);
382: if(i != -1) {
383: q = newnetf(nbuf, -1, 0);
384: y.ino = q->ino;
385: y.dev = q->dev;
386: errno = 0;
387: chown(nbuf, myuid(x->uid, x->gid),
388: mygid(x->uid, x->gid));
389: (void) fstat(q->fd, &q->statb);
390: debug1("\tmknod 0%o %d %d\n",
391: q->statb.st_mode, q->statb.st_uid, q->statb.st_gid);
392: }
393: else
394: debug1("\tmknod\n");
395: break;
396: case S_IFLNK:
397: errno = 0;
398: fd = creat(nbuf, 0777);
399: if(fd < 0)
400: break;
401: chown(nbuf, myuid(x->uid, x->gid),
402: mygid(x->uid, x->gid));
403: i = fchmod(fd, x->mode | S_IFLNK);
404: debug1("\tfchmod(%s) %d errno %d\n", nbuf, i, errno);
405: if(errno == 0) {
406: debug2("\tfd = %d\n", fd);
407: q = newnetf(nbuf, fd, 1);
408: y.ino = q->ino;
409: y.dev = q->dev;
410: }
411: break;
412: default:
413: errno = EPERM;
414: break;
415: }
416: }
417: }
418: bad:
419: y.tag = q->tag;
420: y.nlink = q->statb.st_nlink;
421: y.size = q->statb.st_size;
422: y.uid = hostuid(&q->statb);
423: y.gid = hostuid(&q->statb);
424: respond(errno);
425: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.