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