|
|
1.1 ! root 1: #include "u.h" ! 2: #include "../port/lib.h" ! 3: #include "mem.h" ! 4: #include "dat.h" ! 5: #include "fns.h" ! 6: #include "../port/error.h" ! 7: ! 8: /* ! 9: * The sys*() routines needn't poperror() as they return directly to syscall(). ! 10: */ ! 11: ! 12: int ! 13: newfd(Chan *c) ! 14: { ! 15: Fgrp *f = u->p->fgrp; ! 16: int i; ! 17: ! 18: lock(f); ! 19: for(i=0; i<NFD; i++) ! 20: if(f->fd[i] == 0){ ! 21: if(i > f->maxfd) ! 22: f->maxfd = i; ! 23: f->fd[i] = c; ! 24: unlock(f); ! 25: return i; ! 26: } ! 27: unlock(f); ! 28: exhausted("file descriptors"); ! 29: return 0; ! 30: } ! 31: ! 32: Chan* ! 33: fdtochan(int fd, int mode, int chkmnt, int iref) ! 34: { ! 35: Chan *c; ! 36: Fgrp *f; ! 37: ! 38: c = 0; ! 39: f = u->p->fgrp; ! 40: ! 41: lock(f); ! 42: if(fd<0 || NFD<=fd || (c = f->fd[fd])==0) { ! 43: unlock(f); ! 44: error(Ebadfd); ! 45: } ! 46: if(iref) ! 47: incref(c); ! 48: unlock(f); ! 49: ! 50: if(chkmnt && (c->flag&CMSG)) { ! 51: if(iref) ! 52: close(c); ! 53: error(Ebadusefd); ! 54: } ! 55: ! 56: if(mode<0 || c->mode==ORDWR) ! 57: return c; ! 58: ! 59: if((mode&OTRUNC) && c->mode==OREAD) { ! 60: if(iref) ! 61: close(c); ! 62: error(Ebadusefd); ! 63: } ! 64: ! 65: if((mode&~OTRUNC) != c->mode) { ! 66: if(iref) ! 67: close(c); ! 68: error(Ebadusefd); ! 69: } ! 70: ! 71: return c; ! 72: } ! 73: ! 74: int ! 75: openmode(ulong o) ! 76: { ! 77: if(o >= (OTRUNC|OCEXEC|ORCLOSE|OEXEC)) ! 78: error(Ebadarg); ! 79: o &= ~(OTRUNC|OCEXEC|ORCLOSE); ! 80: if(o > OEXEC) ! 81: error(Ebadarg); ! 82: if(o == OEXEC) ! 83: return OREAD; ! 84: return o; ! 85: } ! 86: ! 87: long ! 88: syspipe(ulong *arg) ! 89: { ! 90: int fd[2]; ! 91: Chan *c[2]; ! 92: Dev *d; ! 93: Fgrp *f = u->p->fgrp; ! 94: ! 95: validaddr(arg[0], 2*BY2WD, 1); ! 96: evenaddr(arg[0]); ! 97: d = &devtab[devno('|', 0)]; ! 98: c[0] = (*d->attach)(0); ! 99: c[1] = 0; ! 100: fd[0] = -1; ! 101: fd[1] = -1; ! 102: if(waserror()){ ! 103: close(c[0]); ! 104: if(c[1]) ! 105: close(c[1]); ! 106: if(fd[0] >= 0) ! 107: f->fd[fd[0]]=0; ! 108: if(fd[1] >= 0) ! 109: f->fd[fd[1]]=0; ! 110: nexterror(); ! 111: } ! 112: c[1] = (*d->clone)(c[0], 0); ! 113: (*d->walk)(c[0], "data"); ! 114: (*d->walk)(c[1], "data1"); ! 115: c[0] = (*d->open)(c[0], ORDWR); ! 116: c[1] = (*d->open)(c[1], ORDWR); ! 117: fd[0] = newfd(c[0]); ! 118: fd[1] = newfd(c[1]); ! 119: ((long*)arg[0])[0] = fd[0]; ! 120: ((long*)arg[0])[1] = fd[1]; ! 121: poperror(); ! 122: return 0; ! 123: } ! 124: ! 125: long ! 126: sysdup(ulong *arg) ! 127: { ! 128: int fd; ! 129: Chan *c, *oc; ! 130: Fgrp *f = u->p->fgrp; ! 131: ! 132: /* ! 133: * Close after dup'ing, so date > #d/1 works ! 134: */ ! 135: c = fdtochan(arg[0], -1, 0, 1); ! 136: fd = arg[1]; ! 137: if(fd != -1){ ! 138: if(fd<0 || NFD<=fd) { ! 139: close(c); ! 140: error(Ebadfd); ! 141: } ! 142: lock(f); ! 143: if(fd > f->maxfd) ! 144: f->maxfd = fd; ! 145: ! 146: oc = f->fd[fd]; ! 147: f->fd[fd] = c; ! 148: unlock(f); ! 149: if(oc) ! 150: close(oc); ! 151: }else{ ! 152: if(waserror()) { ! 153: close(c); ! 154: nexterror(); ! 155: } ! 156: fd = newfd(c); ! 157: poperror(); ! 158: } ! 159: ! 160: return fd; ! 161: } ! 162: ! 163: long ! 164: sysopen(ulong *arg) ! 165: { ! 166: int fd; ! 167: Chan *c = 0; ! 168: ! 169: openmode(arg[1]); /* error check only */ ! 170: if(waserror()){ ! 171: if(c) ! 172: close(c); ! 173: nexterror(); ! 174: } ! 175: validaddr(arg[0], 1, 0); ! 176: c = namec((char*)arg[0], Aopen, arg[1], 0); ! 177: fd = newfd(c); ! 178: poperror(); ! 179: return fd; ! 180: } ! 181: ! 182: void ! 183: fdclose(int fd, int flag) ! 184: { ! 185: int i; ! 186: Chan *c; ! 187: Fgrp *f = u->p->fgrp; ! 188: ! 189: lock(f); ! 190: c = f->fd[fd]; ! 191: if(c == 0){ ! 192: /* can happen for users with shared fd tables */ ! 193: unlock(f); ! 194: return; ! 195: } ! 196: if(flag){ ! 197: if(c==0 || !(c->flag&flag)){ ! 198: unlock(f); ! 199: return; ! 200: } ! 201: } ! 202: f->fd[fd] = 0; ! 203: if(fd == f->maxfd) ! 204: for(i=fd; --i>=0 && f->fd[i]==0; ) ! 205: f->maxfd = i; ! 206: ! 207: unlock(f); ! 208: close(c); ! 209: } ! 210: ! 211: long ! 212: sysclose(ulong *arg) ! 213: { ! 214: fdtochan(arg[0], -1, 0, 0); ! 215: fdclose(arg[0], 0); ! 216: ! 217: return 0; ! 218: } ! 219: ! 220: long ! 221: unionread(Chan *c, void *va, long n) ! 222: { ! 223: long nr; ! 224: Chan *nc; ! 225: Pgrp *pg; ! 226: ! 227: pg = u->p->pgrp; ! 228: rlock(&pg->ns); ! 229: ! 230: for(;;) { ! 231: /* Error causes component of union to be skipped */ ! 232: if(waserror()) ! 233: goto next; ! 234: ! 235: nc = clone(c->mnt->to, 0); ! 236: poperror(); ! 237: ! 238: if(c->mountid != c->mnt->mountid) { ! 239: pprint("unionread: changed underfoot?\n"); ! 240: runlock(&pg->ns); ! 241: close(nc); ! 242: return 0; ! 243: } ! 244: ! 245: if(waserror()) { ! 246: close(nc); ! 247: goto next; ! 248: } ! 249: ! 250: nc = (*devtab[nc->type].open)(nc, OREAD); ! 251: nc->offset = c->offset; ! 252: nr = (*devtab[nc->type].read)(nc, va, n, nc->offset); ! 253: /* devdirread e.g. changes it */ ! 254: c->offset = nc->offset; ! 255: poperror(); ! 256: ! 257: close(nc); ! 258: if(nr > 0) { ! 259: runlock(&pg->ns); ! 260: return nr; ! 261: } ! 262: /* Advance to next element */ ! 263: next: ! 264: c->mnt = c->mnt->next; ! 265: if(c->mnt == 0) ! 266: break; ! 267: c->mountid = c->mnt->mountid; ! 268: c->offset = 0; ! 269: } ! 270: runlock(&pg->ns); ! 271: return 0; ! 272: } ! 273: ! 274: long ! 275: sysread(ulong *arg) ! 276: { ! 277: int dir; ! 278: long n; ! 279: Chan *c; ! 280: ! 281: validaddr(arg[1], arg[2], 1); ! 282: c = fdtochan(arg[0], OREAD, 1, 1); ! 283: if(waserror()) { ! 284: close(c); ! 285: nexterror(); ! 286: } ! 287: ! 288: n = arg[2]; ! 289: dir = c->qid.path&CHDIR; ! 290: ! 291: if(dir) { ! 292: n -= n%DIRLEN; ! 293: if(c->offset%DIRLEN || n==0) ! 294: error(Etoosmall); ! 295: } ! 296: ! 297: if(dir && c->mnt) ! 298: n = unionread(c, (void*)arg[1], n); ! 299: else ! 300: n = (*devtab[c->type].read)(c, (void*)arg[1], n, c->offset); ! 301: ! 302: lock(c); ! 303: c->offset += n; ! 304: unlock(c); ! 305: ! 306: poperror(); ! 307: close(c); ! 308: ! 309: return n; ! 310: } ! 311: ! 312: long ! 313: syswrite(ulong *arg) ! 314: { ! 315: Chan *c; ! 316: long n; ! 317: ! 318: validaddr(arg[1], arg[2], 0); ! 319: c = fdtochan(arg[0], OWRITE, 1, 1); ! 320: if(waserror()) { ! 321: close(c); ! 322: nexterror(); ! 323: } ! 324: ! 325: if(c->qid.path & CHDIR) ! 326: error(Eisdir); ! 327: ! 328: n = (*devtab[c->type].write)(c, (void*)arg[1], arg[2], c->offset); ! 329: ! 330: lock(c); ! 331: c->offset += n; ! 332: unlock(c); ! 333: ! 334: poperror(); ! 335: close(c); ! 336: ! 337: return n; ! 338: } ! 339: ! 340: long ! 341: sysseek(ulong *arg) ! 342: { ! 343: Chan *c; ! 344: char buf[DIRLEN]; ! 345: Dir dir; ! 346: long off; ! 347: ! 348: c = fdtochan(arg[0], -1, 1, 0); ! 349: if(c->qid.path & CHDIR) ! 350: error(Eisdir); ! 351: ! 352: if(devchar[c->type] == '|') ! 353: error(Eisstream); ! 354: ! 355: off = 0; ! 356: switch(arg[2]){ ! 357: case 0: ! 358: off = c->offset = arg[1]; ! 359: break; ! 360: ! 361: case 1: ! 362: lock(c); /* lock for read/write update */ ! 363: c->offset += (long)arg[1]; ! 364: off = c->offset; ! 365: unlock(c); ! 366: break; ! 367: ! 368: case 2: ! 369: (*devtab[c->type].stat)(c, buf); ! 370: convM2D(buf, &dir); ! 371: c->offset = dir.length + (long)arg[1]; ! 372: off = c->offset; ! 373: break; ! 374: } ! 375: return off; ! 376: } ! 377: ! 378: long ! 379: sysfstat(ulong *arg) ! 380: { ! 381: Chan *c; ! 382: ! 383: validaddr(arg[1], DIRLEN, 1); ! 384: evenaddr(arg[1]); ! 385: c = fdtochan(arg[0], -1, 0, 1); ! 386: if(waserror()) { ! 387: close(c); ! 388: nexterror(); ! 389: } ! 390: (*devtab[c->type].stat)(c, (char*)arg[1]); ! 391: poperror(); ! 392: close(c); ! 393: return 0; ! 394: } ! 395: ! 396: long ! 397: sysstat(ulong *arg) ! 398: { ! 399: Chan *c; ! 400: ! 401: validaddr(arg[1], DIRLEN, 1); ! 402: evenaddr(arg[1]); ! 403: validaddr(arg[0], 1, 0); ! 404: c = namec((char*)arg[0], Aaccess, 0, 0); ! 405: if(waserror()){ ! 406: close(c); ! 407: nexterror(); ! 408: } ! 409: (*devtab[c->type].stat)(c, (char*)arg[1]); ! 410: poperror(); ! 411: close(c); ! 412: return 0; ! 413: } ! 414: ! 415: long ! 416: syschdir(ulong *arg) ! 417: { ! 418: Chan *c; ! 419: ! 420: validaddr(arg[0], 1, 0); ! 421: c = namec((char*)arg[0], Atodir, 0, 0); ! 422: close(u->dot); ! 423: u->dot = c; ! 424: return 0; ! 425: } ! 426: ! 427: long ! 428: bindmount(ulong *arg, int ismount) ! 429: { ! 430: Chan *c0, *c1, *bc; ! 431: ulong flag; ! 432: long ret; ! 433: int fd; ! 434: struct{ ! 435: Chan *chan; ! 436: char *spec; ! 437: }bogus; ! 438: ! 439: flag = arg[2]; ! 440: fd = arg[0]; ! 441: if(flag>MMASK || (flag&MORDER)==(MBEFORE|MAFTER)) ! 442: error(Ebadarg); ! 443: if(ismount){ ! 444: bc = fdtochan(fd, 2, 0, 1); ! 445: if(waserror()) { ! 446: close(bc); ! 447: nexterror(); ! 448: } ! 449: bogus.chan = bc; ! 450: ! 451: validaddr(arg[3], 1, 0); ! 452: if(vmemchr((char*)arg[3], '\0', NAMELEN) == 0) ! 453: error(Ebadarg); ! 454: ! 455: bogus.spec = (char*)arg[3]; ! 456: ! 457: ret = devno('M', 0); ! 458: c0 = (*devtab[ret].attach)((char*)&bogus); ! 459: ! 460: poperror(); ! 461: close(bc); ! 462: } ! 463: else { ! 464: validaddr(arg[0], 1, 0); ! 465: c0 = namec((char*)arg[0], Aaccess, 0, 0); ! 466: } ! 467: if(waserror()){ ! 468: close(c0); ! 469: nexterror(); ! 470: } ! 471: validaddr(arg[1], 1, 0); ! 472: c1 = namec((char*)arg[1], Amount, 0, 0); ! 473: if(waserror()){ ! 474: close(c1); ! 475: nexterror(); ! 476: } ! 477: if((c0->qid.path^c1->qid.path) & CHDIR) ! 478: error(Emount); ! 479: if(flag && !(c0->qid.path&CHDIR)) ! 480: error(Emount); ! 481: ret = mount(c0, c1, flag); ! 482: poperror(); ! 483: close(c1); ! 484: poperror(); ! 485: close(c0); ! 486: if(ismount) ! 487: fdclose(fd, 0); ! 488: return ret; ! 489: } ! 490: ! 491: long ! 492: sysbind(ulong *arg) ! 493: { ! 494: return bindmount(arg, 0); ! 495: } ! 496: ! 497: long ! 498: sysmount(ulong *arg) ! 499: { ! 500: return bindmount(arg, 1); ! 501: } ! 502: ! 503: long ! 504: sysunmount(ulong *arg) ! 505: { ! 506: Chan *cmount, *cmounted; ! 507: ! 508: cmounted = 0; ! 509: ! 510: validaddr(arg[1], 1, 0); ! 511: cmount = namec((char *)arg[1], Amount, 0, 0); ! 512: ! 513: if(arg[0]) { ! 514: if(waserror()) { ! 515: close(cmount); ! 516: nexterror(); ! 517: } ! 518: validaddr(arg[0], 1, 0); ! 519: cmounted = namec((char*)arg[0], Aopen, OREAD, 0); ! 520: poperror(); ! 521: } ! 522: ! 523: if(waserror()) { ! 524: close(cmount); ! 525: if(cmounted) ! 526: close(cmounted); ! 527: nexterror(); ! 528: } ! 529: unmount(cmount, cmounted); ! 530: close(cmount); ! 531: if(cmounted) ! 532: close(cmounted); ! 533: poperror(); ! 534: return 0; ! 535: } ! 536: ! 537: long ! 538: syscreate(ulong *arg) ! 539: { ! 540: int fd; ! 541: Chan *c = 0; ! 542: ! 543: openmode(arg[1]); /* error check only */ ! 544: if(waserror()) { ! 545: if(c) ! 546: close(c); ! 547: nexterror(); ! 548: } ! 549: validaddr(arg[0], 1, 0); ! 550: c = namec((char*)arg[0], Acreate, arg[1], arg[2]); ! 551: fd = newfd(c); ! 552: poperror(); ! 553: return fd; ! 554: } ! 555: ! 556: long ! 557: sysremove(ulong *arg) ! 558: { ! 559: Chan *c; ! 560: ! 561: validaddr(arg[0], 1, 0); ! 562: c = namec((char*)arg[0], Aaccess, 0, 0); ! 563: if(waserror()){ ! 564: c->type = 0; /* see below */ ! 565: close(c); ! 566: nexterror(); ! 567: } ! 568: (*devtab[c->type].remove)(c); ! 569: /* ! 570: * Remove clunks the fid, but we need to recover the Chan ! 571: * so fake it up. rootclose() is known to be a nop. ! 572: */ ! 573: c->type = 0; ! 574: poperror(); ! 575: close(c); ! 576: return 0; ! 577: } ! 578: ! 579: long ! 580: syswstat(ulong *arg) ! 581: { ! 582: Chan *c; ! 583: ! 584: validaddr(arg[1], DIRLEN, 0); ! 585: nameok((char*)arg[1]); ! 586: validaddr(arg[0], 1, 0); ! 587: c = namec((char*)arg[0], Aaccess, 0, 0); ! 588: if(waserror()){ ! 589: close(c); ! 590: nexterror(); ! 591: } ! 592: (*devtab[c->type].wstat)(c, (char*)arg[1]); ! 593: poperror(); ! 594: close(c); ! 595: return 0; ! 596: } ! 597: ! 598: long ! 599: sysfwstat(ulong *arg) ! 600: { ! 601: Chan *c; ! 602: ! 603: validaddr(arg[1], DIRLEN, 0); ! 604: nameok((char*)arg[1]); ! 605: c = fdtochan(arg[0], -1, 1, 1); ! 606: if(waserror()) { ! 607: close(c); ! 608: nexterror(); ! 609: } ! 610: (*devtab[c->type].wstat)(c, (char*)arg[1]); ! 611: poperror(); ! 612: close(c); ! 613: return 0; ! 614: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.