Annotation of MiNT/src/dosfile.c, revision 1.1

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: 
        !            75:        TRACE("do_open(%s)", name);
        !            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: 
        !            91:                mint_errno = r;
        !            92: 
        !            93:                DEBUG("do_open(%s): error %ld", name, r);
        !            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: 
        !           119:                DEBUG("do_open(%s): file already exists",name);
        !           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: 
        !           149:                        DEBUG("do_open(%s): couldn't get "
        !           150: 
        !           151:                              "write permission on directory",name);
        !           152: 
        !           153:                        mint_errno = r;
        !           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: 
        !           165:                        DEBUG("do_open(%s): error %ld while creating file",
        !           166: 
        !           167:                                name, r);
        !           168: 
        !           169:                        mint_errno = r;
        !           170: 
        !           171:                        return NULL;
        !           172: 
        !           173:                }
        !           174: 
        !           175:                creating = 1;
        !           176: 
        !           177:        } else if (r) {
        !           178: 
        !           179:                DEBUG("do_open(%s): error %ld while searching for file",
        !           180: 
        !           181:                        name, r);
        !           182: 
        !           183:                mint_errno = r;
        !           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: 
        !           205:                DEBUG("do_open(%s): couldn't get file attributes",name);
        !           206: 
        !           207:                mint_errno = r;
        !           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: 
        !           221:                DEBUG("do_open(%s): file is a directory",name);
        !           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: 
        !           267:                DEBUG("do_open(%s): access to file denied",name);
        !           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: 
        !           293:                        DEBUG("do_open(%s): can't write a read-only file",
        !           294: 
        !           295:                                name);
        !           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: 
        !           343:                mint_errno = devsp;
        !           344: 
        !           345:                DEBUG("do_open(%s): device driver not found",name);
        !           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: 
        !           371:        if (!(f = new_fileptr())) {
        !           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: 
        !           397:                DEBUG("do_open(%s): device open failed with error %ld",
        !           398: 
        !           399:                        name, r);
        !           400: 
        !           401:                mint_errno = r;
        !           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: 
        !           481:  * (this is just in case we were killed by a signal
        !           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: 
        !           537:                        DEBUG("close: device close failed");
        !           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: 
        !           569: long
        !           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: 
        !           587:        TRACE("Fopen(%s, %x)", name, mode);
        !           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: 
        !           615:        DEBUG("Fopen(%s): process out of handles",name);
        !           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: 
        !           675:        TRACE("Fopen: returning %d", i);
        !           676: 
        !           677:        return i;
        !           678: 
        !           679: }
        !           680: 
        !           681: 
        !           682: 
        !           683: long
        !           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: 
        !           707:        TRACE("Fcreate(%s, %x)", name, attrib);
        !           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: 
        !           737:        DEBUG("Fcreate(%s): process out of handles",name);
        !           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: 
        !           775:                DEBUG("Fcreate(%s,%x): illegal attributes",name,attrib);
        !           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: 
        !           789:                DEBUG("Fcreate(%s) failed, error %d", name, mint_errno);
        !           790: 
        !           791:                return mint_errno;
        !           792: 
        !           793:        }
        !           794: 
        !           795:        proc->handle[i] = f;
        !           796: 
        !           797:        i += offset;
        !           798: 
        !           799:        TRACE("Fcreate: returning %d", i);
        !           800: 
        !           801:        return i;
        !           802: 
        !           803: }
        !           804: 
        !           805: 
        !           806: 
        !           807: long
        !           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: 
        !           823:        TRACE("Fclose: %d", fh);
        !           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: 
        !           843:        if (fh < 0 || fh >= MAX_OPEN || !(f = proc->handle[fh])) {
        !           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: 
        !           887: long
        !           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: 
        !           925:        if (fh < MIN_HANDLE || fh >= MAX_OPEN || !(f = proc->handle[fh])) {
        !           926: 
        !           927:                DEBUG("Fread: invalid handle: %d", fh);
        !           928: 
        !           929:                return EIHNDL;
        !           930: 
        !           931:        }
        !           932: 
        !           933:        if ( (f->flags & O_RWMODE) == O_WRONLY ) {
        !           934: 
        !           935:                DEBUG("Fread: read on a write-only handle");
        !           936: 
        !           937:                return EACCDN;
        !           938: 
        !           939:        }
        !           940: 
        !           941:        if (is_terminal(f))
        !           942: 
        !           943:                return tty_read(f, buf, count);
        !           944: 
        !           945: 
        !           946: 
        !           947:        TRACE("Fread: %ld bytes from handle %d", count, fh);
        !           948: 
        !           949:        return (*f->dev->read)(f, buf, count);
        !           950: 
        !           951: }
        !           952: 
        !           953: 
        !           954: 
        !           955: long
        !           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: 
        !           993:        if (fh < MIN_HANDLE || fh >= MAX_OPEN || !(f = proc->handle[fh])) {
        !           994: 
        !           995:                DEBUG("Fwrite: bad handle: %d", fh);
        !           996: 
        !           997:                return EIHNDL;
        !           998: 
        !           999:        }
        !          1000: 
        !          1001:        if ( (f->flags & O_RWMODE) == O_RDONLY ) {
        !          1002: 
        !          1003:                DEBUG("Fwrite: write on a read-only handle");
        !          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: 
        !          1031:                TRACE("Fwrite: %ld bytes to handle %d", count, fh);
        !          1032: 
        !          1033:                r = (*f->dev->write)(f, buf, count);
        !          1034: 
        !          1035:        }
        !          1036: 
        !          1037:        if (r < 0) {
        !          1038: 
        !          1039:                DEBUG("Fwrite: error %ld", r);
        !          1040: 
        !          1041:        }
        !          1042: 
        !          1043:        return r;
        !          1044: 
        !          1045: }
        !          1046: 
        !          1047: 
        !          1048: 
        !          1049: long
        !          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: 
        !          1067:        TRACE("Fseek(%ld, %d) on handle %d", place, how, fh);
        !          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: 
        !          1087:        if (fh < MIN_HANDLE || fh >= MAX_OPEN || !(f = proc->handle[fh])) {
        !          1088: 
        !          1089:                DEBUG("Fseek: bad handle: %d", fh);
        !          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: 
        !          1157:        if (fh < MIN_HANDLE || fh >= MAX_OPEN || !(f = proc->handle[fh]))
        !          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: 
        !          1189: long
        !          1190: 
        !          1191: f_dup(fh)
        !          1192: 
        !          1193:        int fh;
        !          1194: 
        !          1195: {
        !          1196: 
        !          1197:        long r;
        !          1198: 
        !          1199:        r = do_dup(fh, MIN_OPEN);
        !          1200: 
        !          1201:        TRACE("Fdup(%d) -> %ld", fh, r);
        !          1202: 
        !          1203:        return r;
        !          1204: 
        !          1205: }
        !          1206: 
        !          1207: 
        !          1208: 
        !          1209: long
        !          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: 
        !          1225:        TRACE("Fforce(%d, %d)", newh, oldh);
        !          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: 
        !          1247:            !(f = proc->handle[oldh])) {
        !          1248: 
        !          1249:                DEBUG("Fforce: old handle invalid");
        !          1250: 
        !          1251:                return EIHNDL;
        !          1252: 
        !          1253:        }
        !          1254: 
        !          1255: 
        !          1256: 
        !          1257:        if (newh < MIN_HANDLE || newh >= MAX_OPEN) {
        !          1258: 
        !          1259:                DEBUG("Fforce: new handle out of range");
        !          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: 
        !          1301: long
        !          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: 
        !          1319:        TRACE("Fdatime(%d)", fh);
        !          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: 
        !          1339:        if (fh < MIN_HANDLE || fh >= MAX_OPEN || !(f = proc->handle[fh])) {
        !          1340: 
        !          1341:                DEBUG("Fdatime: invalid handle");
        !          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: 
        !          1363: long
        !          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: 
        !          1399:        if (fh < MIN_HANDLE || fh >= MAX_OPEN || !(f = proc->handle[fh])) {
        !          1400: 
        !          1401:                DEBUG("Flock: invalid handle");
        !          1402: 
        !          1403:                return EIHNDL;
        !          1404: 
        !          1405:        }
        !          1406: 
        !          1407:        TRACE("Flock(%d,%d,%ld,%ld)", fh, mode, start, length);
        !          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: 
        !          1457: long
        !          1458: 
        !          1459: f_pipe(usrh)
        !          1460: 
        !          1461:        short *usrh;
        !          1462: 
        !          1463: {
        !          1464: 
        !          1465:        extern FILESYS pipe_filesys;
        !          1466: 
        !          1467:        FILESYS *fs;
        !          1468: 
        !          1469:        FILEPTR *in, *out;
        !          1470: 
        !          1471:        static int pipeno = 0;
        !          1472: 
        !          1473:        int i, j;
        !          1474: 
        !          1475:        char pipename[32]; /* MAGIC: 32 >= strlen "u:\pipe\sys$pipe.000\0" */
        !          1476: 
        !          1477: 
        !          1478: 
        !          1479:        TRACE("Fpipe");
        !          1480: 
        !          1481:        fs = &pipe_filesys;
        !          1482: 
        !          1483: 
        !          1484: 
        !          1485: /* BUG: more than 999 open pipes hangs the system */
        !          1486: 
        !          1487:        do {
        !          1488: 
        !          1489:                ksprintf(pipename, "u:\\pipe\\sys$pipe.%03d", pipeno);
        !          1490: 
        !          1491:                pipeno++; if (pipeno > 999) pipeno = 0;
        !          1492: 
        !          1493:                out = do_open(pipename, O_WRONLY|O_CREAT|O_EXCL, 3, (XATTR *)0);
        !          1494: 
        !          1495:                        /* read-only attribute means unidirectional fifo */
        !          1496: 
        !          1497:                        /* hidden attribute means check for broken pipes */
        !          1498: 
        !          1499:        } while (out == 0 && mint_errno == EACCDN);
        !          1500: 
        !          1501: 
        !          1502: 
        !          1503:        if (!out) {
        !          1504: 
        !          1505:                DEBUG("Fpipe: error %d", mint_errno);
        !          1506: 
        !          1507:                return mint_errno;
        !          1508: 
        !          1509:        }
        !          1510: 
        !          1511: 
        !          1512: 
        !          1513:        in = do_open(pipename, O_RDONLY, 0, (XATTR *)0);
        !          1514: 
        !          1515:        if (!in) {
        !          1516: 
        !          1517:                DEBUG("Fpipe: in side of pipe not opened (error %d)",
        !          1518: 
        !          1519:                        mint_errno);
        !          1520: 
        !          1521:                (void)do_close(out);
        !          1522: 
        !          1523:                return mint_errno;
        !          1524: 
        !          1525:        }
        !          1526: 
        !          1527: 
        !          1528: 
        !          1529:        for (i = MIN_OPEN; i < MAX_OPEN; i++) {
        !          1530: 
        !          1531:                if (curproc->handle[i] == 0)
        !          1532: 
        !          1533:                        break;
        !          1534: 
        !          1535:        }
        !          1536: 
        !          1537: 
        !          1538: 
        !          1539:        for (j = i+1; j < MAX_OPEN; j++) {
        !          1540: 
        !          1541:                if (curproc->handle[j] == 0)
        !          1542: 
        !          1543:                        break;
        !          1544: 
        !          1545:        }
        !          1546: 
        !          1547: 
        !          1548: 
        !          1549:        if (j >= MAX_OPEN) {
        !          1550: 
        !          1551:                DEBUG("Fpipe: not enough handles left");
        !          1552: 
        !          1553:                (void) do_close(in);
        !          1554: 
        !          1555:                (void) do_close(out);
        !          1556: 
        !          1557:                return ENHNDL;
        !          1558: 
        !          1559:        }
        !          1560: 
        !          1561:        curproc->handle[i] = in; curproc->handle[j] = out;
        !          1562: 
        !          1563: /* leave pipes open across Pexec */
        !          1564: 
        !          1565:        curproc->fdflags[i] = 0;
        !          1566: 
        !          1567:        curproc->fdflags[j] = 0;
        !          1568: 
        !          1569: 
        !          1570: 
        !          1571:        usrh[0] = i;
        !          1572: 
        !          1573:        usrh[1] = j;
        !          1574: 
        !          1575:        TRACE("Fpipe: returning 0: input %d output %d",i,j);
        !          1576: 
        !          1577:        return 0;
        !          1578: 
        !          1579: }
        !          1580: 
        !          1581: 
        !          1582: 
        !          1583: /*
        !          1584: 
        !          1585:  * f_cntl: a combination "ioctl" and "fcntl". Some functions are
        !          1586: 
        !          1587:  * handled here, if they apply to the file descriptors directly
        !          1588: 
        !          1589:  * (e.g. F_DUPFD) or if they're easily translated into file system
        !          1590: 
        !          1591:  * functions (e.g. FSTAT). Others are passed on to the device driver
        !          1592: 
        !          1593:  * via dev->ioctl.
        !          1594: 
        !          1595:  */
        !          1596: 
        !          1597: 
        !          1598: 
        !          1599: long
        !          1600: 
        !          1601: f_cntl(fh, arg, cmd)
        !          1602: 
        !          1603:        int fh;
        !          1604: 
        !          1605:        long arg;
        !          1606: 
        !          1607:        int cmd;
        !          1608: 
        !          1609: {
        !          1610: 
        !          1611:        FILEPTR *f;
        !          1612: 
        !          1613:        PROC *proc;
        !          1614: 
        !          1615:        struct flock *fl;
        !          1616: 
        !          1617:        long r;
        !          1618: 
        !          1619: 
        !          1620: 
        !          1621:        TRACE("Fcntl(%d, cmd=0x%x)", fh, cmd);
        !          1622: 
        !          1623: #if O_GLOBAL
        !          1624: 
        !          1625:        if (fh >= 100) {
        !          1626: 
        !          1627:            fh -= 100;
        !          1628: 
        !          1629:            proc = rootproc;
        !          1630: 
        !          1631:        }
        !          1632: 
        !          1633:        else
        !          1634: 
        !          1635: #endif
        !          1636: 
        !          1637:            proc = curproc;
        !          1638: 
        !          1639: 
        !          1640: 
        !          1641:        if (fh < MIN_HANDLE || fh >= MAX_OPEN) {
        !          1642: 
        !          1643:                DEBUG("Fcntl: bad file handle");
        !          1644: 
        !          1645:                return EIHNDL;
        !          1646: 
        !          1647:        }
        !          1648: 
        !          1649: 
        !          1650: 
        !          1651:        if (cmd == F_DUPFD) {
        !          1652: 
        !          1653: #if O_GLOBAL
        !          1654: 
        !          1655:                if (proc != curproc) fh += 100;
        !          1656: 
        !          1657: #endif
        !          1658: 
        !          1659:                return do_dup(fh, (int)arg);
        !          1660: 
        !          1661:        }
        !          1662: 
        !          1663: 
        !          1664: 
        !          1665:        f = proc->handle[fh];
        !          1666: 
        !          1667:        if (!f) return EIHNDL;
        !          1668: 
        !          1669: 
        !          1670: 
        !          1671:        switch(cmd) {
        !          1672: 
        !          1673:        case F_GETFD:
        !          1674: 
        !          1675:                TRACE("Fcntl F_GETFD");
        !          1676: 
        !          1677:                if (fh < 0) return EIHNDL;
        !          1678: 
        !          1679:                return proc->fdflags[fh];
        !          1680: 
        !          1681:        case F_SETFD:
        !          1682: 
        !          1683:                TRACE("Fcntl F_SETFD");
        !          1684: 
        !          1685:                if (fh < 0) return EIHNDL;
        !          1686: 
        !          1687:                proc->fdflags[fh] = arg;
        !          1688: 
        !          1689:                return 0;
        !          1690: 
        !          1691:        case F_GETFL:
        !          1692: 
        !          1693:                TRACE("Fcntl F_GETFL");
        !          1694: 
        !          1695:                return f->flags & O_USER;
        !          1696: 
        !          1697:        case F_SETFL:
        !          1698: 
        !          1699:                TRACE("Fcntl F_SETFL");
        !          1700: 
        !          1701:                arg &= O_USER;          /* make sure only user bits set */
        !          1702: 
        !          1703:        /* COMPATIBILITY WITH OLD VERSIONS ONLY */
        !          1704: 
        !          1705:        /* THIS CODE WILL GO AWAY. REALLY! */
        !          1706: 
        !          1707:                if (arg & 4) {
        !          1708: 
        !          1709:                        arg |= O_NDELAY;
        !          1710: 
        !          1711:                        arg &= ~4;
        !          1712: 
        !          1713:                }
        !          1714: 
        !          1715: 
        !          1716: 
        !          1717:        /* make sure the file access and sharing modes are not changed */
        !          1718: 
        !          1719:                arg &= ~(O_RWMODE|O_SHMODE);
        !          1720: 
        !          1721:                arg |= f->flags & (O_RWMODE|O_SHMODE);
        !          1722: 
        !          1723:                f->flags &= ~O_USER;    /* set user bits to arg */
        !          1724: 
        !          1725:                f->flags |= arg;
        !          1726: 
        !          1727:                return 0;
        !          1728: 
        !          1729:        case FSTAT:
        !          1730: 
        !          1731:                return (*f->fc.fs->getxattr)(&f->fc, (XATTR *)arg);
        !          1732: 
        !          1733:        case F_SETLK:
        !          1734: 
        !          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: 
        !          1757:                TRACE("Fcntl mode %x: calling ioctl",cmd);
        !          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: 
        !          1819: long
        !          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: 
        !          1843:        if (rfdp) {
        !          1844: 
        !          1845:                rfd = *rfdp; *rfdp = 0;
        !          1846: 
        !          1847:        }
        !          1848: 
        !          1849:        else
        !          1850: 
        !          1851:                rfd = 0;
        !          1852: 
        !          1853:        if (wfdp) {
        !          1854: 
        !          1855:                wfd = *wfdp; *wfdp = 0;
        !          1856: 
        !          1857:        }
        !          1858: 
        !          1859:        else
        !          1860: 
        !          1861:                wfd = 0;
        !          1862: 
        !          1863: 
        !          1864: 
        !          1865:        TRACE("Fselect(%u, %lx, %lx)", timeout, rfd, wfd);
        !          1866: 
        !          1867:        p = curproc;                    /* help the optimizer out */
        !          1868: 
        !          1869: 
        !          1870: 
        !          1871:        /* first, validate the masks */
        !          1872: 
        !          1873:        mask = 1L;
        !          1874: 
        !          1875:        for (i = 0; i < MAX_OPEN; i++) {
        !          1876: 
        !          1877:                if ( ((rfd & mask) || (wfd & mask)) && !(p->handle[i]) ) {
        !          1878: 
        !          1879:                        DEBUG("Fselect: invalid handle");
        !          1880: 
        !          1881:                        return EIHNDL;
        !          1882: 
        !          1883:                }
        !          1884: 
        !          1885:                mask = mask << 1L;
        !          1886: 
        !          1887:        }
        !          1888: 
        !          1889: 
        !          1890: 
        !          1891: /* now, loop through the file descriptors, setting up the select process */
        !          1892: 
        !          1893: /* NOTE: wakeselect will set p->wait_cond to 0 if data arrives during the
        !          1894: 
        !          1895:  * selection
        !          1896: 
        !          1897:  * Also note: because of the validation above, we may assume that the
        !          1898: 
        !          1899:  * file handles are valid here. However, this assumption may no longer
        !          1900: 
        !          1901:  * be true after we've gone to sleep, since a signal handler may have
        !          1902: 
        !          1903:  * closed one of the handles.
        !          1904: 
        !          1905:  */
        !          1906: 
        !          1907: 
        !          1908: 
        !          1909:        mask = 1L;
        !          1910: 
        !          1911:        count = 0;
        !          1912: 
        !          1913:        curproc->wait_cond = (long)&wakeselect;         /* flag */
        !          1914: 
        !          1915: 
        !          1916: 
        !          1917:        for (i = 0; i < MAX_OPEN; i++) {
        !          1918: 
        !          1919:                if (rfd & mask) {
        !          1920: 
        !          1921:                        f = p->handle[i];
        !          1922: 
        !          1923:                        if ((*f->dev->select)(f, (long)p, O_RDONLY)) {
        !          1924: 
        !          1925:                                count++;
        !          1926: 
        !          1927:                                *rfdp |= mask;
        !          1928: 
        !          1929:                        }
        !          1930: 
        !          1931:                }
        !          1932: 
        !          1933:                if (wfd & mask) {
        !          1934: 
        !          1935:                        f = p->handle[i];
        !          1936: 
        !          1937:                        if ((*f->dev->select)(f, (long)p, O_WRONLY)) {
        !          1938: 
        !          1939:                                count++;
        !          1940: 
        !          1941:                                *wfdp |= mask;
        !          1942: 
        !          1943:                        }
        !          1944: 
        !          1945:                }
        !          1946: 
        !          1947:                mask = mask << 1L;
        !          1948: 
        !          1949:        }
        !          1950: 
        !          1951: 
        !          1952: 
        !          1953:        if (count == 0) {
        !          1954: 
        !          1955:                /* OK, now let's set a timeout */
        !          1956: 
        !          1957: 
        !          1958: 
        !          1959:                if (timeout) {
        !          1960: 
        !          1961:                        t = addtimeout((long)timeout, unselectme);
        !          1962: 
        !          1963:                } else {
        !          1964: 
        !          1965:                        t = 0;
        !          1966: 
        !          1967:                }
        !          1968: 
        !          1969: 
        !          1970: 
        !          1971:        /* curproc->wait_cond changes when data arrives or the timeout happens */
        !          1972: 
        !          1973:                while (curproc->wait_cond == (long)&wakeselect) {
        !          1974: 
        !          1975:                        TRACE("sleeping in Fselect");
        !          1976: 
        !          1977:                        sleep(SELECT_Q, (long)&wakeselect);
        !          1978: 
        !          1979:                }
        !          1980: 
        !          1981: 
        !          1982: 
        !          1983:        /* we can cancel the time out now (if it hasn't already happened) */
        !          1984: 
        !          1985:                if (t) canceltimeout(t);
        !          1986: 
        !          1987: 
        !          1988: 
        !          1989:        /* OK, let's see what data arrived (if any) */
        !          1990: 
        !          1991:                mask = 1L;
        !          1992: 
        !          1993:                for (i = 0; i < MAX_OPEN; i++) {
        !          1994: 
        !          1995:                        if (rfd & mask) {
        !          1996: 
        !          1997:                                f = p->handle[i];
        !          1998: 
        !          1999:                                if (f) {
        !          2000: 
        !          2001:                                    bytes = 1L;
        !          2002: 
        !          2003:                                    (void)(*f->dev->ioctl)(f, FIONREAD,&bytes);
        !          2004: 
        !          2005:                                    if (bytes > 0) {
        !          2006: 
        !          2007:                                        *rfdp |= mask;
        !          2008: 
        !          2009:                                        count++;
        !          2010: 
        !          2011:                                    }
        !          2012: 
        !          2013:                                }
        !          2014: 
        !          2015:                        }
        !          2016: 
        !          2017:                        if (wfd & mask) {
        !          2018: 
        !          2019:                                f = p->handle[i];
        !          2020: 
        !          2021:                                if (f) {
        !          2022: 
        !          2023:                                    bytes = 1L;
        !          2024: 
        !          2025:                                    (void)(*f->dev->ioctl)(f, FIONWRITE,&bytes);
        !          2026: 
        !          2027:                                    if (bytes > 0) {
        !          2028: 
        !          2029:                                        *wfdp |= mask;
        !          2030: 
        !          2031:                                        count++;
        !          2032: 
        !          2033:                                    }
        !          2034: 
        !          2035:                                }
        !          2036: 
        !          2037:                        }
        !          2038: 
        !          2039:                        mask = mask << 1L;
        !          2040: 
        !          2041:                }
        !          2042: 
        !          2043:        } else {
        !          2044: 
        !          2045: /*             TRACE("Fselect: data already present (count == %d)", count); */
        !          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: 
        !          2087:        TRACE("Fselect: returning %d", count);
        !          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: 
        !          2111: long
        !          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: 
        !          2147:        if (in < MIN_HANDLE || in >= MAX_OPEN || (!(fin = curproc->handle[in])))
        !          2148: 
        !          2149:                return EIHNDL;
        !          2150: 
        !          2151:        if ( (fin->flags & O_RWMODE) == O_WRONLY ) {
        !          2152: 
        !          2153:                DEBUG("Fmidipipe: input side is write only");
        !          2154: 
        !          2155:                return EACCDN;
        !          2156: 
        !          2157:        }
        !          2158: 
        !          2159:        if (out < MIN_HANDLE || out >= MAX_OPEN || (!(fout = curproc->handle[out])))
        !          2160: 
        !          2161:                return EIHNDL;
        !          2162: 
        !          2163:        if ( (fout->flags & O_RWMODE) == O_RDONLY ) {
        !          2164: 
        !          2165:                DEBUG("Fmidipipe: output side is read only");
        !          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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.