|
|
1.1 root 1: /* when the client reads directories, some work may be required */
2: #include "share.h"
3:
4: file tfile;
5: int roottag;
6: unsigned char *slash;
7:
8: openit()
9: { int n;
10: if(!openfile()) {
11: if(client.namiflags != NBROOT)
12: client.errno = ENOENT;
13: return;
14: }
15: n = gimmefile();
16: if(n < 0)
17: return;
18: files[n].fd = tfile.fd;
19: files[n].flags = tfile.flags;
20: if(stat(nmbuf, &files[n].stb) < 0) {
21: client.errno = errno; /* must have been set? */
22: close(tfile.fd);
23: return; /* files[n].tag is 0 still */
24: }
25: checkdev(files[n].stb.st_dev);
26: files[n].tag = maketag(&files[n].stb);
27: if(setname(n))
28: return;
29: checkdupl(n);
30: retnami(n);
31: }
32:
33: creatit()
34: { int n, fd;
35: if((n = openfile()) && client.flags == NI_NXCREAT) {
36: client.errno = EEXIST;
37: close(tfile.fd);
38: return;
39: }
40: if(n) { /* exists, creat it */
41: if(writeperm())
42: return;
43: n = creat(nmbuf, (int)client.mode);
44: if(n >= 0)
45: close(n);
46: else {
47: client.errno = errno;
48: return;
49: }
50: n = gimmefile();
51: if(n < 0)
52: return;
53: files[n].fd = tfile.fd;
54: files[n].flags = tfile.flags;
55: if(stat(nmbuf, &files[n].stb) < 0) {
56: client.errno = errno;
57: close(tfile.fd);
58: return;
59: }
60: checkdev(files[n].stb.st_dev);
61: files[n].tag = maketag(&files[n].stb);
62: if(setname(n))
63: return;
64: checkdupl(n); /* here it is important too to get the new one */
65: retnami(n);
66: return;
67: }
68: /* doesn't exist, creat it */
69: if(client.namiflags == NBROOT)
70: return; /* can't creat the root (is errno set?) */
71: n = gimmefile();
72: if(n < 0)
73: return;
74: if(dirwriteperm())
75: return;
76: if((client.mode & S_IFMT)) { /* no symbolic links or mknods */
77: error("client: client.mode 0%o\n", client.mode);
78: client.errno = EXDEV;
79: return;
80: }
81: if((fd = creat(nmbuf, client.mode)) < 0) {
82: client.errno = errno;
83: return;
84: }
85: if(chown(nmbuf, clientuid(), clientgid()) < 0)
86: return;
87: files[n].fd = open(nmbuf, 2);
88: if(files[n].fd < 0) {
89: files[n].fd = open(nmbuf, 0);
90: if(files[n].fd < 0) {
91: client.errno = errno;
92: unlink(nmbuf);
93: close(fd);
94: return;
95: }
96: files[n].flags = 1;
97: }
98: close(fd); /* fd was write-only */
99: if(stat(nmbuf, &files[n].stb) < 0) { /* it was there a second ago */
100: client.errno = errno;
101: unlink(nmbuf);
102: close(files[n].fd);
103: return;
104: }
105: checkdev(files[n].stb.st_dev);
106: files[n].tag = maketag(&files[n].stb);
107: if(setname(n))
108: return;
109: retnami(n);
110: }
111:
112: linkit()
113: { int i, n;
114: if(dirwriteperm())
115: return;
116: if(openfile()) {
117: client.errno = EEXIST;
118: close(tfile.fd);
119: return;
120: }
121: for(i = 0; i < FILES; i++)
122: if(files[i].tag == client.ino)
123: break;
124: if(i >= FILES) { /* can't happen */
125: error("can't happen: linkit %s, no tag %x\n", nmbuf, client.ino);
126: client.errno = EXDEV; /* not really */
127: return;
128: }
129: debug("linking %s to %s\n", files[i].name, nmbuf);
130: n = link(files[i].name, nmbuf);
131: if(n < 0) {
132: debug("link errno %d\n", errno);
133: client.errno = errno;
134: }
135: }
136:
137: mkdirit()
138: { int n;
139: if(openfile()) {
140: client.errno = EEXIST;
141: close(tfile.fd); /* how does entry get tossed? */
142: return;
143: }
144: if(client.namiflags == NBROOT)
145: return;
146: if(dirwriteperm())
147: return;
148: if(mkdir(nmbuf, client.mode) < 0) {
149: client.errno = errno;
150: return;
151: }
152: if(chown(nmbuf, clientuid(), clientgid()) < 0)
153: return;
154: }
155:
156: rmdirit()
157: {
158: if(!openfile()) {
159: client.errno = EEXIST;
160: return;
161: }
162: close(tfile.fd);
163: if(dirwriteperm())
164: return;
165: if(rmdir(nmbuf) < 0)
166: client.errno = errno;
167: else
168: client.errno = 0;
169: }
170:
171: delit()
172: {
173: if(!openfile()) {
174: client.errno = ENOENT;
175: close(tfile.fd);
176: return;
177: }
178: if(client.namiflags == NBROOT)
179: return;
180: close(tfile.fd);
181: if(dirwriteperm())
182: return;
183: if((tfile.stb.st_mode & S_IFMT) != S_IFREG) {
184: client.errno = EISDIR;
185: return;
186: }
187: if(unlink(nmbuf) < 0)
188: client.errno = errno;
189: else
190: client.errno = 0;
191: }
192:
193: openfile()
194: { unsigned char *p;
195: static struct stat statb;
196: int i;
197: slash = 0;
198: for(p = nmbuf; *p; ) {
199: for(; *p == '/'; p++)
200: slash = p;
201: if(*p == 0)
202: break;
203: *--p = 0;
204: i = stat(nmbuf, &statb);
205: if(i < 0) {
206: debug("openfile: stat %s (%d)\n", nmbuf, errno);
207: client.errno = errno;
208: return(0);
209: }
210: if(searchperm())
211: return(0);
212: *p++ = '/';
213: checkdev(statb.st_dev);
214: if(maketag(&statb) == roottag && p[0] == '.' && p[1] == '.'
215: && (p[2] == 0 || p[2] == '/')) {
216: client.namiflags = NBROOT;
217: client.used = 2 + (p - nmbuf) - nmoffset;
218: debug("openfile: root used %d offset %d\n", client.used,
219: nmoffset);
220: return(0);
221: }
222: while(*p && *p != '/')
223: p++;
224: }
225: i = stat(nmbuf, &statb);
226: if(i < 0)
227: return(0);
228: tfile.fd = -1;
229: tfile.flags = 0;
230: tfile.stb = statb;
231: tfile.fd = open(nmbuf, 2);
232: if(tfile.fd < 0) {
233: tfile.fd = open(nmbuf, 0);
234: if(tfile.fd < 0)
235: return(0);
236: tfile.flags = 1;
237: }
238: return(1);
239: }
240:
241: retnami(n)
242: { file *t = files + n;
243: client.tag = t->tag;
244: client.ino = t->stb.st_ino;
245: client.dev = hostdev(t->stb.st_dev);
246: debug("retnami dev 0x%x ino %d tag 0x%x %s\n", client.dev, client.ino,
247: client.tag, t->name);
248: client.mode = t->stb.st_mode;
249: client.used = 0; /* ? */
250: client.nlink = t->stb.st_nlink;
251: client.uid = hostuid(t->stb.st_uid);
252: client.gid = hostgid(t->stb.st_gid);
253: client.size = t->stb.st_size; /* watch it! */
254: if(cray && client.size >= 0x80000000)
255: client.size = 0x7fffffff;
256: /* fortunately all known hosts agree on time */
257: client.ta = t->stb.st_atime - dtime;
258: client.tc = t->stb.st_ctime - dtime;
259: client.tm = t->stb.st_mtime - dtime;
260: }
261:
262: gimmefile()
263: { int i;
264: for(i = 0; i < FILES; i++)
265: if(files[i].tag == 0)
266: break;
267: if(i >= FILES) {
268: error("out of file structs %d\n", i);
269: client.errno = ENFILE;
270: return(-1);
271: }
272: files[i].flags = 0;
273: files[i].pos = 0;
274: return(i);
275: }
276:
277: /* is this really an error to recover from? */
278: setname(n)
279: { unsigned char *p;
280: p = (unsigned char *)malloc(strlen(nmbuf) + 1);
281: if(p == NULL) {
282: error("out of space on %s\n", nmbuf);
283: client.errno = ENOSPC;
284: return(-1);
285: }
286: strcpy(p, nmbuf);
287: files[n].name = p;
288: return(0);
289: }
290:
291: checkdupl(n)
292: { int i;
293: unsigned char *x;
294: /* if it duplicates someone we've got, toss the old one, but use its tag */
295: for(i = 0; i < FILES; i++) {
296: if(i == n)
297: continue;
298: if(files[i].tag != files[n].tag)
299: continue;
300: debug("ok: creat found dup %s\n", nmbuf);
301: if(strlen(files[i].name) < strlen(files[n].name)) {
302: x = files[n].name;
303: files[n].name = files[i].name;
304: free(x);
305: }
306: else
307: free(files[i].name);
308: close(files[i].fd);
309: files[i].tag = 0;
310: }
311: /* update device translation if necessary */
312: checkdev(files[n].stb.st_dev);
313: }
314:
315: dev *devs;
316: int devlen, ndev;
317: checkdev(n)
318: { int i;
319: for(i = 0; i < ndev; i++)
320: if(devs[i].hdev == n)
321: return;
322: if(ndev >= devlen) {
323: if(!devlen)
324: devs = (dev *) malloc((devlen = 10) * sizeof(dev));
325: else {
326: devlen *= 2;
327: devs = (dev *) realloc((char *)devs, devlen * sizeof(dev));
328: error("reallocated devs to %d entries\n", devlen);
329: }
330: if(!devs)
331: fatal("alloc of %d devs failed!\n", devlen);
332: }
333: if(ndev >= 256)
334: fatal("%d devs? (too many)\n", ndev);
335: devs[ndev].hdev = n;
336: devs[ndev].cdev = hisdev | ndev;
337: debug("devs[%d] %x->%x\n", ndev, n, hisdev | ndev);
338: ndev++;
339: }
340:
341: addroot()
342: { int n;
343: n = gimmefile();
344: files[n].name = (unsigned char *)"/";
345: files[n].fd = open("/", 2);
346: if(files[n].fd < 0) {
347: files[n].fd = open("/", 0);
348: if(files[n].fd < 0)
349: fatal("can't open root, errno %d\n", errno);
350: files[n].flags = 1;
351: }
352: if(stat("/", &files[n].stb) < 0)
353: fatal("stat root errno %d\n", errno);
354: checkdev(files[n].stb.st_dev);
355: files[n].tag = maketag(&files[n].stb);
356: roottag = files[n].tag;
357: debug("root %d, tag 0x%x\n", n, files[n].tag);
358: if(files[n].stb.st_ino != ROOTINO) /* which ROOTINO is this? */
359: error("client and host probably don't agree on rootino %d\n",
360: files[n].stb.st_ino);
361: }
362:
363: maketag(s)
364: struct stat *s;
365: { int tag;
366: tag = (hostdev(s->st_dev) << 16) | s->st_ino;
367: debug("maketag (%x,%x)->%x\n", s->st_dev, s->st_ino, tag);
368: return(tag);
369: }
370:
371: #if cray == 1
372: #include "signal.h"
373: int crapsig;
374: char sysbuf[256];
375: mkdir(s)
376: char *s;
377: { int pid, ret = 0;
378: if(!crapsig++)
379: signal(SIGCLD, SIG_IGN);
380: sprintf(sysbuf, "mkdir %s", s);
381: if(strlen(sysbuf) >= sizeof(sysbuf))
382: fatal("sysbuf overflow %s\n", sysbuf);
383: if((pid = fork()) == 0) {
384: setuid(clientuid());
385: setgid(clientgid());
386: exit(system(sysbuf));
387: }
388: wait(&ret);
389: if(!ret)
390: return(0);
391: errno = EPERM; /* who knows? */
392: return(-1);
393: }
394: rmdir(s)
395: char *s;
396: {
397: if(!crapsig++)
398: signal(SIGCLD, SIG_IGN);
399: sprintf(sysbuf, "rmdir %s", s);
400: if(strlen(sysbuf) >= sizeof(sysbuf))
401: fatal("sysbuf overflow in rmdir %s\n", sysbuf);
402: if(system(sysbuf) == 0)
403: return(0);
404: errno = EPERM; /* ? */
405: return(-1);
406: }
407: fchmod()
408: {
409: fatal("!!!fchmod called\n");
410: }
411: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.