|
|
1.1 root 1: /*
2:
3: Copyright 1990,1991,1992 Eric R. Smith. All rights reserved.
4:
5: */
6:
7:
8:
9: /* DOS file handling routines */
10:
11:
12:
13: #include "mint.h"
14:
15:
16:
17: extern char temp1[]; /* see filesys.c */
18:
19:
20:
21: static long do_dup P_((int,int));
22:
23: static void unselectme P_((PROC *));
24:
25:
26:
27: /*
28:
29: * first, some utility routines
30:
31: */
32:
33:
34:
35: FILEPTR *
36:
37: do_open(name, rwmode, attr, x)
38:
39: const char *name; /* file name */
40:
41: int rwmode; /* file access mode */
42:
43: int attr; /* TOS attributes for created files (if applicable) */
44:
45: XATTR *x; /* filled in with attributes of opened file */
46:
47: {
48:
49: struct tty *tty;
50:
51: fcookie dir, fc;
52:
53: long devsp;
54:
55: FILEPTR *f;
56:
57: DEVDRV *dev;
58:
59: long r;
60:
61: XATTR xattr;
62:
63: unsigned perm;
64:
65: int creating;
66:
67:
68:
69: /* for special BIOS "fake" devices */
70:
71: extern DEVDRV fakedev;
72:
73:
74:
1.1.1.2 ! root 75: TRACE(("do_open(%s)", name));
1.1 root 76:
77:
78:
79: /*
80:
81: * first step: get a cookie for the directory
82:
83: */
84:
85:
86:
87: r = path2cookie(name, temp1, &dir);
88:
89: if (r) {
90:
1.1.1.2 ! root 91: mint_errno = (int)r;
1.1 root 92:
1.1.1.2 ! root 93: DEBUG(("do_open(%s): error %ld", name, r));
1.1 root 94:
95: return NULL;
96:
97: }
98:
99:
100:
101: /*
102:
103: * second step: try to locate the file itself
104:
105: */
106:
107: r = relpath2cookie(&dir, temp1, follow_links, &fc, 0);
108:
109:
110:
111: /*
112:
113: * file found: this is an error if (O_CREAT|O_EXCL) are set
114:
115: */
116:
117: if ( (r == 0) && ( (rwmode & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL) ) ) {
118:
1.1.1.2 ! root 119: DEBUG(("do_open(%s): file already exists",name));
1.1 root 120:
121: mint_errno = EACCDN;
122:
123: return NULL;
124:
125: }
126:
127: /*
128:
129: * file not found: maybe we should create it
130:
131: */
132:
133: if (r == EFILNF && (rwmode & O_CREAT)) {
134:
135: /* check first for write permission in the directory */
136:
137: r = (*dir.fs->getxattr)(&dir, &xattr);
138:
139: if (r == 0) {
140:
141: if (denyaccess(&xattr, S_IWOTH))
142:
143: r = EACCDN;
144:
145: }
146:
147: if (r) {
148:
1.1.1.2 ! root 149: DEBUG(("do_open(%s): couldn't get "
1.1 root 150:
1.1.1.2 ! root 151: "write permission on directory",name));
1.1 root 152:
1.1.1.2 ! root 153: mint_errno = (int)r;
1.1 root 154:
155: return NULL;
156:
157: }
158:
159: r = (*dir.fs->creat)(&dir, temp1,
160:
161: (S_IFREG|DEFAULT_MODE) & (~curproc->umask), attr, &fc);
162:
163: if (r) {
164:
1.1.1.2 ! root 165: DEBUG(("do_open(%s): error %ld while creating file",
1.1 root 166:
1.1.1.2 ! root 167: name, r));
1.1 root 168:
1.1.1.2 ! root 169: mint_errno = (int)r;
1.1 root 170:
171: return NULL;
172:
173: }
174:
175: creating = 1;
176:
177: } else if (r) {
178:
1.1.1.2 ! root 179: DEBUG(("do_open(%s): error %ld while searching for file",
1.1 root 180:
1.1.1.2 ! root 181: name, r));
1.1 root 182:
1.1.1.2 ! root 183: mint_errno = (int)r;
1.1 root 184:
185: return NULL;
186:
187: } else {
188:
189: creating = 0;
190:
191: }
192:
193:
194:
195: /*
196:
197: * check now for permission to actually access the file
198:
199: */
200:
201: r = (*fc.fs->getxattr)(&fc, &xattr);
202:
203: if (r) {
204:
1.1.1.2 ! root 205: DEBUG(("do_open(%s): couldn't get file attributes",name));
1.1 root 206:
1.1.1.2 ! root 207: mint_errno = (int)r;
1.1 root 208:
209: return NULL;
210:
211: }
212:
213: /*
214:
215: * we don't do directories
216:
217: */
218:
219: if ( (xattr.mode & S_IFMT) == S_IFDIR ) {
220:
1.1.1.2 ! root 221: DEBUG(("do_open(%s): file is a directory",name));
1.1 root 222:
223: mint_errno = EFILNF;
224:
225: return NULL;
226:
227: }
228:
229:
230:
231: switch (rwmode & O_RWMODE) {
232:
233: case O_WRONLY:
234:
235: perm = S_IWOTH;
236:
237: break;
238:
239: case O_RDWR:
240:
241: perm = S_IROTH|S_IWOTH;
242:
243: break;
244:
245: case O_EXEC:
246:
247: perm = (fc.fs->fsflags & FS_NOXBIT) ? S_IROTH : S_IXOTH;
248:
249: break;
250:
251: case O_RDONLY:
252:
253: perm = S_IROTH;
254:
255: break;
256:
257: default:
258:
259: perm = 0;
260:
261: ALERT("do_open: bad file access mode: %x", rwmode);
262:
263: }
264:
265: if (!creating && denyaccess(&xattr, perm)) {
266:
1.1.1.2 ! root 267: DEBUG(("do_open(%s): access to file denied",name));
1.1 root 268:
269: mint_errno = EACCDN;
270:
271: return NULL;
272:
273: }
274:
275:
276:
277: /*
278:
279: * an extra check for write access -- even the superuser shouldn't
280:
281: * write to files with the FA_RDONLY attribute bit set (unless,
282:
283: * we just created the file)
284:
285: */
286:
287: if ( !creating && (xattr.attr & FA_RDONLY)) {
288:
289: if ( (rwmode & O_RWMODE) == O_RDWR ||
290:
291: (rwmode & O_RWMODE) == O_WRONLY ) {
292:
1.1.1.2 ! root 293: DEBUG(("do_open(%s): can't write a read-only file",
1.1 root 294:
1.1.1.2 ! root 295: name));
1.1 root 296:
297: mint_errno = EACCDN;
298:
299: return NULL;
300:
301: }
302:
303: }
304:
305:
306:
307: /*
308:
309: * if writing to a setuid or setgid file, clear those bits
310:
311: */
312:
313: if ( (perm & S_IWOTH) && (xattr.mode & (S_ISUID|S_ISGID)) ) {
314:
315: xattr.mode &= ~(S_ISUID|S_ISGID);
316:
317: (*fc.fs->chmode)(&fc, (xattr.mode & ~S_IFMT));
318:
319: }
320:
321: /*
322:
323: * If the caller asked for the attributes of the opened file, copy them over.
324:
325: */
326:
327: if (x) *x = xattr;
328:
329:
330:
331: /*
332:
333: * So far, so good. Let's get the device driver now, and try to
334:
335: * actually open the file.
336:
337: */
338:
339: dev = (*fc.fs->getdev)(&fc, &devsp);
340:
341: if (!dev) {
342:
1.1.1.2 ! root 343: mint_errno = (int)devsp;
1.1 root 344:
1.1.1.2 ! root 345: DEBUG(("do_open(%s): device driver not found",name));
1.1 root 346:
347: return NULL;
348:
349: }
350:
351:
352:
353: if (dev == &fakedev) { /* fake BIOS devices */
354:
355: f = curproc->handle[devsp];
356:
357: if (!f) {
358:
359: mint_errno = EIHNDL;
360:
361: return 0;
362:
363: }
364:
365: f->links++;
366:
367: return f;
368:
369: }
370:
1.1.1.2 ! root 371: if (0 == (f = new_fileptr())) {
1.1 root 372:
373: mint_errno = ENSMEM;
374:
375: return NULL;
376:
377: }
378:
379: f->links = 1;
380:
381: f->flags = rwmode;
382:
383: f->pos = 0;
384:
385: f->devinfo = devsp;
386:
387: f->fc = fc;
388:
389: f->dev = dev;
390:
391:
392:
393: r = (*dev->open)(f);
394:
395: if (r < 0) {
396:
1.1.1.2 ! root 397: DEBUG(("do_open(%s): device open failed with error %ld",
1.1 root 398:
1.1.1.2 ! root 399: name, r));
1.1 root 400:
1.1.1.2 ! root 401: mint_errno = (int)r;
1.1 root 402:
403: f->links = 0;
404:
405: dispose_fileptr(f);
406:
407: return NULL;
408:
409: }
410:
411:
412:
413: /* special code for opening a tty */
414:
415: if (is_terminal(f)) {
416:
417: extern struct tty default_tty; /* in tty.c */
418:
419:
420:
421: tty = (struct tty *)f->devinfo;
422:
423: if (tty->use_cnt == 0) { /* first open for this device? */
424:
425: *tty = default_tty;
426:
427: }
428:
429: tty->use_cnt++;
430:
431: }
432:
433: return f;
434:
435: }
436:
437:
438:
439: /*
440:
441: * helper function for do_close: this closes the indicated file pointer which
442:
443: * is assumed to be associated with process p. The extra parameter is necessary
444:
445: * because f_midipipe mucks with file pointers of other processes, so
446:
447: * sometimes p != curproc.
448:
449: *
450:
451: * Note that the function changedrv() in filesys.c can call this routine.
452:
453: * in that case, f->dev will be 0 to represent an invalid device, and
454:
455: * we cannot call the device close routine.
456:
457: */
458:
459:
460:
461: long
462:
463: do_pclose(p, f)
464:
465: PROC *p;
466:
467: FILEPTR *f;
468:
469: {
470:
471: long r = 0;
472:
473:
474:
475: if (!f) return EIHNDL;
476:
477:
478:
479: /* if this file is "select'd" by this process, unselect it
480:
1.1.1.2 ! root 481: * (this is just in case we were killed by a signal)
1.1 root 482:
483: */
484:
485:
486:
487: /* BUG? Feature? If media change is detected while we're doing the select,
488:
489: * we'll never unselect (since f->dev is set to NULL by changedrv())
490:
491: */
492:
493: if (f->dev) {
494:
495: (*f->dev->unselect)(f, (long)p, O_RDONLY);
496:
497: (*f->dev->unselect)(f, (long)p, O_WRONLY);
498:
499: }
500:
501:
502:
503: f->links--;
504:
505:
506:
507: /* TTY manipulation must be done *before* calling the device close routine,
508:
509: * since afterwards the TTY structure may no longer exist
510:
511: */
512:
513: if (is_terminal(f) && f->links <= 0) {
514:
515: struct tty *tty = (struct tty *)f->devinfo;
516:
517: tty->use_cnt--;
518:
519: if (tty->use_cnt <= 0 && tty->xkey) {
520:
521: kfree(tty->xkey);
522:
523: tty->xkey = 0;
524:
525: }
526:
527: }
528:
529:
530:
531: if (f->dev) {
532:
533: r = (*f->dev->close)(f, p->pid);
534:
535: if (r) {
536:
1.1.1.2 ! root 537: DEBUG(("close: device close failed"));
1.1 root 538:
539: }
540:
541: }
542:
543: if (f->links <= 0) {
544:
545: dispose_fileptr(f);
546:
547: }
548:
549: return r;
550:
551: }
552:
553:
554:
555: long
556:
557: do_close(f)
558:
559: FILEPTR *f;
560:
561: {
562:
563: return do_pclose(curproc, f);
564:
565: }
566:
567:
568:
1.1.1.2 ! root 569: long ARGS_ON_STACK
1.1 root 570:
571: f_open(name, mode)
572:
573: const char *name;
574:
575: int mode;
576:
577: {
578:
579: int i;
580:
581: FILEPTR *f;
582:
583: PROC *proc;
584:
585:
586:
1.1.1.2 ! root 587: TRACE(("Fopen(%s, %x)", name, mode));
1.1 root 588:
589: #if O_GLOBAL
590:
591: if (mode & O_GLOBAL) {
592:
593: /* oh, boy! user wants us to open a global handle! */
594:
595: proc = rootproc;
596:
597: }
598:
599: else
600:
601: #endif
602:
603: proc = curproc;
604:
605:
606:
607: for (i = MIN_OPEN; i < MAX_OPEN; i++) {
608:
609: if (!proc->handle[i])
610:
611: goto found_for_open;
612:
613: }
614:
1.1.1.2 ! root 615: DEBUG(("Fopen(%s): process out of handles",name));
1.1 root 616:
617: return ENHNDL; /* no more handles */
618:
619:
620:
621: found_for_open:
622:
623: mode &= O_USER; /* make sure the mode is legal */
624:
625:
626:
627: /* note: file mode 3 is reserved for the kernel; for users, transmogrify it
628:
629: * into O_RDWR (mode 2)
630:
631: */
632:
633: if ( (mode & O_RWMODE) == O_EXEC ) {
634:
635: mode = (mode & ~O_RWMODE) | O_RDWR;
636:
637: }
638:
639:
640:
641: f = do_open(name, mode, 0, (XATTR *)0);
642:
643:
644:
645:
646:
647: if (!f) {
648:
649: return mint_errno;
650:
651: }
652:
653: proc->handle[i] = f;
654:
655: /* default is to close non-standard files on exec */
656:
657: proc->fdflags[i] = FD_CLOEXEC;
658:
659:
660:
661: #if O_GLOBAL
662:
663: if (proc != curproc) {
664:
665: /* we just opened a global handle */
666:
667: i += 100;
668:
669: }
670:
671: #endif
672:
673:
674:
1.1.1.2 ! root 675: TRACE(("Fopen: returning %d", i));
1.1 root 676:
677: return i;
678:
679: }
680:
681:
682:
1.1.1.2 ! root 683: long ARGS_ON_STACK
1.1 root 684:
685: f_create(name, attrib)
686:
687: const char *name;
688:
689: int attrib;
690:
691: {
692:
693: fcookie dir;
694:
695: int i;
696:
697: FILEPTR *f;
698:
699: long r;
700:
701: PROC *proc;
702:
703: int offset = 0;
704:
705:
706:
1.1.1.2 ! root 707: TRACE(("Fcreate(%s, %x)", name, attrib));
1.1 root 708:
709: #if O_GLOBAL
710:
711: if (attrib & O_GLOBAL) {
712:
713: proc = rootproc;
714:
715: offset = 100;
716:
717: attrib &= ~O_GLOBAL;
718:
719: }
720:
721: else
722:
723: #endif
724:
725: proc = curproc;
726:
727:
728:
729: for (i = MIN_OPEN; i < MAX_OPEN; i++) {
730:
731: if (!proc->handle[i])
732:
733: goto found_for_create;
734:
735: }
736:
1.1.1.2 ! root 737: DEBUG(("Fcreate(%s): process out of handles",name));
1.1 root 738:
739: return ENHNDL; /* no more handles */
740:
741:
742:
743: found_for_create:
744:
745: if (attrib == FA_LABEL) {
746:
747: r = path2cookie(name, temp1, &dir);
748:
749: if (r) return r;
750:
751: r = (*dir.fs->writelabel)(&dir, temp1);
752:
753: if (r) return r;
754:
755: /*
756:
757: * just in case the caller tries to do something with this handle,
758:
759: * make it point to u:\dev\null
760:
761: */
762:
763: f = do_open("u:\\dev\\null", O_RDWR|O_CREAT|O_TRUNC, 0,
764:
765: (XATTR *)0);
766:
767: proc->handle[i] = f;
768:
769: return i+offset;
770:
771: }
772:
773: if (attrib & (FA_LABEL|FA_DIR)) {
774:
1.1.1.2 ! root 775: DEBUG(("Fcreate(%s,%x): illegal attributes",name,attrib));
1.1 root 776:
777: return EACCDN;
778:
779: }
780:
781:
782:
783: f = do_open(name, O_RDWR|O_CREAT|O_TRUNC, attrib, (XATTR *)0);
784:
785:
786:
787: if (!f) {
788:
1.1.1.2 ! root 789: DEBUG(("Fcreate(%s) failed, error %d", name, mint_errno));
1.1 root 790:
791: return mint_errno;
792:
793: }
794:
795: proc->handle[i] = f;
796:
797: i += offset;
798:
1.1.1.2 ! root 799: TRACE(("Fcreate: returning %d", i));
1.1 root 800:
801: return i;
802:
803: }
804:
805:
806:
1.1.1.2 ! root 807: long ARGS_ON_STACK
1.1 root 808:
809: f_close(fh)
810:
811: int fh;
812:
813: {
814:
815: FILEPTR *f;
816:
817: long r;
818:
819: PROC *proc;
820:
821:
822:
1.1.1.2 ! root 823: TRACE(("Fclose: %d", fh));
1.1 root 824:
825: #if O_GLOBAL
826:
827: if (fh >= 100) {
828:
829: fh -= 100;
830:
831: proc = rootproc;
832:
833: }
834:
835: else
836:
837: #endif
838:
839: proc = curproc;
840:
841:
842:
1.1.1.2 ! root 843: if (fh < 0 || fh >= MAX_OPEN || 0 == (f = proc->handle[fh])) {
1.1 root 844:
845: return EIHNDL;
846:
847: }
848:
849: r = do_close(f);
850:
851:
852:
853: /* standard handles should be restored to default values */
854:
855: /* do this for TOS domain only! */
856:
857: if (proc->domain == DOM_TOS) {
858:
859: if (fh == 0 || fh == 1)
860:
861: f = proc->handle[-1];
862:
863: else if (fh == 2 || fh == 3)
864:
865: f = proc->handle[-fh];
866:
867: else
868:
869: f = 0;
870:
871: } else
872:
873: f = 0;
874:
875:
876:
877: if (f) f->links++;
878:
879: proc->handle[fh] = f;
880:
881: return r;
882:
883: }
884:
885:
886:
1.1.1.2 ! root 887: long ARGS_ON_STACK
1.1 root 888:
889: f_read(fh, count, buf)
890:
891: int fh;
892:
893: long count;
894:
895: char *buf;
896:
897: {
898:
899: FILEPTR *f;
900:
901:
902:
903: PROC *proc;
904:
905:
906:
907: #if O_GLOBAL
908:
909: if (fh >= 100) {
910:
911: fh -= 100;
912:
913: proc = rootproc;
914:
915: }
916:
917: else
918:
919: #endif
920:
921: proc = curproc;
922:
923:
924:
1.1.1.2 ! root 925: if (fh < MIN_HANDLE || fh >= MAX_OPEN || 0 == (f = proc->handle[fh])) {
1.1 root 926:
1.1.1.2 ! root 927: DEBUG(("Fread: invalid handle: %d", fh));
1.1 root 928:
929: return EIHNDL;
930:
931: }
932:
933: if ( (f->flags & O_RWMODE) == O_WRONLY ) {
934:
1.1.1.2 ! root 935: DEBUG(("Fread: read on a write-only handle"));
1.1 root 936:
937: return EACCDN;
938:
939: }
940:
941: if (is_terminal(f))
942:
943: return tty_read(f, buf, count);
944:
945:
946:
1.1.1.2 ! root 947: TRACE(("Fread: %ld bytes from handle %d to %lx", count, fh, buf));
1.1 root 948:
949: return (*f->dev->read)(f, buf, count);
950:
951: }
952:
953:
954:
1.1.1.2 ! root 955: long ARGS_ON_STACK
1.1 root 956:
957: f_write(fh, count, buf)
958:
959: int fh;
960:
961: long count;
962:
963: const char *buf;
964:
965: {
966:
967: FILEPTR *f;
968:
969: PROC *proc;
970:
971: long r;
972:
973:
974:
975: #if O_GLOBAL
976:
977: if (fh >= 100) {
978:
979: fh -= 100;
980:
981: proc = rootproc;
982:
983: }
984:
985: else
986:
987: #endif
988:
989: proc = curproc;
990:
991:
992:
1.1.1.2 ! root 993: if (fh < MIN_HANDLE || fh >= MAX_OPEN || 0 == (f = proc->handle[fh])) {
1.1 root 994:
1.1.1.2 ! root 995: DEBUG(("Fwrite: bad handle: %d", fh));
1.1 root 996:
997: return EIHNDL;
998:
999: }
1000:
1001: if ( (f->flags & O_RWMODE) == O_RDONLY ) {
1002:
1.1.1.2 ! root 1003: DEBUG(("Fwrite: write on a read-only handle"));
1.1 root 1004:
1005: return EACCDN;
1006:
1007: }
1008:
1009: if (is_terminal(f))
1010:
1011: return tty_write(f, buf, count);
1012:
1013:
1014:
1015: /* it would be faster to do this in the device driver, but this
1016:
1017: * way the drivers are easier to write
1018:
1019: */
1020:
1021: if (f->flags & O_APPEND)
1022:
1023: r = (*f->dev->lseek)(f, 0L, SEEK_END);
1024:
1025: else
1026:
1027: r = 0;
1028:
1029: if (r >= 0) {
1030:
1.1.1.2 ! root 1031: TRACE(("Fwrite: %ld bytes to handle %d", count, fh));
1.1 root 1032:
1033: r = (*f->dev->write)(f, buf, count);
1034:
1035: }
1036:
1037: if (r < 0) {
1038:
1.1.1.2 ! root 1039: DEBUG(("Fwrite: error %ld", r));
1.1 root 1040:
1041: }
1042:
1043: return r;
1044:
1045: }
1046:
1047:
1048:
1.1.1.2 ! root 1049: long ARGS_ON_STACK
1.1 root 1050:
1051: f_seek(place, fh, how)
1052:
1053: long place;
1054:
1055: int fh;
1056:
1057: int how;
1058:
1059: {
1060:
1061: FILEPTR *f;
1062:
1063: PROC *proc;
1064:
1065:
1066:
1.1.1.2 ! root 1067: TRACE(("Fseek(%ld, %d) on handle %d", place, how, fh));
1.1 root 1068:
1069: #if O_GLOBAL
1070:
1071: if (fh >= 100) {
1072:
1073: fh -= 100;
1074:
1075: proc = rootproc;
1076:
1077: }
1078:
1079: else
1080:
1081: #endif
1082:
1083: proc = curproc;
1084:
1085:
1086:
1.1.1.2 ! root 1087: if (fh < MIN_HANDLE || fh >= MAX_OPEN || 0 == (f = proc->handle[fh])) {
1.1 root 1088:
1.1.1.2 ! root 1089: DEBUG(("Fseek: bad handle: %d", fh));
1.1 root 1090:
1091: return EIHNDL;
1092:
1093: }
1094:
1095: if (is_terminal(f)) {
1096:
1097: return 0;
1098:
1099: }
1100:
1101: return (*f->dev->lseek)(f, place, how);
1102:
1103: }
1104:
1105:
1106:
1107: /* duplicate file pointer fh; returns a new file pointer >= min, if
1108:
1109: one exists, or ENHNDL if not. called by f_dup and f_cntl
1110:
1111: */
1112:
1113:
1114:
1115: static long do_dup(fh, min)
1116:
1117: int fh, min;
1118:
1119: {
1120:
1121: FILEPTR *f;
1122:
1123: int i;
1124:
1125: PROC *proc;
1126:
1127:
1128:
1129: for (i = min; i < MAX_OPEN; i++) {
1130:
1131: if (!curproc->handle[i])
1132:
1133: goto found;
1134:
1135: }
1136:
1137: return ENHNDL; /* no more handles */
1138:
1139: found:
1140:
1141: #if O_GLOBAL
1142:
1143: if (fh >= 100) {
1144:
1145: fh -= 100;
1146:
1147: proc = rootproc;
1148:
1149: } else
1150:
1151: #endif
1152:
1153: proc = curproc;
1154:
1155:
1156:
1.1.1.2 ! root 1157: if (fh < MIN_HANDLE || fh >= MAX_OPEN || 0 == (f = proc->handle[fh]))
1.1 root 1158:
1159: return EIHNDL;
1160:
1161:
1162:
1163: curproc->handle[i] = f;
1164:
1165:
1166:
1167: /* set default file descriptor flags */
1168:
1169: if (i >= 0) {
1170:
1171: if (i >= MIN_OPEN)
1172:
1173: curproc->fdflags[i] = FD_CLOEXEC;
1174:
1175: else
1176:
1177: curproc->fdflags[i] = 0;
1178:
1179: }
1180:
1181: f->links++;
1182:
1183: return i;
1184:
1185: }
1186:
1187:
1188:
1.1.1.2 ! root 1189: long ARGS_ON_STACK
1.1 root 1190:
1191: f_dup(fh)
1192:
1193: int fh;
1194:
1195: {
1196:
1197: long r;
1198:
1199: r = do_dup(fh, MIN_OPEN);
1200:
1.1.1.2 ! root 1201: TRACE(("Fdup(%d) -> %ld", fh, r));
1.1 root 1202:
1203: return r;
1204:
1205: }
1206:
1207:
1208:
1.1.1.2 ! root 1209: long ARGS_ON_STACK
1.1 root 1210:
1211: f_force(newh, oldh)
1212:
1213: int newh;
1214:
1215: int oldh;
1216:
1217: {
1218:
1219: FILEPTR *f;
1220:
1221: PROC *proc;
1222:
1223:
1224:
1.1.1.2 ! root 1225: TRACE(("Fforce(%d, %d)", newh, oldh));
1.1 root 1226:
1227:
1228:
1229: #if O_GLOBAL
1230:
1231: if (oldh >= 100) {
1232:
1233: oldh -= 100;
1234:
1235: proc = rootproc;
1236:
1237: } else
1238:
1239: #endif
1240:
1241: proc = curproc;
1242:
1243:
1244:
1245: if (oldh < MIN_HANDLE || oldh >= MAX_OPEN ||
1246:
1.1.1.2 ! root 1247: 0 == (f = proc->handle[oldh])) {
1.1 root 1248:
1.1.1.2 ! root 1249: DEBUG(("Fforce: old handle invalid"));
1.1 root 1250:
1251: return EIHNDL;
1252:
1253: }
1254:
1255:
1256:
1257: if (newh < MIN_HANDLE || newh >= MAX_OPEN) {
1258:
1.1.1.2 ! root 1259: DEBUG(("Fforce: new handle out of range"));
1.1 root 1260:
1261: return EIHNDL;
1262:
1263: }
1264:
1265:
1266:
1267: (void)do_close(curproc->handle[newh]);
1268:
1269: curproc->handle[newh] = f;
1270:
1271: f->links++;
1272:
1273: /*
1274:
1275: * special: for a tty, if this is becoming a control terminal and the
1276:
1277: * tty doesn't have a pgrp yet, make it have the pgrp of the process
1278:
1279: * doing the Fforce
1280:
1281: */
1282:
1283: if (is_terminal(f) && newh == -1) {
1284:
1285: struct tty *tty = (struct tty *)f->devinfo;
1286:
1287:
1288:
1289: if (!tty->pgrp)
1290:
1291: tty->pgrp = curproc->pgrp;
1292:
1293: }
1294:
1295: return newh;
1296:
1297: }
1298:
1299:
1300:
1.1.1.2 ! root 1301: long ARGS_ON_STACK
1.1 root 1302:
1303: f_datime(timeptr, fh, rwflag)
1304:
1305: short *timeptr;
1306:
1307: int fh;
1308:
1309: int rwflag;
1310:
1311: {
1312:
1313: FILEPTR *f;
1314:
1315: PROC *proc;
1316:
1317:
1318:
1.1.1.2 ! root 1319: TRACE(("Fdatime(%d)", fh));
1.1 root 1320:
1321: #if O_GLOBAL
1322:
1323: if (fh >= 100) {
1324:
1325: fh -= 100;
1326:
1327: proc = rootproc;
1328:
1329: }
1330:
1331: else
1332:
1333: #endif
1334:
1335: proc = curproc;
1336:
1337:
1338:
1.1.1.2 ! root 1339: if (fh < MIN_HANDLE || fh >= MAX_OPEN || 0 == (f = proc->handle[fh])) {
1.1 root 1340:
1.1.1.2 ! root 1341: DEBUG(("Fdatime: invalid handle"));
1.1 root 1342:
1343: return EIHNDL;
1344:
1345: }
1346:
1347:
1348:
1349: /* some programs use Fdatime to test for TTY devices */
1350:
1351: if (is_terminal(f))
1352:
1353: return EACCDN;
1354:
1355:
1356:
1357: return (*f->dev->datime)(f, timeptr, rwflag);
1358:
1359: }
1360:
1361:
1362:
1.1.1.2 ! root 1363: long ARGS_ON_STACK
1.1 root 1364:
1365: f_lock(fh, mode, start, length)
1366:
1367: int fh, mode;
1368:
1369: long start, length;
1370:
1371: {
1372:
1373: FILEPTR *f;
1374:
1375: struct flock lock;
1376:
1377: PROC *proc;
1378:
1379:
1380:
1381: #if O_GLOBAL
1382:
1383: if (fh >= 100) {
1384:
1385: fh -= 100;
1386:
1387: proc = rootproc;
1388:
1389: }
1390:
1391: else
1392:
1393: #endif
1394:
1395: proc = curproc;
1396:
1397:
1398:
1.1.1.2 ! root 1399: if (fh < MIN_HANDLE || fh >= MAX_OPEN || 0 == (f = proc->handle[fh])) {
1.1 root 1400:
1.1.1.2 ! root 1401: DEBUG(("Flock: invalid handle"));
1.1 root 1402:
1403: return EIHNDL;
1404:
1405: }
1406:
1.1.1.2 ! root 1407: TRACE(("Flock(%d,%d,%ld,%ld)", fh, mode, start, length));
1.1 root 1408:
1409: lock.l_whence = SEEK_SET;
1410:
1411: lock.l_start = start;
1412:
1413: lock.l_len = length;
1414:
1415:
1416:
1417: if (mode == 0) /* create a lock */
1418:
1419: lock.l_type = F_WRLCK;
1420:
1421: else if (mode == 1) /* unlock region */
1422:
1423: lock.l_type = F_UNLCK;
1424:
1425: else
1426:
1427: return EINVFN;
1428:
1429:
1430:
1431: return (*f->dev->ioctl)(f, F_SETLK, &lock);
1432:
1433: }
1434:
1435:
1436:
1437: /*
1438:
1439: * extensions to GEMDOS:
1440:
1441: */
1442:
1443:
1444:
1445: /*
1446:
1447: * Fpipe(int *handles): opens a pipe. if successful, returns 0, and
1448:
1449: * sets handles[0] to a file descriptor for the read end of the pipe
1450:
1451: * and handles[1] to one for the write end.
1452:
1453: */
1454:
1455:
1456:
1.1.1.2 ! root 1457: long ARGS_ON_STACK
1.1 root 1458:
1459: f_pipe(usrh)
1460:
1461: short *usrh;
1462:
1463: {
1464:
1465: FILEPTR *in, *out;
1466:
1467: static int pipeno = 0;
1468:
1469: int i, j;
1470:
1471: char pipename[32]; /* MAGIC: 32 >= strlen "u:\pipe\sys$pipe.000\0" */
1472:
1473:
1474:
1.1.1.2 ! root 1475: TRACE(("Fpipe"));
1.1 root 1476:
1477:
1478:
1479: /* BUG: more than 999 open pipes hangs the system */
1480:
1481: do {
1482:
1483: ksprintf(pipename, "u:\\pipe\\sys$pipe.%03d", pipeno);
1484:
1485: pipeno++; if (pipeno > 999) pipeno = 0;
1486:
1.1.1.2 ! root 1487: out = do_open(pipename, O_WRONLY|O_CREAT|O_EXCL, FA_RDONLY|FA_HIDDEN|FA_CHANGED,
! 1488:
! 1489: (XATTR *)0);
1.1 root 1490:
1491: /* read-only attribute means unidirectional fifo */
1492:
1493: /* hidden attribute means check for broken pipes */
1494:
1.1.1.2 ! root 1495: /* changed attribute means act like Unix fifos */
! 1496:
1.1 root 1497: } while (out == 0 && mint_errno == EACCDN);
1498:
1499:
1500:
1501: if (!out) {
1502:
1.1.1.2 ! root 1503: DEBUG(("Fpipe: error %d", mint_errno));
1.1 root 1504:
1505: return mint_errno;
1506:
1507: }
1508:
1509:
1510:
1511: in = do_open(pipename, O_RDONLY, 0, (XATTR *)0);
1512:
1513: if (!in) {
1514:
1.1.1.2 ! root 1515: DEBUG(("Fpipe: in side of pipe not opened (error %d)",
1.1 root 1516:
1.1.1.2 ! root 1517: mint_errno));
1.1 root 1518:
1519: (void)do_close(out);
1520:
1521: return mint_errno;
1522:
1523: }
1524:
1525:
1526:
1527: for (i = MIN_OPEN; i < MAX_OPEN; i++) {
1528:
1529: if (curproc->handle[i] == 0)
1530:
1531: break;
1532:
1533: }
1534:
1535:
1536:
1537: for (j = i+1; j < MAX_OPEN; j++) {
1538:
1539: if (curproc->handle[j] == 0)
1540:
1541: break;
1542:
1543: }
1544:
1545:
1546:
1547: if (j >= MAX_OPEN) {
1548:
1.1.1.2 ! root 1549: DEBUG(("Fpipe: not enough handles left"));
1.1 root 1550:
1551: (void) do_close(in);
1552:
1553: (void) do_close(out);
1554:
1555: return ENHNDL;
1556:
1557: }
1558:
1559: curproc->handle[i] = in; curproc->handle[j] = out;
1560:
1561: /* leave pipes open across Pexec */
1562:
1563: curproc->fdflags[i] = 0;
1564:
1565: curproc->fdflags[j] = 0;
1566:
1567:
1568:
1569: usrh[0] = i;
1570:
1571: usrh[1] = j;
1572:
1.1.1.2 ! root 1573: TRACE(("Fpipe: returning 0: input %d output %d",i,j));
1.1 root 1574:
1575: return 0;
1576:
1577: }
1578:
1579:
1580:
1581: /*
1582:
1583: * f_cntl: a combination "ioctl" and "fcntl". Some functions are
1584:
1585: * handled here, if they apply to the file descriptors directly
1586:
1587: * (e.g. F_DUPFD) or if they're easily translated into file system
1588:
1589: * functions (e.g. FSTAT). Others are passed on to the device driver
1590:
1591: * via dev->ioctl.
1592:
1593: */
1594:
1595:
1596:
1.1.1.2 ! root 1597: long ARGS_ON_STACK
1.1 root 1598:
1599: f_cntl(fh, arg, cmd)
1600:
1601: int fh;
1602:
1603: long arg;
1604:
1605: int cmd;
1606:
1607: {
1608:
1609: FILEPTR *f;
1610:
1611: PROC *proc;
1612:
1613: struct flock *fl;
1614:
1615: long r;
1616:
1617:
1618:
1.1.1.2 ! root 1619: TRACE(("Fcntl(%d, cmd=0x%x)", fh, cmd));
1.1 root 1620:
1621: #if O_GLOBAL
1622:
1623: if (fh >= 100) {
1624:
1625: fh -= 100;
1626:
1627: proc = rootproc;
1628:
1629: }
1630:
1631: else
1632:
1633: #endif
1634:
1635: proc = curproc;
1636:
1637:
1638:
1639: if (fh < MIN_HANDLE || fh >= MAX_OPEN) {
1640:
1.1.1.2 ! root 1641: DEBUG(("Fcntl: bad file handle"));
1.1 root 1642:
1643: return EIHNDL;
1644:
1645: }
1646:
1647:
1648:
1649: if (cmd == F_DUPFD) {
1650:
1651: #if O_GLOBAL
1652:
1653: if (proc != curproc) fh += 100;
1654:
1655: #endif
1656:
1657: return do_dup(fh, (int)arg);
1658:
1659: }
1660:
1661:
1662:
1663: f = proc->handle[fh];
1664:
1665: if (!f) return EIHNDL;
1666:
1667:
1668:
1669: switch(cmd) {
1670:
1671: case F_GETFD:
1672:
1.1.1.2 ! root 1673: TRACE(("Fcntl F_GETFD"));
1.1 root 1674:
1675: if (fh < 0) return EIHNDL;
1676:
1677: return proc->fdflags[fh];
1678:
1679: case F_SETFD:
1680:
1.1.1.2 ! root 1681: TRACE(("Fcntl F_SETFD"));
1.1 root 1682:
1683: if (fh < 0) return EIHNDL;
1684:
1685: proc->fdflags[fh] = arg;
1686:
1687: return 0;
1688:
1689: case F_GETFL:
1690:
1.1.1.2 ! root 1691: TRACE(("Fcntl F_GETFL"));
1.1 root 1692:
1693: return f->flags & O_USER;
1694:
1695: case F_SETFL:
1696:
1.1.1.2 ! root 1697: TRACE(("Fcntl F_SETFL"));
1.1 root 1698:
1699: arg &= O_USER; /* make sure only user bits set */
1700:
1701: /* COMPATIBILITY WITH OLD VERSIONS ONLY */
1702:
1703: /* THIS CODE WILL GO AWAY. REALLY! */
1704:
1705: if (arg & 4) {
1706:
1707: arg |= O_NDELAY;
1708:
1709: arg &= ~4;
1710:
1711: }
1712:
1713:
1714:
1715: /* make sure the file access and sharing modes are not changed */
1716:
1717: arg &= ~(O_RWMODE|O_SHMODE);
1718:
1719: arg |= f->flags & (O_RWMODE|O_SHMODE);
1720:
1721: f->flags &= ~O_USER; /* set user bits to arg */
1722:
1723: f->flags |= arg;
1724:
1725: return 0;
1726:
1727: case FSTAT:
1728:
1729: return (*f->fc.fs->getxattr)(&f->fc, (XATTR *)arg);
1730:
1731: case F_SETLK:
1732:
1.1.1.2 ! root 1733: case F_SETLKW:
! 1734:
1.1 root 1735: /* make sure that the file was opened with appropriate permissions */
1736:
1737: fl = (struct flock *)arg;
1738:
1739: if (fl->l_type == F_RDLCK) {
1740:
1741: if ( (f->flags & O_RWMODE) == O_WRONLY )
1742:
1743: return EACCDN;
1744:
1745: } else {
1746:
1747: if ( (f->flags & O_RWMODE) == O_RDONLY )
1748:
1749: return EACCDN;
1750:
1751: }
1752:
1753: /* fall through to device ioctl */
1754:
1755: default:
1756:
1.1.1.2 ! root 1757: TRACE(("Fcntl mode %x: calling ioctl",cmd));
1.1 root 1758:
1759: r = (*f->dev->ioctl)(f, cmd, (void *)arg);
1760:
1761: if (r == EINVFN && is_terminal(f)) {
1762:
1763: r = tty_ioctl(f, cmd, (void *)arg);
1764:
1765: }
1766:
1767: return r;
1768:
1769: }
1770:
1771: }
1772:
1773:
1774:
1775: /*
1776:
1777: * fselect(timeout, rfd, wfd, xfd)
1778:
1779: * timeout is an (unsigned) 16 bit integer giving the maximum number
1780:
1781: * of milliseconds to wait; rfd, wfd, and xfd are pointers to 32 bit
1782:
1783: * integers containing bitmasks that describe which file descriptors
1784:
1785: * we're interested in. These masks are changed to represent which
1786:
1787: * file descriptors actually have data waiting (rfd), are ready to
1788:
1789: * output (wfd), or have exceptional conditions (xfd -- currently
1790:
1791: * ignored). If timeout is 0, fselect blocks until some file descriptor
1792:
1793: * is ready; otherwise, it waits only "timeout" milliseconds.
1794:
1795: * Return value: number of file descriptors that are available for
1796:
1797: * reading/writing; or a negative error number.
1798:
1799: */
1800:
1801:
1802:
1803: /* helper function for time outs */
1804:
1805: static void
1806:
1807: unselectme(p)
1808:
1809: PROC *p;
1810:
1811: {
1812:
1813: wakeselect((long)p);
1814:
1815: }
1816:
1817:
1818:
1.1.1.2 ! root 1819: long ARGS_ON_STACK
1.1 root 1820:
1821: f_select(timeout, rfdp, wfdp, xfdp)
1822:
1823: unsigned timeout;
1824:
1825: long *rfdp, *wfdp, *xfdp;
1826:
1827: {
1828:
1829: long rfd, wfd;
1830:
1831: long mask, bytes;
1832:
1833: int i, count;
1834:
1835: FILEPTR *f;
1836:
1837: PROC *p;
1838:
1839: TIMEOUT *t;
1840:
1841:
1842:
1.1.1.2 ! root 1843: UNUSED(xfdp);
! 1844:
! 1845:
! 1846:
1.1 root 1847: if (rfdp) {
1848:
1849: rfd = *rfdp; *rfdp = 0;
1850:
1851: }
1852:
1853: else
1854:
1855: rfd = 0;
1856:
1857: if (wfdp) {
1858:
1859: wfd = *wfdp; *wfdp = 0;
1860:
1861: }
1862:
1863: else
1864:
1865: wfd = 0;
1866:
1867:
1868:
1.1.1.2 ! root 1869: TRACE(("Fselect(%u, %lx, %lx)", timeout, rfd, wfd));
1.1 root 1870:
1871: p = curproc; /* help the optimizer out */
1872:
1873:
1874:
1875: /* first, validate the masks */
1876:
1877: mask = 1L;
1878:
1879: for (i = 0; i < MAX_OPEN; i++) {
1880:
1881: if ( ((rfd & mask) || (wfd & mask)) && !(p->handle[i]) ) {
1882:
1.1.1.2 ! root 1883: DEBUG(("Fselect: invalid handle"));
1.1 root 1884:
1885: return EIHNDL;
1886:
1887: }
1888:
1889: mask = mask << 1L;
1890:
1891: }
1892:
1893:
1894:
1895: /* now, loop through the file descriptors, setting up the select process */
1896:
1897: /* NOTE: wakeselect will set p->wait_cond to 0 if data arrives during the
1898:
1899: * selection
1900:
1901: * Also note: because of the validation above, we may assume that the
1902:
1903: * file handles are valid here. However, this assumption may no longer
1904:
1905: * be true after we've gone to sleep, since a signal handler may have
1906:
1907: * closed one of the handles.
1908:
1909: */
1910:
1911:
1912:
1913: mask = 1L;
1914:
1915: count = 0;
1916:
1.1.1.2 ! root 1917: curproc->wait_cond = (long)wakeselect; /* flag */
1.1 root 1918:
1919:
1920:
1921: for (i = 0; i < MAX_OPEN; i++) {
1922:
1923: if (rfd & mask) {
1924:
1925: f = p->handle[i];
1926:
1927: if ((*f->dev->select)(f, (long)p, O_RDONLY)) {
1928:
1929: count++;
1930:
1931: *rfdp |= mask;
1932:
1933: }
1934:
1935: }
1936:
1937: if (wfd & mask) {
1938:
1939: f = p->handle[i];
1940:
1941: if ((*f->dev->select)(f, (long)p, O_WRONLY)) {
1942:
1943: count++;
1944:
1945: *wfdp |= mask;
1946:
1947: }
1948:
1949: }
1950:
1951: mask = mask << 1L;
1952:
1953: }
1954:
1955:
1956:
1957: if (count == 0) {
1958:
1959: /* OK, now let's set a timeout */
1960:
1961:
1962:
1963: if (timeout) {
1964:
1965: t = addtimeout((long)timeout, unselectme);
1966:
1967: } else {
1968:
1969: t = 0;
1970:
1971: }
1972:
1973:
1974:
1975: /* curproc->wait_cond changes when data arrives or the timeout happens */
1976:
1.1.1.2 ! root 1977: while (curproc->wait_cond == (long)wakeselect) {
1.1 root 1978:
1.1.1.2 ! root 1979: TRACE(("sleeping in Fselect"));
1.1 root 1980:
1.1.1.2 ! root 1981: sleep(SELECT_Q, (long)wakeselect);
1.1 root 1982:
1983: }
1984:
1985:
1986:
1987: /* we can cancel the time out now (if it hasn't already happened) */
1988:
1989: if (t) canceltimeout(t);
1990:
1991:
1992:
1993: /* OK, let's see what data arrived (if any) */
1994:
1995: mask = 1L;
1996:
1997: for (i = 0; i < MAX_OPEN; i++) {
1998:
1999: if (rfd & mask) {
2000:
2001: f = p->handle[i];
2002:
2003: if (f) {
2004:
2005: bytes = 1L;
2006:
2007: (void)(*f->dev->ioctl)(f, FIONREAD,&bytes);
2008:
2009: if (bytes > 0) {
2010:
2011: *rfdp |= mask;
2012:
2013: count++;
2014:
2015: }
2016:
2017: }
2018:
2019: }
2020:
2021: if (wfd & mask) {
2022:
2023: f = p->handle[i];
2024:
2025: if (f) {
2026:
2027: bytes = 1L;
2028:
2029: (void)(*f->dev->ioctl)(f, FIONWRITE,&bytes);
2030:
2031: if (bytes > 0) {
2032:
2033: *wfdp |= mask;
2034:
2035: count++;
2036:
2037: }
2038:
2039: }
2040:
2041: }
2042:
2043: mask = mask << 1L;
2044:
2045: }
2046:
2047: }
2048:
2049:
2050:
2051: /* at this point, we either have data or a time out */
2052:
2053: /* cancel all the selects */
2054:
2055: mask = 1L;
2056:
2057:
2058:
2059: for (i = 0; i < MAX_OPEN; i++) {
2060:
2061: if (rfd & mask) {
2062:
2063: f = p->handle[i];
2064:
2065: if (f)
2066:
2067: (*f->dev->unselect)(f, (long)p, O_RDONLY);
2068:
2069: }
2070:
2071: if (wfd & mask) {
2072:
2073: f = p->handle[i];
2074:
2075: if (f)
2076:
2077: (*f->dev->unselect)(f, (long)p, O_WRONLY);
2078:
2079: }
2080:
2081: mask = mask << 1L;
2082:
2083: }
2084:
2085:
2086:
1.1.1.2 ! root 2087: TRACE(("Fselect: returning %d", count));
1.1 root 2088:
2089: return count;
2090:
2091: }
2092:
2093:
2094:
2095:
2096:
2097: /*
2098:
2099: * GEMDOS extension: Fmidipipe
2100:
2101: * Fmidipipe(pid, in, out) manipultes the MIDI file handles (handles -4 and -5)
2102:
2103: * of process "pid" so that they now point to the files with handles "in" and
2104:
2105: * "out" in the calling process
2106:
2107: */
2108:
2109:
2110:
1.1.1.2 ! root 2111: long ARGS_ON_STACK
1.1 root 2112:
2113: f_midipipe(pid, in, out)
2114:
2115: int pid, in, out;
2116:
2117: {
2118:
2119: PROC *p;
2120:
2121: FILEPTR *fin, *fout;
2122:
2123:
2124:
2125: /* first, find the process */
2126:
2127:
2128:
2129: if (pid == 0)
2130:
2131: p = curproc;
2132:
2133: else {
2134:
2135: p = pid2proc(pid);
2136:
2137: if (!p)
2138:
2139: return EFILNF;
2140:
2141: }
2142:
2143:
2144:
2145: /* next, validate the input and output file handles */
2146:
1.1.1.2 ! root 2147: if (in < MIN_HANDLE || in >= MAX_OPEN || (0==(fin = curproc->handle[in])))
1.1 root 2148:
2149: return EIHNDL;
2150:
2151: if ( (fin->flags & O_RWMODE) == O_WRONLY ) {
2152:
1.1.1.2 ! root 2153: DEBUG(("Fmidipipe: input side is write only"));
1.1 root 2154:
2155: return EACCDN;
2156:
2157: }
2158:
1.1.1.2 ! root 2159: if (out < MIN_HANDLE || out >= MAX_OPEN || (0==(fout = curproc->handle[out])))
1.1 root 2160:
2161: return EIHNDL;
2162:
2163: if ( (fout->flags & O_RWMODE) == O_RDONLY ) {
2164:
1.1.1.2 ! root 2165: DEBUG(("Fmidipipe: output side is read only"));
1.1 root 2166:
2167: return EACCDN;
2168:
2169: }
2170:
2171:
2172:
2173: /* OK, duplicate the handles and put them in the new process */
2174:
2175: fin->links++; fout->links++;
2176:
2177: (void)do_pclose(p, p->midiin);
2178:
2179: (void)do_pclose(p, p->midiout);
2180:
2181: p->midiin = fin; p->midiout = fout;
2182:
2183: return 0;
2184:
2185: }
2186:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.