|
|
1.1 ! root 1: /* ! 2: ! 3: Copyright 1991,1992 Eric R. Smith. All rights reserved. ! 4: ! 5: */ ! 6: ! 7: ! 8: ! 9: /* simple pipefs.c */ ! 10: ! 11: ! 12: ! 13: #include "mint.h" ! 14: ! 15: ! 16: ! 17: static int pipetime, pipedate; /* root directory time/date stamp */ ! 18: ! 19: ! 20: ! 21: static long pipe_root P_((int drv, fcookie *fc)); ! 22: ! 23: static long pipe_lookup P_((fcookie *dir, const char *name, fcookie *fc)); ! 24: ! 25: static long pipe_getxattr P_((fcookie *file, XATTR *xattr)); ! 26: ! 27: static long pipe_chattr P_((fcookie *file, int attrib)); ! 28: ! 29: static long pipe_chown P_((fcookie *file, int uid, int gid)); ! 30: ! 31: static long pipe_chmode P_((fcookie *file, unsigned mode)); ! 32: ! 33: static long pipe_rmdir P_((fcookie *dir, const char *name)); ! 34: ! 35: static long pipe_remove P_((fcookie *dir, const char *name)); ! 36: ! 37: static long pipe_getname P_((fcookie *root, fcookie *dir, char *pathname)); ! 38: ! 39: static long pipe_rename P_((fcookie *olddir, char *oldname, ! 40: ! 41: fcookie *newdir, const char *newname)); ! 42: ! 43: static long pipe_opendir P_((DIR *dirh, int flags)); ! 44: ! 45: static long pipe_readdir P_((DIR *dirh, char *nm, int nmlen, fcookie *)); ! 46: ! 47: static long pipe_rewinddir P_((DIR *dirh)); ! 48: ! 49: static long pipe_closedir P_((DIR *dirh)); ! 50: ! 51: static long pipe_pathconf P_((fcookie *dir, int which)); ! 52: ! 53: static long pipe_dfree P_((fcookie *dir, long *buf)); ! 54: ! 55: static long pipe_creat P_((fcookie *dir, const char *name, unsigned mode, ! 56: ! 57: int attrib, fcookie *fc)); ! 58: ! 59: static DEVDRV * pipe_getdev P_((fcookie *fc, long *devsp)); ! 60: ! 61: ! 62: ! 63: static long pipe_open P_((FILEPTR *f)); ! 64: ! 65: static long pipe_write P_((FILEPTR *f, const char *buf, long bytes)); ! 66: ! 67: static long pipe_read P_((FILEPTR *f, char *buf, long bytes)); ! 68: ! 69: static long pipe_lseek P_((FILEPTR *f, long where, int whence)); ! 70: ! 71: static long pipe_ioctl P_((FILEPTR *f, int mode, void *buf)); ! 72: ! 73: static long pipe_datime P_((FILEPTR *f, short *time, int rwflag)); ! 74: ! 75: static long pipe_close P_((FILEPTR *f, int pid)); ! 76: ! 77: static long pipe_select P_((FILEPTR *f, long p, int mode)); ! 78: ! 79: static void pipe_unselect P_((FILEPTR *f, long p, int mode)); ! 80: ! 81: ! 82: ! 83: DEVDRV pipe_device = { ! 84: ! 85: pipe_open, pipe_write, pipe_read, pipe_lseek, pipe_ioctl, pipe_datime, ! 86: ! 87: pipe_close, pipe_select, pipe_unselect ! 88: ! 89: }; ! 90: ! 91: ! 92: ! 93: /* ptys and pipes can share the same driver, for now */ ! 94: ! 95: #define pty_device pipe_device ! 96: ! 97: ! 98: ! 99: FILESYS pipe_filesys = { ! 100: ! 101: (FILESYS *)0, ! 102: ! 103: 0, ! 104: ! 105: pipe_root, ! 106: ! 107: pipe_lookup, pipe_creat, pipe_getdev, pipe_getxattr, ! 108: ! 109: pipe_chattr, pipe_chown, pipe_chmode, ! 110: ! 111: nomkdir, pipe_rmdir, pipe_remove, pipe_getname, pipe_rename, ! 112: ! 113: pipe_opendir, pipe_readdir, pipe_rewinddir, pipe_closedir, ! 114: ! 115: pipe_pathconf, pipe_dfree, ! 116: ! 117: nowritelabel, noreadlabel, nosymlink, noreadlink, ! 118: ! 119: nohardlink, nofscntl, nodskchng ! 120: ! 121: }; ! 122: ! 123: ! 124: ! 125: /* size of pipes */ ! 126: ! 127: #define PIPESIZ 4096 /* MUST be a multiple of 4 */ ! 128: ! 129: ! 130: ! 131: /* writes smaller than this are atomic */ ! 132: ! 133: #define PIPE_BUF 1024 /* should be a multiple of 4 */ ! 134: ! 135: ! 136: ! 137: /* magic flag: indicates that nobody but the creator has opened this pipe */ ! 138: ! 139: /* note: if this many processes open the pipe, we lose :-( */ ! 140: ! 141: #define VIRGIN_PIPE 0x7fff ! 142: ! 143: ! 144: ! 145: struct pipe { ! 146: ! 147: int readers; /* number of readers of this pipe */ ! 148: ! 149: int writers; /* number of writers of this pipe */ ! 150: ! 151: int head, tail; /* pipe head, tail (head == tail for empty) */ ! 152: ! 153: long rsel; /* process that did select() for reads */ ! 154: ! 155: long wsel; /* process that did select() for writes */ ! 156: ! 157: char buf[PIPESIZ]; /* pipe data */ ! 158: ! 159: }; ! 160: ! 161: ! 162: ! 163: struct fifo { ! 164: ! 165: char name[NAME_MAX+1]; /* FIFO's name */ ! 166: ! 167: short date, time; /* date & time of last write */ ! 168: ! 169: short dosflags; /* DOS flags, e.g. FA_RDONLY, FA_HIDDEN */ ! 170: ! 171: ushort mode; /* file access mode, for XATTR */ ! 172: ! 173: ushort uid, gid; /* file owner; uid and gid */ ! 174: ! 175: short flags; /* various other flags (e.g. O_TTY) */ ! 176: ! 177: short lockpid; /* pid of locking process */ ! 178: ! 179: struct tty *tty; /* tty struct for pseudo TTY's */ ! 180: ! 181: struct pipe *inp; /* pipe for reads */ ! 182: ! 183: struct pipe *outp; /* pipe for writes (0 if unidirectional) */ ! 184: ! 185: struct fifo *next; /* link to next FIFO in list */ ! 186: ! 187: FILEPTR *open; /* open file pointers for this fifo */ ! 188: ! 189: } *rootlist; ! 190: ! 191: ! 192: ! 193: ! 194: ! 195: static long ! 196: ! 197: pipe_root(drv, fc) ! 198: ! 199: int drv; ! 200: ! 201: fcookie *fc; ! 202: ! 203: { ! 204: ! 205: if (drv == PIPEDRV) { ! 206: ! 207: fc->fs = &pipe_filesys; ! 208: ! 209: fc->dev = drv; ! 210: ! 211: fc->index = 0L; ! 212: ! 213: return 0; ! 214: ! 215: } ! 216: ! 217: fc->fs = 0; ! 218: ! 219: return EINTRN; ! 220: ! 221: } ! 222: ! 223: ! 224: ! 225: static long ! 226: ! 227: pipe_lookup(dir, name, fc) ! 228: ! 229: fcookie *dir; ! 230: ! 231: const char *name; ! 232: ! 233: fcookie *fc; ! 234: ! 235: { ! 236: ! 237: struct fifo *b; ! 238: ! 239: ! 240: ! 241: TRACE("pipe_lookup(%s)", name); ! 242: ! 243: ! 244: ! 245: if (dir->index != 0) { ! 246: ! 247: DEBUG("pipe_lookup(%s): bad directory", name); ! 248: ! 249: return EPTHNF; ! 250: ! 251: } ! 252: ! 253: /* special case: an empty name in a directory means that directory */ ! 254: ! 255: /* so does "." */ ! 256: ! 257: if (!*name || (name[0] == '.' && name[1] == 0)) { ! 258: ! 259: *fc = *dir; ! 260: ! 261: return 0; ! 262: ! 263: } ! 264: ! 265: ! 266: ! 267: /* another special case: ".." could be a mount point */ ! 268: ! 269: if (!strcmp(name, "..")) { ! 270: ! 271: *fc = *dir; ! 272: ! 273: return EMOUNT; ! 274: ! 275: } ! 276: ! 277: ! 278: ! 279: for (b = rootlist; b; b = b->next) { ! 280: ! 281: if (!strnicmp(b->name, name, 14)) { ! 282: ! 283: fc->fs = &pipe_filesys; ! 284: ! 285: fc->index = (long)b; ! 286: ! 287: fc->dev = dir->dev; ! 288: ! 289: return 0; ! 290: ! 291: } ! 292: ! 293: } ! 294: ! 295: DEBUG("pipe_lookup: name `%s' not found", name); ! 296: ! 297: return EFILNF; ! 298: ! 299: } ! 300: ! 301: ! 302: ! 303: static long ! 304: ! 305: pipe_getxattr(fc, xattr) ! 306: ! 307: fcookie *fc; ! 308: ! 309: XATTR *xattr; ! 310: ! 311: { ! 312: ! 313: struct fifo *this; ! 314: ! 315: ! 316: ! 317: xattr->index = fc->index; ! 318: ! 319: xattr->dev = fc->dev; ! 320: ! 321: xattr->nlink = 1; ! 322: ! 323: xattr->blksize = 1; ! 324: ! 325: ! 326: ! 327: if (fc->index == 0) { /* root directory? */ ! 328: ! 329: xattr->uid = xattr->gid = 0; ! 330: ! 331: xattr->mtime = xattr->atime = xattr->ctime = pipetime; ! 332: ! 333: xattr->mdate = xattr->adate = xattr->cdate = pipedate; ! 334: ! 335: xattr->mode = S_IFDIR | DEFAULT_DIRMODE; ! 336: ! 337: xattr->attr = FA_DIR; ! 338: ! 339: xattr->size = xattr->nblocks = 0; ! 340: ! 341: } else { ! 342: ! 343: this = (struct fifo *)fc->index; ! 344: ! 345: xattr->uid = this->uid; ! 346: ! 347: xattr->gid = this->gid; ! 348: ! 349: xattr->mtime = xattr->atime = xattr->ctime = this->time; ! 350: ! 351: xattr->mdate = xattr->adate = xattr->cdate = this->date; ! 352: ! 353: xattr->mode = this->mode; ! 354: ! 355: xattr->attr = this->dosflags; ! 356: ! 357: /* note: fifo's that haven't been opened yet can be written to */ ! 358: ! 359: if (this->flags & O_HEAD) { ! 360: ! 361: xattr->attr &= ~FA_RDONLY; ! 362: ! 363: } ! 364: ! 365: ! 366: ! 367: xattr->nblocks = PIPESIZ; ! 368: ! 369: if (this->dosflags & FA_SYSTEM) { /* pseudo-tty */ ! 370: ! 371: xattr->size = PIPESIZ/4; ! 372: ! 373: } else { ! 374: ! 375: xattr->size = PIPESIZ; ! 376: ! 377: } ! 378: ! 379: } ! 380: ! 381: return 0; ! 382: ! 383: } ! 384: ! 385: ! 386: ! 387: static long ! 388: ! 389: pipe_chattr(fc, attrib) ! 390: ! 391: fcookie *fc; ! 392: ! 393: int attrib; ! 394: ! 395: { ! 396: ! 397: return EACCDN; ! 398: ! 399: } ! 400: ! 401: ! 402: ! 403: static long ! 404: ! 405: pipe_chown(fc, uid, gid) ! 406: ! 407: fcookie *fc; ! 408: ! 409: int uid, gid; ! 410: ! 411: { ! 412: ! 413: struct fifo *this; ! 414: ! 415: ! 416: ! 417: if (!(this = (struct fifo *)fc->index)) return EACCDN; ! 418: ! 419: ! 420: ! 421: this->uid = uid; ! 422: ! 423: this->gid = gid; ! 424: ! 425: return 0; ! 426: ! 427: } ! 428: ! 429: ! 430: ! 431: static long ! 432: ! 433: pipe_chmode(fc, mode) ! 434: ! 435: fcookie *fc; ! 436: ! 437: unsigned mode; ! 438: ! 439: { ! 440: ! 441: struct fifo *this; ! 442: ! 443: ! 444: ! 445: if (!(this = (struct fifo *)fc->index)) return EACCDN; ! 446: ! 447: ! 448: ! 449: this->mode = (this->mode & S_IFMT) | (mode & ~S_IFMT); ! 450: ! 451: return 0; ! 452: ! 453: } ! 454: ! 455: ! 456: ! 457: static long ! 458: ! 459: pipe_rmdir(dir, name) ! 460: ! 461: fcookie *dir; ! 462: ! 463: const char *name; ! 464: ! 465: { ! 466: ! 467: /* the kernel already checked to see if the file exists */ ! 468: ! 469: return EACCDN; ! 470: ! 471: } ! 472: ! 473: ! 474: ! 475: static long ! 476: ! 477: pipe_remove(dir, name) ! 478: ! 479: fcookie *dir; ! 480: ! 481: const char *name; ! 482: ! 483: { ! 484: ! 485: /* the kernel already checked to see if the file exists */ ! 486: ! 487: return EACCDN; ! 488: ! 489: } ! 490: ! 491: ! 492: ! 493: static long ! 494: ! 495: pipe_getname(root, dir, pathname) ! 496: ! 497: fcookie *root, *dir; char *pathname; ! 498: ! 499: { ! 500: ! 501: if (dir->index == 0) ! 502: ! 503: *pathname = 0; ! 504: ! 505: else ! 506: ! 507: strcpy(pathname, ((struct fifo *)dir->index)->name); ! 508: ! 509: return 0; ! 510: ! 511: } ! 512: ! 513: ! 514: ! 515: static long ! 516: ! 517: pipe_rename(olddir, oldname, newdir, newname) ! 518: ! 519: fcookie *olddir; ! 520: ! 521: char *oldname; ! 522: ! 523: fcookie *newdir; ! 524: ! 525: const char *newname; ! 526: ! 527: { ! 528: ! 529: return EACCDN; ! 530: ! 531: } ! 532: ! 533: ! 534: ! 535: static long ! 536: ! 537: pipe_opendir(dirh, flags) ! 538: ! 539: DIR *dirh; ! 540: ! 541: int flags; ! 542: ! 543: { ! 544: ! 545: if (dirh->fc.index != 0) { ! 546: ! 547: DEBUG("pipe_opendir: bad directory"); ! 548: ! 549: return EPTHNF; ! 550: ! 551: } ! 552: ! 553: dirh->index = 0; ! 554: ! 555: return 0; ! 556: ! 557: } ! 558: ! 559: ! 560: ! 561: static long ! 562: ! 563: pipe_readdir(dirh, name, namelen, fc) ! 564: ! 565: DIR *dirh; ! 566: ! 567: char *name; ! 568: ! 569: int namelen; ! 570: ! 571: fcookie *fc; ! 572: ! 573: { ! 574: ! 575: struct fifo *this; ! 576: ! 577: int i; ! 578: ! 579: int giveindex = dirh->flags == 0; ! 580: ! 581: ! 582: ! 583: i = dirh->index++; ! 584: ! 585: this = rootlist; ! 586: ! 587: while (i > 0 && this) { ! 588: ! 589: --i; this = this->next; ! 590: ! 591: } ! 592: ! 593: if (!this) ! 594: ! 595: return ENMFIL; ! 596: ! 597: ! 598: ! 599: fc->fs = &pipe_filesys; ! 600: ! 601: fc->index = (long)this; ! 602: ! 603: fc->dev = dirh->fc.dev; ! 604: ! 605: if (giveindex) { ! 606: ! 607: namelen -= sizeof(long); ! 608: ! 609: if (namelen <= 0) return ERANGE; ! 610: ! 611: *((long *)name) = (long)this; ! 612: ! 613: name += sizeof(long); ! 614: ! 615: } ! 616: ! 617: strncpy(name, this->name, namelen-1); ! 618: ! 619: if (strlen(this->name) >= namelen) ! 620: ! 621: return ENAMETOOLONG; ! 622: ! 623: return 0; ! 624: ! 625: } ! 626: ! 627: ! 628: ! 629: static long ! 630: ! 631: pipe_rewinddir(dirh) ! 632: ! 633: DIR *dirh; ! 634: ! 635: { ! 636: ! 637: dirh->index = 0; ! 638: ! 639: return 0; ! 640: ! 641: } ! 642: ! 643: ! 644: ! 645: static long ! 646: ! 647: pipe_closedir(dirh) ! 648: ! 649: DIR *dirh; ! 650: ! 651: { ! 652: ! 653: return 0; ! 654: ! 655: } ! 656: ! 657: ! 658: ! 659: static long ! 660: ! 661: pipe_pathconf(dir, which) ! 662: ! 663: fcookie *dir; ! 664: ! 665: int which; ! 666: ! 667: { ! 668: ! 669: switch(which) { ! 670: ! 671: case -1: ! 672: ! 673: return DP_MAXREQ; ! 674: ! 675: case DP_IOPEN: ! 676: ! 677: return UNLIMITED; /* no internal limit on open files */ ! 678: ! 679: case DP_MAXLINKS: ! 680: ! 681: return 1; /* no hard links */ ! 682: ! 683: case DP_PATHMAX: ! 684: ! 685: return PATH_MAX; ! 686: ! 687: case DP_NAMEMAX: ! 688: ! 689: return NAME_MAX; ! 690: ! 691: case DP_ATOMIC: ! 692: ! 693: /* BUG: for pty's, this should actually be PIPE_BUF/4 */ ! 694: ! 695: return PIPE_BUF; ! 696: ! 697: case DP_TRUNC: ! 698: ! 699: return DP_AUTOTRUNC; ! 700: ! 701: case DP_CASE: ! 702: ! 703: return DP_CASEINSENS; ! 704: ! 705: default: ! 706: ! 707: return EINVFN; ! 708: ! 709: } ! 710: ! 711: } ! 712: ! 713: ! 714: ! 715: static long ! 716: ! 717: pipe_dfree(dir, buf) ! 718: ! 719: fcookie *dir; ! 720: ! 721: long *buf; ! 722: ! 723: { ! 724: ! 725: int i; ! 726: ! 727: struct fifo *b; ! 728: ! 729: long freemem; ! 730: ! 731: ! 732: ! 733: /* the "sector" size is the number of bytes per pipe */ ! 734: ! 735: /* so we get the total number of sectors used by counting pipes */ ! 736: ! 737: ! 738: ! 739: i = 0; ! 740: ! 741: for (b = rootlist; b; b = b->next) { ! 742: ! 743: if (b->inp) i++; ! 744: ! 745: if (b->outp) i++; ! 746: ! 747: } ! 748: ! 749: ! 750: ! 751: freemem = tot_rsize(core, 0) + tot_rsize(alt, 0); ! 752: ! 753: ! 754: ! 755: /* note: the "free clusters" isn't quite accurate, since there's overhead ! 756: ! 757: * in the fifo structure; but we're not looking for 100% accuracy here ! 758: ! 759: */ ! 760: ! 761: buf[0] = freemem/PIPESIZ; /* number of free clusters */ ! 762: ! 763: buf[1] = buf[0]+i; /* total number of clusters */ ! 764: ! 765: buf[2] = PIPESIZ; /* sector size (bytes) */ ! 766: ! 767: buf[3] = 1; /* cluster size (sectors) */ ! 768: ! 769: return 0; ! 770: ! 771: } ! 772: ! 773: ! 774: ! 775: /* create a new pipe. ! 776: ! 777: * this only gets called by the kernel if a lookup already failed, ! 778: ! 779: * so we know that the new pipe creation is OK ! 780: ! 781: */ ! 782: ! 783: ! 784: ! 785: static long ! 786: ! 787: pipe_creat(dir, name, mode, attrib, fc) ! 788: ! 789: fcookie *dir; ! 790: ! 791: const char *name; ! 792: ! 793: unsigned mode; ! 794: ! 795: int attrib; ! 796: ! 797: fcookie *fc; ! 798: ! 799: { ! 800: ! 801: struct pipe *inp, *outp; ! 802: ! 803: struct tty *tty; ! 804: ! 805: struct fifo *b; ! 806: ! 807: /* selfread == 1 if we want reads to wait even if no other processes ! 808: ! 809: have currently opened the file, and writes to succeed in the same ! 810: ! 811: event. This is useful for servers who want to wait for requests. ! 812: ! 813: Pipes should always have selfread == 0. ! 814: ! 815: */ ! 816: ! 817: int selfread = (attrib & FA_HIDDEN) ? 0 : 1; ! 818: ! 819: ! 820: ! 821: ! 822: ! 823: /* create the new pipe */ ! 824: ! 825: if (!(inp = (struct pipe *)kmalloc(SIZEOF(struct pipe)))) { ! 826: ! 827: return ENSMEM; ! 828: ! 829: } ! 830: ! 831: if (attrib & FA_RDONLY) { /* read only FIFOs are unidirectional */ ! 832: ! 833: outp = 0; ! 834: ! 835: } else { ! 836: ! 837: outp = (struct pipe *)kmalloc(SIZEOF(struct pipe)); ! 838: ! 839: if (!outp) { ! 840: ! 841: kfree(inp); ! 842: ! 843: return ENSMEM; ! 844: ! 845: } ! 846: ! 847: } ! 848: ! 849: b = (struct fifo *)kmalloc(SIZEOF(struct fifo)); ! 850: ! 851: if (!b) { ! 852: ! 853: kfree(inp); ! 854: ! 855: if (outp) kfree(outp); ! 856: ! 857: return ENSMEM; ! 858: ! 859: } ! 860: ! 861: if (attrib & FA_SYSTEM) { /* pseudo-tty */ ! 862: ! 863: tty = (struct tty *)kmalloc(SIZEOF(struct tty)); ! 864: ! 865: if (!tty) { ! 866: ! 867: kfree(inp); ! 868: ! 869: kfree(b); ! 870: ! 871: if (outp) kfree(outp); ! 872: ! 873: return ENSMEM; ! 874: ! 875: } ! 876: ! 877: tty->use_cnt = 0; ! 878: ! 879: /* do_open does the rest of tty initialization */ ! 880: ! 881: } else tty = 0; ! 882: ! 883: ! 884: ! 885: /* set up the pipes appropriately */ ! 886: ! 887: inp->head = inp->tail = 0; ! 888: ! 889: inp->readers = selfread ? 1 : VIRGIN_PIPE; inp->writers = 1; ! 890: ! 891: inp->rsel = inp->wsel = 0; ! 892: ! 893: if (outp) { ! 894: ! 895: outp->head = outp->tail = 0; ! 896: ! 897: outp->readers = 1; outp->writers = selfread ? 1 : VIRGIN_PIPE; ! 898: ! 899: outp->wsel = outp->rsel = 0; ! 900: ! 901: } ! 902: ! 903: strncpy(b->name, name, NAME_MAX); ! 904: ! 905: b->time = timestamp; ! 906: ! 907: b->date = datestamp; ! 908: ! 909: b->dosflags = attrib; ! 910: ! 911: b->mode = ((attrib & FA_SYSTEM) ? S_IFCHR : S_IFIFO) | mode; ! 912: ! 913: b->uid = curproc->ruid; ! 914: ! 915: b->gid = curproc->rgid; ! 916: ! 917: ! 918: ! 919: /* the O_HEAD flag indicates that the file hasn't actually been opened ! 920: ! 921: * yet; the next open gets to be the pty master. pipe_open will ! 922: ! 923: * clear the flag when this happens. ! 924: ! 925: */ ! 926: ! 927: b->flags = ((attrib & FA_SYSTEM) ? O_TTY : 0) | O_HEAD; ! 928: ! 929: b->inp = inp; b->outp = outp; b->tty = tty; ! 930: ! 931: ! 932: ! 933: b->next = rootlist; ! 934: ! 935: b->open = (FILEPTR *)0; ! 936: ! 937: rootlist = b; ! 938: ! 939: ! 940: ! 941: /* we have to return a file cookie as well */ ! 942: ! 943: fc->fs = &pipe_filesys; ! 944: ! 945: fc->index = (long)b; ! 946: ! 947: fc->dev = dir->dev; ! 948: ! 949: ! 950: ! 951: /* update time/date stamps for u:\pipe */ ! 952: ! 953: pipetime = timestamp; ! 954: ! 955: pipedate = datestamp; ! 956: ! 957: ! 958: ! 959: return 0; ! 960: ! 961: } ! 962: ! 963: ! 964: ! 965: static DEVDRV * ! 966: ! 967: pipe_getdev(fc, devsp) ! 968: ! 969: fcookie *fc; ! 970: ! 971: long *devsp; ! 972: ! 973: { ! 974: ! 975: struct fifo *b = (struct fifo *)fc->index; ! 976: ! 977: ! 978: ! 979: return (b->flags & O_TTY) ? &pty_device : &pipe_device; ! 980: ! 981: } ! 982: ! 983: ! 984: ! 985: /* ! 986: ! 987: * PIPE device driver ! 988: ! 989: */ ! 990: ! 991: ! 992: ! 993: static long ! 994: ! 995: pipe_open(f) ! 996: ! 997: FILEPTR *f; ! 998: ! 999: { ! 1000: ! 1001: struct fifo *p; ! 1002: ! 1003: int rwmode = f->flags & O_RWMODE; ! 1004: ! 1005: ! 1006: ! 1007: p = (struct fifo *)f->fc.index; ! 1008: ! 1009: f->flags |= p->flags; ! 1010: ! 1011: /* ! 1012: ! 1013: * if this is the first open for this file, then the O_HEAD flag is ! 1014: ! 1015: * set in p->flags. If not, and someone was trying to create the file, ! 1016: ! 1017: * return an error ! 1018: ! 1019: */ ! 1020: ! 1021: if (p->flags & O_HEAD) { ! 1022: ! 1023: if (!(f->flags & O_CREAT)) { ! 1024: ! 1025: DEBUG("pipe_open: file hasn't been created yet"); ! 1026: ! 1027: return EINTRN; ! 1028: ! 1029: } ! 1030: ! 1031: p->flags &= ~O_HEAD; ! 1032: ! 1033: } else { ! 1034: ! 1035: if (f->flags & O_CREAT) { ! 1036: ! 1037: DEBUG("pipe_open: fifo already exists"); ! 1038: ! 1039: return EACCDN; ! 1040: ! 1041: } ! 1042: ! 1043: } ! 1044: ! 1045: /* ! 1046: ! 1047: * check for file sharing compatibility. note that O_COMPAT gets mutated ! 1048: ! 1049: * into O_DENYNONE, because any old programs that know about pipes will ! 1050: ! 1051: * already handle multitasking correctly ! 1052: ! 1053: */ ! 1054: ! 1055: if ( (f->flags & O_SHMODE) == O_COMPAT ) { ! 1056: ! 1057: f->flags = (f->flags & ~O_SHMODE) | O_DENYNONE; ! 1058: ! 1059: } ! 1060: ! 1061: if (denyshare(p->open, f)) ! 1062: ! 1063: return EACCDN; ! 1064: ! 1065: f->next = p->open; /* add this open fileptr to the list */ ! 1066: ! 1067: p->open = f; ! 1068: ! 1069: ! 1070: ! 1071: /* ! 1072: ! 1073: * add readers/writers to the list ! 1074: ! 1075: */ ! 1076: ! 1077: if (!(f->flags & O_HEAD)) { ! 1078: ! 1079: if (rwmode == O_RDONLY || rwmode == O_RDWR) { ! 1080: ! 1081: if (p->inp->readers == VIRGIN_PIPE) ! 1082: ! 1083: p->inp->readers = 1; ! 1084: ! 1085: else ! 1086: ! 1087: p->inp->readers++; ! 1088: ! 1089: } ! 1090: ! 1091: if ((rwmode == O_WRONLY || rwmode == O_RDWR) && p->outp) { ! 1092: ! 1093: if (p->outp->writers == VIRGIN_PIPE) ! 1094: ! 1095: p->outp->writers = 1; ! 1096: ! 1097: else ! 1098: ! 1099: p->outp->writers++; ! 1100: ! 1101: } ! 1102: ! 1103: } ! 1104: ! 1105: ! 1106: ! 1107: /* TTY devices need a tty structure in f->devinfo */ ! 1108: ! 1109: f->devinfo = (long)p->tty; ! 1110: ! 1111: ! 1112: ! 1113: return 0; ! 1114: ! 1115: } ! 1116: ! 1117: ! 1118: ! 1119: static long ! 1120: ! 1121: pipe_write(f, buf, nbytes) ! 1122: ! 1123: FILEPTR *f; const char *buf; long nbytes; ! 1124: ! 1125: { ! 1126: ! 1127: int ptail, phead, j; ! 1128: ! 1129: char *pbuf; ! 1130: ! 1131: struct pipe *p; ! 1132: ! 1133: struct fifo *this; ! 1134: ! 1135: long bytes_written = 0; ! 1136: ! 1137: long r; ! 1138: ! 1139: ! 1140: ! 1141: this = (struct fifo *)f->fc.index; ! 1142: ! 1143: p = (f->flags & O_HEAD) ? this->inp : this->outp; ! 1144: ! 1145: if (!p) { ! 1146: ! 1147: DEBUG("pipe_write: write on wrong end of pipe"); ! 1148: ! 1149: return EACCDN; ! 1150: ! 1151: } ! 1152: ! 1153: ! 1154: ! 1155: if (nbytes > 0 && nbytes <= PIPE_BUF) { ! 1156: ! 1157: check_atomicity: ! 1158: ! 1159: r = p->tail - p->head; ! 1160: ! 1161: if (r < 0) r += PIPESIZ; ! 1162: ! 1163: r = (PIPESIZ-1) - r; /* r is the number of bytes we can write */ ! 1164: ! 1165: if (r < nbytes) { ! 1166: ! 1167: /* check for broken pipes */ ! 1168: ! 1169: if (p->readers == 0 || p->readers == VIRGIN_PIPE) { ! 1170: ! 1171: check_sigs(); ! 1172: ! 1173: DEBUG("pipe_write: broken pipe"); ! 1174: ! 1175: raise(SIGPIPE); ! 1176: ! 1177: return -1; ! 1178: ! 1179: } ! 1180: ! 1181: /* wake up any readers, and wait for them to gobble some data */ ! 1182: ! 1183: if (p->rsel) { ! 1184: ! 1185: wakeselect(p->rsel); ! 1186: ! 1187: p->rsel = 0; ! 1188: ! 1189: } ! 1190: ! 1191: wake(IO_Q, (long)p); ! 1192: ! 1193: sleep(IO_Q, (long)p); ! 1194: ! 1195: goto check_atomicity; ! 1196: ! 1197: } ! 1198: ! 1199: } ! 1200: ! 1201: ! 1202: ! 1203: while (nbytes > 0) { ! 1204: ! 1205: ptail = p->tail; phead = p->head; ! 1206: ! 1207: j = ptail+1; ! 1208: ! 1209: if (j >= PIPESIZ) j = 0; ! 1210: ! 1211: if (j != phead) { ! 1212: ! 1213: pbuf = &p->buf[ptail]; ! 1214: ! 1215: do { ! 1216: ! 1217: *pbuf++ = *buf++; ! 1218: ! 1219: nbytes--; bytes_written++; ! 1220: ! 1221: if ( (ptail = j) == 0 ) ! 1222: ! 1223: pbuf = &p->buf[0]; ! 1224: ! 1225: j++; ! 1226: ! 1227: if (j >= PIPESIZ) j = 0; ! 1228: ! 1229: } while ( (nbytes > 0) && (j != phead) ); ! 1230: ! 1231: p->tail = ptail; ! 1232: ! 1233: } else { /* pipe full */ ! 1234: ! 1235: if (p->readers == 0 || p->readers == VIRGIN_PIPE) { ! 1236: ! 1237: /* maybe some other signal is waiting for us? */ ! 1238: ! 1239: check_sigs(); ! 1240: ! 1241: DEBUG("pipe_write: broken pipe"); ! 1242: ! 1243: raise(SIGPIPE); ! 1244: ! 1245: return -1; ! 1246: ! 1247: } ! 1248: ! 1249: if (f->flags & O_NDELAY) { ! 1250: ! 1251: break; ! 1252: ! 1253: } ! 1254: ! 1255: /* is someone select()ing the other end of the pipe for reading? */ ! 1256: ! 1257: if (p->rsel) { ! 1258: ! 1259: wakeselect(p->rsel); ! 1260: ! 1261: p->rsel = 0; ! 1262: ! 1263: } ! 1264: ! 1265: wake(IO_Q, (long)p); /* readers may continue */ ! 1266: ! 1267: DEBUG("pipe_write: sleep on %lx", p); ! 1268: ! 1269: sleep(IO_Q, (long)p); ! 1270: ! 1271: } ! 1272: ! 1273: } ! 1274: ! 1275: this->time = timestamp; ! 1276: ! 1277: this->date = datestamp; ! 1278: ! 1279: if (bytes_written > 0) { ! 1280: ! 1281: if (p->rsel) { ! 1282: ! 1283: wakeselect(p->rsel); ! 1284: ! 1285: p->rsel = 0; ! 1286: ! 1287: } ! 1288: ! 1289: wake(IO_Q, (long)p); /* maybe someone wants this data */ ! 1290: ! 1291: } ! 1292: ! 1293: ! 1294: ! 1295: return bytes_written; ! 1296: ! 1297: } ! 1298: ! 1299: ! 1300: ! 1301: static long ! 1302: ! 1303: pipe_read(f, buf, nbytes) ! 1304: ! 1305: FILEPTR *f; char *buf; long nbytes; ! 1306: ! 1307: { ! 1308: ! 1309: int phead, ptail; ! 1310: ! 1311: struct fifo *this; ! 1312: ! 1313: struct pipe *p; ! 1314: ! 1315: long bytes_read = 0; ! 1316: ! 1317: char *pbuf; ! 1318: ! 1319: ! 1320: ! 1321: this = (struct fifo *)f->fc.index; ! 1322: ! 1323: p = (f->flags & O_HEAD) ? this->outp : this->inp; ! 1324: ! 1325: if (!p) { ! 1326: ! 1327: DEBUG("pipe_read: read on the wrong end of a pipe"); ! 1328: ! 1329: return EACCDN; ! 1330: ! 1331: } ! 1332: ! 1333: ! 1334: ! 1335: while (nbytes > 0) { ! 1336: ! 1337: phead = p->head; ptail = p->tail; ! 1338: ! 1339: if (ptail != phead) { ! 1340: ! 1341: pbuf = &p->buf[phead]; ! 1342: ! 1343: do { ! 1344: ! 1345: *buf++ = *pbuf++; ! 1346: ! 1347: nbytes--; bytes_read++; ! 1348: ! 1349: phead++; ! 1350: ! 1351: if (phead >= PIPESIZ) { ! 1352: ! 1353: phead = 0; ! 1354: ! 1355: pbuf = &p->buf[phead]; ! 1356: ! 1357: } ! 1358: ! 1359: } while ( (nbytes > 0) && (phead != ptail) ); ! 1360: ! 1361: p->head = phead; ! 1362: ! 1363: } ! 1364: ! 1365: else if (p->writers <= 0 || p->writers == VIRGIN_PIPE) { ! 1366: ! 1367: TRACE("pipe_read: no more writers"); ! 1368: ! 1369: break; ! 1370: ! 1371: } ! 1372: ! 1373: else if (f->flags & O_NDELAY) { ! 1374: ! 1375: break; ! 1376: ! 1377: } ! 1378: ! 1379: else { ! 1380: ! 1381: /* is someone select()ing the other end of the pipe for writing? */ ! 1382: ! 1383: if (p->wsel) { ! 1384: ! 1385: wakeselect(p->wsel); ! 1386: ! 1387: p->wsel = 0; ! 1388: ! 1389: } ! 1390: ! 1391: wake(IO_Q, (long)p); /* writers may continue */ ! 1392: ! 1393: sleep(IO_Q, (long)p); ! 1394: ! 1395: } ! 1396: ! 1397: } ! 1398: ! 1399: if (bytes_read > 0) { ! 1400: ! 1401: if (p->wsel) { ! 1402: ! 1403: wakeselect(p->wsel); ! 1404: ! 1405: p->wsel = 0; ! 1406: ! 1407: } ! 1408: ! 1409: wake(IO_Q, (long)p); /* wake writers */ ! 1410: ! 1411: } ! 1412: ! 1413: return bytes_read; ! 1414: ! 1415: } ! 1416: ! 1417: ! 1418: ! 1419: static long ! 1420: ! 1421: pipe_ioctl(f, mode, buf) ! 1422: ! 1423: FILEPTR *f; int mode; void *buf; ! 1424: ! 1425: { ! 1426: ! 1427: struct pipe *p; ! 1428: ! 1429: struct fifo *this; ! 1430: ! 1431: struct flock *lck; ! 1432: ! 1433: ! 1434: ! 1435: long r; ! 1436: ! 1437: ! 1438: ! 1439: this = (struct fifo *)f->fc.index; ! 1440: ! 1441: ! 1442: ! 1443: if (mode == FIONREAD) { ! 1444: ! 1445: p = (f->flags & O_HEAD) ? this->outp : this->inp; ! 1446: ! 1447: assert(p != 0); ! 1448: ! 1449: if (p->writers <= 0 || p->writers == VIRGIN_PIPE) { ! 1450: ! 1451: DEBUG("pipe FIONREAD: no writers"); ! 1452: ! 1453: r = -1; ! 1454: ! 1455: } else { ! 1456: ! 1457: r = p->tail - p->head; ! 1458: ! 1459: if (r < 0) r += PIPESIZ; ! 1460: ! 1461: if (is_terminal(f)) ! 1462: ! 1463: r = r >> 2; /* r /= 4 */ ! 1464: ! 1465: } ! 1466: ! 1467: *((long *) buf) = r; ! 1468: ! 1469: } ! 1470: ! 1471: else if (mode == FIONWRITE) { ! 1472: ! 1473: p = (f->flags & O_HEAD) ? this->inp : this->outp; ! 1474: ! 1475: assert(p != 0); ! 1476: ! 1477: if (p->readers <= 0) { ! 1478: ! 1479: r = -1; ! 1480: ! 1481: } else { ! 1482: ! 1483: r = p->tail - p->head; ! 1484: ! 1485: if (r < 0) r += PIPESIZ; ! 1486: ! 1487: r = (PIPESIZ-1) - r; ! 1488: ! 1489: if (is_terminal(f)) ! 1490: ! 1491: r = r >> 2; /* r /= 4 */ ! 1492: ! 1493: } ! 1494: ! 1495: *((long *) buf) = r; ! 1496: ! 1497: } ! 1498: ! 1499: else if (mode == F_SETLK) { ! 1500: ! 1501: lck = (struct flock *)buf; ! 1502: ! 1503: if (this->flags & O_LOCK) { ! 1504: ! 1505: if (this->lockpid != curproc->pid) { ! 1506: ! 1507: DEBUG("pipe_ioctl: pipe already locked"); ! 1508: ! 1509: return ELOCKED; ! 1510: ! 1511: } ! 1512: ! 1513: } ! 1514: ! 1515: if (lck->l_type == F_UNLCK) { ! 1516: ! 1517: if (!(f->flags & O_LOCK)) { ! 1518: ! 1519: DEBUG("pipe_ioctl: wrong file descriptor for UNLCK"); ! 1520: ! 1521: return ENSLOCK; ! 1522: ! 1523: } ! 1524: ! 1525: this->flags &= ~O_LOCK; ! 1526: ! 1527: this->lockpid = 0; ! 1528: ! 1529: f->flags &= ~O_LOCK; ! 1530: ! 1531: } ! 1532: ! 1533: else { ! 1534: ! 1535: this->flags |= O_LOCK; ! 1536: ! 1537: this->lockpid = curproc->pid; ! 1538: ! 1539: f->flags |= O_LOCK; ! 1540: ! 1541: } ! 1542: ! 1543: } ! 1544: ! 1545: else if (mode == F_GETLK) { ! 1546: ! 1547: lck = (struct flock *)buf; ! 1548: ! 1549: if (this->flags & O_LOCK) { ! 1550: ! 1551: lck->l_type = F_WRLCK; ! 1552: ! 1553: lck->l_start = lck->l_len = 0; ! 1554: ! 1555: lck->l_pid = this->lockpid; ! 1556: ! 1557: } ! 1558: ! 1559: else ! 1560: ! 1561: lck->l_type = F_UNLCK; ! 1562: ! 1563: } ! 1564: ! 1565: else if (mode == TIOCFLUSH) { ! 1566: ! 1567: if (this->inp) { ! 1568: ! 1569: this->inp->head = this->inp->tail; ! 1570: ! 1571: wake(IO_Q, (long)this->inp); ! 1572: ! 1573: } ! 1574: ! 1575: if (this->outp) { ! 1576: ! 1577: this->outp->head = this->outp->tail; ! 1578: ! 1579: wake(IO_Q, (long)this->outp); ! 1580: ! 1581: } ! 1582: ! 1583: } else if (mode == TIOCIBAUD || mode == TIOCOBAUD) { ! 1584: ! 1585: *(long *)buf = -1L; ! 1586: ! 1587: } else if (mode == TIOCGFLAGS) { ! 1588: ! 1589: *((unsigned short *)buf) = 0; ! 1590: ! 1591: } else { ! 1592: ! 1593: /* if the file is a terminal, Fcntl will automatically ! 1594: ! 1595: * call tty_ioctl for us to handle 'generic' terminal ! 1596: ! 1597: * functions ! 1598: ! 1599: */ ! 1600: ! 1601: return EINVFN; ! 1602: ! 1603: } ! 1604: ! 1605: ! 1606: ! 1607: return 0; ! 1608: ! 1609: } ! 1610: ! 1611: ! 1612: ! 1613: static long ! 1614: ! 1615: pipe_lseek(f, where, whence) ! 1616: ! 1617: FILEPTR *f; long where; int whence; ! 1618: ! 1619: { ! 1620: ! 1621: return EACCDN; ! 1622: ! 1623: } ! 1624: ! 1625: ! 1626: ! 1627: static long ! 1628: ! 1629: pipe_datime(f, timeptr, rwflag) ! 1630: ! 1631: FILEPTR *f; ! 1632: ! 1633: short *timeptr; ! 1634: ! 1635: int rwflag; ! 1636: ! 1637: { ! 1638: ! 1639: struct fifo *this; ! 1640: ! 1641: ! 1642: ! 1643: this = (struct fifo *)f->fc.index; ! 1644: ! 1645: if (rwflag) { ! 1646: ! 1647: this->time = timeptr[0]; ! 1648: ! 1649: this->date = timeptr[1]; ! 1650: ! 1651: } ! 1652: ! 1653: else { ! 1654: ! 1655: timeptr[0] = this->time; ! 1656: ! 1657: timeptr[1] = this->date; ! 1658: ! 1659: } ! 1660: ! 1661: return 0; ! 1662: ! 1663: } ! 1664: ! 1665: ! 1666: ! 1667: static long ! 1668: ! 1669: pipe_close(f, pid) ! 1670: ! 1671: FILEPTR *f; ! 1672: ! 1673: int pid; ! 1674: ! 1675: { ! 1676: ! 1677: struct fifo *this, *old; ! 1678: ! 1679: struct pipe *p; ! 1680: ! 1681: int rwmode; ! 1682: ! 1683: FILEPTR **old_x, *x; ! 1684: ! 1685: ! 1686: ! 1687: this = (struct fifo *)f->fc.index; ! 1688: ! 1689: ! 1690: ! 1691: /* wake any processes waiting on this pipe */ ! 1692: ! 1693: wake(IO_Q, (long)this->inp); ! 1694: ! 1695: if (this->inp->rsel) ! 1696: ! 1697: wakeselect(this->inp->rsel); ! 1698: ! 1699: if (this->inp->wsel) ! 1700: ! 1701: wakeselect(this->inp->wsel); ! 1702: ! 1703: ! 1704: ! 1705: if (this->outp) { ! 1706: ! 1707: wake(IO_Q, (long)this->outp); ! 1708: ! 1709: if (this->outp->wsel) ! 1710: ! 1711: wakeselect(this->outp->wsel); ! 1712: ! 1713: if (this->outp->rsel) ! 1714: ! 1715: wakeselect(this->outp->rsel); ! 1716: ! 1717: } ! 1718: ! 1719: ! 1720: ! 1721: if (f->links <= 0) { ! 1722: ! 1723: /* remove the file pointer from the list of open file pointers ! 1724: ! 1725: * of this pipe ! 1726: ! 1727: */ ! 1728: ! 1729: old_x = &this->open; ! 1730: ! 1731: x = this->open; ! 1732: ! 1733: while (x && x != f) { ! 1734: ! 1735: old_x = &x->next; ! 1736: ! 1737: x = x->next; ! 1738: ! 1739: } ! 1740: ! 1741: assert(x); ! 1742: ! 1743: *old_x = f->next; ! 1744: ! 1745: /* f->next = 0; */ ! 1746: ! 1747: ! 1748: ! 1749: rwmode = f->flags & O_RWMODE; ! 1750: ! 1751: if (rwmode == O_RDONLY || rwmode == O_RDWR) { ! 1752: ! 1753: p = (f->flags & O_HEAD) ? this->outp : this->inp; ! 1754: ! 1755: /* note that this can never be a virgin pipe, since we had a handle ! 1756: ! 1757: * on it! ! 1758: ! 1759: */ if (p) ! 1760: ! 1761: p->readers--; ! 1762: ! 1763: } ! 1764: ! 1765: if (rwmode == O_WRONLY || rwmode == O_RDWR) { ! 1766: ! 1767: p = (f->flags & O_HEAD) ? this->inp : this->outp; ! 1768: ! 1769: if (p) p->writers--; ! 1770: ! 1771: } ! 1772: ! 1773: ! 1774: ! 1775: /* correct for the "selfread" flag (see pipe_creat) */ ! 1776: ! 1777: if ((f->flags & O_HEAD) && !(this->dosflags & 0x02)) ! 1778: ! 1779: this->inp->readers--; ! 1780: ! 1781: ! 1782: ! 1783: /* check for locks */ ! 1784: ! 1785: if ((f->flags & O_LOCK) && (this->lockpid == pid)) { ! 1786: ! 1787: this->flags &= ~O_LOCK; ! 1788: ! 1789: } ! 1790: ! 1791: } ! 1792: ! 1793: ! 1794: ! 1795: /* see if we're finished with the pipe */ ! 1796: ! 1797: if (this->inp->readers == VIRGIN_PIPE) ! 1798: ! 1799: this->inp->readers = 0; ! 1800: ! 1801: if (this->inp->writers == VIRGIN_PIPE) ! 1802: ! 1803: this->inp->writers = 0; ! 1804: ! 1805: ! 1806: ! 1807: if (this->inp->readers <= 0 && this->inp->writers <= 0) { ! 1808: ! 1809: TRACE("disposing of closed fifo"); ! 1810: ! 1811: /* unlink from list of FIFOs */ ! 1812: ! 1813: if (rootlist == this) ! 1814: ! 1815: rootlist = this->next; ! 1816: ! 1817: else { ! 1818: ! 1819: for (old = rootlist; old->next != this; ! 1820: ! 1821: old = old->next) { ! 1822: ! 1823: if (!old) { ! 1824: ! 1825: ALERT("fifo not on list???"); ! 1826: ! 1827: return EINTRN; ! 1828: ! 1829: } ! 1830: ! 1831: } ! 1832: ! 1833: old->next = this->next; ! 1834: ! 1835: } ! 1836: ! 1837: kfree(this->inp); ! 1838: ! 1839: if (this->outp) kfree(this->outp); ! 1840: ! 1841: kfree(this); ! 1842: ! 1843: pipetime = timestamp; ! 1844: ! 1845: pipedate = datestamp; ! 1846: ! 1847: } ! 1848: ! 1849: ! 1850: ! 1851: return 0; ! 1852: ! 1853: } ! 1854: ! 1855: ! 1856: ! 1857: static long ! 1858: ! 1859: pipe_select(f, proc, mode) ! 1860: ! 1861: FILEPTR *f; ! 1862: ! 1863: long proc; ! 1864: ! 1865: int mode; ! 1866: ! 1867: { ! 1868: ! 1869: struct fifo *this; ! 1870: ! 1871: struct pipe *p; ! 1872: ! 1873: int j; ! 1874: ! 1875: ! 1876: ! 1877: this = (struct fifo *)f->fc.index; ! 1878: ! 1879: ! 1880: ! 1881: if (mode == O_RDONLY) { ! 1882: ! 1883: p = (f->flags & O_HEAD) ? this->outp : this->inp; ! 1884: ! 1885: if (!p) { ! 1886: ! 1887: DEBUG("read select on wrong end of pipe"); ! 1888: ! 1889: return 0; ! 1890: ! 1891: } ! 1892: ! 1893: ! 1894: ! 1895: /* NOTE: if p->writers <= 0 then reads won't block (they'll fail) */ ! 1896: ! 1897: if (p->tail != p->head || p->writers <= 0) { ! 1898: ! 1899: return 1; ! 1900: ! 1901: } ! 1902: ! 1903: ! 1904: ! 1905: /* BUG: multiple selects fail, only the first one works */ ! 1906: ! 1907: if (!p->rsel) ! 1908: ! 1909: p->rsel = proc; ! 1910: ! 1911: return 0; ! 1912: ! 1913: } else if (mode == O_WRONLY) { ! 1914: ! 1915: p = (f->flags & O_HEAD) ? this->inp : this->outp; ! 1916: ! 1917: if (!p) { ! 1918: ! 1919: DEBUG("write select on wrong end of pipe"); ! 1920: ! 1921: return 0; ! 1922: ! 1923: } ! 1924: ! 1925: j = p->tail+1; ! 1926: ! 1927: if (j >= PIPESIZ) j = 0; ! 1928: ! 1929: if (j != p->head || p->readers <= 0) ! 1930: ! 1931: return 1; /* data may be written */ ! 1932: ! 1933: if (!p->wsel) ! 1934: ! 1935: p->wsel = proc; ! 1936: ! 1937: return 0; ! 1938: ! 1939: } ! 1940: ! 1941: return 0; ! 1942: ! 1943: } ! 1944: ! 1945: ! 1946: ! 1947: static void ! 1948: ! 1949: pipe_unselect(f, proc, mode) ! 1950: ! 1951: FILEPTR *f; ! 1952: ! 1953: long proc; ! 1954: ! 1955: int mode; ! 1956: ! 1957: { ! 1958: ! 1959: struct fifo *this; ! 1960: ! 1961: struct pipe *p; ! 1962: ! 1963: ! 1964: ! 1965: this = (struct fifo *)f->fc.index; ! 1966: ! 1967: ! 1968: ! 1969: if (mode == O_RDONLY) { ! 1970: ! 1971: p = (f->flags & O_HEAD) ? this->outp : this->inp; ! 1972: ! 1973: if (!p) { ! 1974: ! 1975: return; ! 1976: ! 1977: } ! 1978: ! 1979: if (p->rsel == proc) ! 1980: ! 1981: p->rsel = 0; ! 1982: ! 1983: } else if (mode == O_WRONLY) { ! 1984: ! 1985: p = (f->flags & O_HEAD) ? this->inp : this->outp; ! 1986: ! 1987: if (!p) { ! 1988: ! 1989: return; ! 1990: ! 1991: } ! 1992: ! 1993: if (p->wsel == proc) ! 1994: ! 1995: p->wsel = 0; ! 1996: ! 1997: } ! 1998: ! 1999: } ! 2000:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.