|
|
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.