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