Annotation of 43BSD/contrib/apl/src/ay.c, revision 1.1

1.1     ! root        1: static char Sccsid[] = "ay.c @(#)ay.c  1.1     10/1/82 Berkeley ";
        !             2: #
        !             3: 
        !             4: /*
        !             5:  *      APL Buffered I/O routines
        !             6:  *
        !             7:  *
        !             8:  * The following routines perform all of the I/O required by APL.
        !             9:  * They are designed to maximize buffer utilization while maintaining
        !            10:  * reliable operation.  For a machine such as the PDP-11, the number
        !            11:  * of buffers, defined in apl.h, should be around 4 for best results.
        !            12:  * For a machine such as the VAX 11/780, a larger number may be desirable
        !            13:  * for better results.
        !            14:  *
        !            15:  */
        !            16: 
        !            17: #include "apl.h"                /* Header definitions */
        !            18: #ifdef NBUF                     /* Don't do any of this unless buffering
        !            19:                                 * was requested by defining NBUF
        !            20:                                 */
        !            21: 
        !            22: #define        realfd(x)       files[x].fd_dup
        !            23: 
        !            24: openf(fname, mode)
        !            25: char *fname;
        !            26: {
        !            27: 
        !            28:        int fd;
        !            29: 
        !            30: 
        !            31:        /* The first order of business is to open the
        !            32:         * file.  If this fails, return -1.
        !            33:         */
        !            34: 
        !            35:        if ((fd=open(fname,mode)) < 0) return(fd);
        !            36: 
        !            37: 
        !            38:        /* Now, perform all of the work necessary for setting
        !            39:         * up the file tables.  This code is shared by "openf"
        !            40:         * and "creatf" since both open files.
        !            41:         */
        !            42: 
        !            43:        openup(fd);
        !            44:        return(fd);
        !            45: }
        !            46: 
        !            47: creatf(fname, mode)
        !            48: char *fname;
        !            49: {
        !            50: 
        !            51:        int fd;
        !            52: 
        !            53: 
        !            54:        /* The first order of business is to create the
        !            55:         * file.  If this fails, return -1.
        !            56:         */
        !            57: 
        !            58:        if ((fd=creat(fname,mode)) < 0) return(fd);
        !            59: 
        !            60: 
        !            61:        /* Now, perform all of the work necessary for setting
        !            62:         * up the file tables.  This code is shared by "openf"
        !            63:         * and "creatf" since both open files.
        !            64:         */
        !            65: 
        !            66:        openup(fd);
        !            67:        return(fd);
        !            68: }
        !            69: 
        !            70: openup(fd)
        !            71: {
        !            72:        struct stat stat_buf;
        !            73:        register struct fds *p, *q;
        !            74:        register j;
        !            75: 
        !            76: 
        !            77:        /* Try to perform an "fstat" call on the file.  This
        !            78:         * information is required for all file descriptors
        !            79:         * to prevent reading from a file while data destined
        !            80:         * for that file is still buffered for output.  If for
        !            81:         * some reason the "fstat" fails, arbitrarily set
        !            82:         * the major/minor number and inode number to zero.
        !            83:         */
        !            84: 
        !            85:        if (fstat(fd, &stat_buf) < 0){
        !            86:                write(2, "Can't \"stat\" new fd\n", 20);
        !            87:                stat_buf.st_dev = 0;
        !            88:                stat_buf.st_ino = 0;
        !            89:        }
        !            90: 
        !            91: 
        !            92:        /* Copy the information into the "files" structure, which
        !            93:         * maintains such data on all open files.
        !            94:         */
        !            95: 
        !            96:        p = &files[fd];
        !            97:        p->fd_dev = stat_buf.st_dev;    /* Major/minor device numbers */
        !            98:        p->fd_ind = stat_buf.st_ino;    /* Inode number */
        !            99:        p->fd_open = 1;                 /* File is open */
        !           100:        p->fd_buf = -1;                 /* No buffer is currently assigned */
        !           101:        p->fd_dup = fd;                 /* All it duplicates is itself */
        !           102:        p->fd_lastop = 0;               /* Lastop was read (default) */
        !           103:        p->fd_pipe = !!lseek(fd, 0L, 1);        /* Seek will fail if a pipe */
        !           104: 
        !           105: 
        !           106:        /* Determine if the new fd is unique or not.  If not,
        !           107:         * make sure any matching fd's know that they no longer
        !           108:         * are either.
        !           109:         */
        !           110: 
        !           111:        p->fd_uniq = 1;                 /* Assume uniqueness */
        !           112:        for(j=0; j<NFDS; j++){
        !           113:                if (!files[j].fd_open) continue;        /* File not open */
        !           114: 
        !           115:                q = &files[realfd(j)];
        !           116:                if (p->fd_ind == q->fd_ind && p->fd_dev == q->fd_dev)
        !           117:                        p->fd_uniq = q->fd_uniq = 0;
        !           118:        }
        !           119:        check();                                        /*DEBUG*/
        !           120: }
        !           121: 
        !           122: dupf(fd)
        !           123: {
        !           124: 
        !           125:        int fd2;
        !           126:        register struct fds *p, *q;
        !           127: 
        !           128: 
        !           129:        /* Duplicating a file descriptor does not require an "fstat"
        !           130:         * on the new file descriptor, because its device and inode
        !           131:         * are already recorded.  However, duplicate file descriptors
        !           132:         * complicate I/O because they MUST be linked to the same
        !           133:         * buffer.
        !           134:         */
        !           135: 
        !           136:        if ((fd2=dup(fd)) < 0) return(fd2);     /* Get new fd */
        !           137: 
        !           138:        /* Copy all of the information into the "files" for the new
        !           139:         * file descriptor.  The uniqueness of the original fd is copied
        !           140:         * to the new fd -- they both represent the same thing.
        !           141:         */
        !           142: 
        !           143:        p = &files[fd];                 /* Point to appropriate places */
        !           144:        q = &files[fd2];
        !           145: 
        !           146:        q->fd_dev = p->fd_dev;          /* Major/minor device number */
        !           147:        q->fd_ind = p->fd_ind;          /* Inode number */
        !           148:        q->fd_buf = -1;                 /* Buffer is assigned to princ. fd */
        !           149:        q->fd_uniq = p->fd_uniq;        /* Uniqueness of dev/inode */
        !           150:        q->fd_dup = p->fd_dup;          /* Point new entry to old one */
        !           151:        q->fd_open = 1;                 /* File is now open */
        !           152:        q->fd_lastop = p->fd_lastop;    /* Last operation is the same */
        !           153: 
        !           154:        return(fd2);                    /* Return new fd */
        !           155: }
        !           156: 
        !           157: closef(fd)
        !           158: {
        !           159: 
        !           160:        register j;
        !           161:        register struct fds *p, *q;
        !           162:        int fd2, count;
        !           163: 
        !           164:        /* Closing a file is easier than opening it, but some precautions
        !           165:         * are necessary.  For instance, if a "dup" was performed to
        !           166:         * obtain some new file descriptor and the original file is
        !           167:         * now being closed, the duplicated file must retain all
        !           168:         * pertinent information.  Thus, the first order of business
        !           169:         * is to scan the list of file descriptors for duplicates.
        !           170:         */
        !           171: 
        !           172:        p = &files[fd];                 /* Entry for dying fd */
        !           173: 
        !           174:        count = 0;                      /* Number of remaining dups */
        !           175:        fd2 = -1;                       /* New fd reference for dups */
        !           176: 
        !           177:        if (p->fd_dup == fd) for (j=0; j<NFDS; j++){
        !           178:                if (j == fd) continue;          /* Don't look at fd */
        !           179:                q = &files[j];
        !           180:                if (!q->fd_open) continue;      /* Not open */
        !           181:                if (q->fd_dup != fd) continue;
        !           182:                if (fd2 == -1){
        !           183:                        fd2 = j;                /* New reference */
        !           184:                        q->fd_buf = p->fd_buf;  /* Vital data */
        !           185:                        q->fd_open = 1;
        !           186:                        q->fd_lastop = p->fd_lastop;
        !           187:                }
        !           188:                q->fd_dup = fd2;
        !           189:                count++;
        !           190:        }
        !           191: 
        !           192: 
        !           193:        /* Flush and release the buffer associated with this fd. */
        !           194: 
        !           195:        newbuf(files[realfd(fd)].fd_buf, -1);
        !           196: 
        !           197: 
        !           198:        /* Mark the entry in the file descriptor table as "closed"
        !           199:         * and check the uniqueness of any remaining fd's pointing to
        !           200:         * the same area.  Be sure the buffer is released.
        !           201:         */
        !           202: 
        !           203:        p->fd_open = 0;
        !           204:        p->fd_dup = fd;
        !           205:        p->fd_buf = -1;
        !           206: 
        !           207:        for(j=0; j<NFDS; j++){
        !           208:                if (j == fd) continue;          /* Skip the same fd */
        !           209:                q = &files[fd];
        !           210:                if (!q->fd_open) continue;      /* Skip closed files */
        !           211:                if (p->fd_dev == q->fd_dev && p->fd_ind == q->fd_ind) break;
        !           212:        }
        !           213: 
        !           214:        if (j<NFDS) q->fd_uniq = 1;             /* Assume new fd is unique */
        !           215:        while(++j < NFDS){                      /* Now check to be sure */
        !           216:                p = &files[j];
        !           217:                if (p->fd_dev == q->fd_dev && p->fd_ind == q->fd_ind)
        !           218:                        p->fd_uniq = q->fd_uniq = 0;
        !           219:        }
        !           220: 
        !           221: 
        !           222:        /* Actually perform the close of the fd, and return the status
        !           223:         * of that system call.
        !           224:         */
        !           225: 
        !           226:        return(close(fd));
        !           227: }
        !           228: 
        !           229: 
        !           230: initbuf()
        !           231: {
        !           232: 
        !           233:        /* Initialize buffer structure, then use "openup" to set up
        !           234:         * file descriptors 0, and 1, which should already be
        !           235:         * open from parent process.  If 0 and 1 have the same inode
        !           236:         * and major/minor number they will be considered to be
        !           237:         * duplicates.  Fils descriptor 2 will be closed and set to
        !           238:         * duplicate file descriptor 1.
        !           239:         */
        !           240: 
        !           241:        register j;
        !           242:        register struct fds *p, *q;
        !           243: 
        !           244: 
        !           245:        /* Initialize file descriptor table */
        !           246: 
        !           247:        for(j=0; j<NFDS; j++){
        !           248:                files[j].fd_open = 0;                   /* Closed */
        !           249:                files[j].fd_dup = j;                    /* Dup = fd */
        !           250:                files[j].fd_buf = -1;                   /* No buffer */
        !           251:                files[j].fd_pipe = 0;                   /* Not pipe */
        !           252:        }
        !           253: 
        !           254: 
        !           255:        /* Initialize buffer table */
        !           256: 
        !           257:        for(j=0; j<NBUF; j++) iobuf[j].b_fd = -1;       /* Available */
        !           258: 
        !           259: 
        !           260:        /* "Open" devices 0, and 1 */
        !           261: 
        !           262:        openup(0);
        !           263:        openup(1);
        !           264:        p = &files[0];
        !           265:        q = &files[1];
        !           266:        if (p->fd_ind == q->fd_ind && p->fd_dev == q->fd_dev){
        !           267:                q->fd_dup = 0;
        !           268:                p->fd_uniq = q->fd_uniq = 1;
        !           269:        }
        !           270: 
        !           271: 
        !           272:        /* File descriptor 2 duplicates fd 1 */
        !           273: 
        !           274:        close(2);
        !           275:        dupf(1);
        !           276: }
        !           277: 
        !           278: newbuf(bufnum, fd)
        !           279: {
        !           280: 
        !           281:        register struct iobuf *bp;
        !           282:        register struct fds *fp;
        !           283:        register j;
        !           284:        static int bufcnt = 0;
        !           285: 
        !           286: 
        !           287:        /* The two arguments for this routine specify a buffer to
        !           288:         * be operated upon and a file descriptor.  There are three
        !           289:         * legal cases:
        !           290:         *
        !           291:         * bufnum < 0,  fd >= 0 -- assign new buffer to file descriptor fd
        !           292:         * bufnum >= 0, fd >= 0 -- assign buffer "bufnum" to fd
        !           293:         * bufnum >= 0, fd < 0  -- de-assign buffer "bufnum"
        !           294:         */
        !           295: 
        !           296:        if ((bufnum < 0 && fd < 0) || bufnum >= NBUF || fd >= NFDS)
        !           297:                return(-1);                             /* Invalid args */
        !           298: 
        !           299:        fd = (fd < 0) ? fd : realfd(fd);                /* Handle dups */
        !           300: 
        !           301: 
        !           302:        /* Step one -- if a buffer was specified, flush it.  If the
        !           303:         * last operation was a write, then write out the rest of
        !           304:         * the buffer.  If the last operation was a read, then perform
        !           305:         * a seek backwards on the corresponding fd to reposition the
        !           306:         * next read.
        !           307:         */
        !           308: 
        !           309:        if (bufnum >= 0){
        !           310:                bp = &iobuf[bufnum];
        !           311:                if (bp->b_len && (bp->b_fd >= 0))
        !           312:                        if (files[bp->b_fd].fd_lastop)
        !           313:                                write(bp->b_fd, bp->b_buf, bp->b_len);
        !           314:                        else
        !           315:                                lseek(bp->b_fd, (long)-bp->b_len, 1);
        !           316: 
        !           317:                bp->b_len = 0;                  /* Reset length */
        !           318:                bp->b_next = 0;                 /* Reset next position */
        !           319: 
        !           320: 
        !           321:                /* Step one point five -- if a file descriptor was
        !           322:                 * specified, check to insure that it is open.  Then,
        !           323:                 * reassign the buffer to that fd.
        !           324:                 */
        !           325: 
        !           326:                if(bp->b_fd >= 0)               /* Drop old assignment */
        !           327:                        files[bp->b_fd].fd_buf = -1;
        !           328: 
        !           329:                bp->b_fd = fd;                  /* Give buffer new fd */
        !           330:                if (fd < 0) return(0);          /* If fd < 0, done */
        !           331: 
        !           332:                fp = &files[fd];                /* Point to new structure */
        !           333: 
        !           334:                if (!fp->fd_open){              /* New file is not open */
        !           335:                        bp->b_fd = -1;          /* Drop assignment */
        !           336:                        return(-1);
        !           337:                }
        !           338: 
        !           339:                fp->fd_buf = bufnum;            /* New assignment */
        !           340:                return(0);
        !           341: 
        !           342:        }
        !           343: 
        !           344: 
        !           345:        /* Step two -- if no buffer was specified, but a file descriptor
        !           346:         * was, then some existing buffer must be allocated to that fd.
        !           347:         */
        !           348: 
        !           349:        fp = &files[fd];
        !           350: 
        !           351: 
        !           352:        /* First, check to see if a buffer is already assigned */
        !           353: 
        !           354:        for (j=0; j<NBUF; j++)
        !           355:                if (iobuf[j].b_fd == fd){
        !           356:                        bufcnt = j;
        !           357:                        goto recursive;
        !           358:                }
        !           359: 
        !           360: 
        !           361:        /* Next, scan the table of buffers looking for one
        !           362:         * which is not assigned.
        !           363:         */
        !           364: 
        !           365:        for (j=0; j<NBUF; j++) if (iobuf[j].b_fd < 0){
        !           366:                bufcnt = j;
        !           367:                goto recursive;
        !           368:        }
        !           369: 
        !           370: 
        !           371:        /* If no vacant buffer was found, then a buffer must
        !           372:         * be allocated arbitrarily.  The static local variable
        !           373:         * "bufcnt" is used for this purpose.  It contains the
        !           374:         * number of the last assigned buffer.  Buffers are
        !           375:         * switched in a sort-of "round robin" approach.
        !           376:         */
        !           377: 
        !           378:        j = bufcnt;
        !           379:        do {
        !           380:                bp = &iobuf[j];
        !           381:                fp = &files[bp->b_fd];
        !           382:                if (fp->fd_pipe && (!fp->fd_lastop) && bp->b_len > 0)
        !           383:                        continue;
        !           384:                bufcnt = j;
        !           385:                goto recursive;
        !           386:        } while((j = (j+1)%NBUF) != bufcnt);
        !           387:        return(-1);
        !           388: 
        !           389: 
        !           390:        /* Now, with a recursive call to this routine,
        !           391:         * switch to the new buffer.
        !           392:         */
        !           393: 
        !           394: recursive: return(newbuf(bufcnt, fd));
        !           395: 
        !           396: }
        !           397: 
        !           398: #ifndef realfd
        !           399: realfd(fd)
        !           400: {
        !           401: 
        !           402:        register struct fds *fp;
        !           403: 
        !           404: 
        !           405:        /* Process duplicate file descriptors.  If the main fd is
        !           406:         * nonnegative, use the value of the dup number for the true fd.
        !           407:         * No change is made if the file is closed.
        !           408:         */
        !           409: 
        !           410:        fp = &files[fd];
        !           411:        if (!fp->fd_open) return(fd);
        !           412:        return(fp->fd_dup < 0 ? fd : fp->fd_dup);
        !           413: }
        !           414: #endif
        !           415: 
        !           416: 
        !           417: readf(fd, buffer, length)
        !           418: char *buffer;
        !           419: {
        !           420: 
        !           421:        register struct fds *fp;
        !           422:        register struct iobuf *bp;
        !           423:        register j;
        !           424:        int change, trlog, again;
        !           425: 
        !           426: 
        !           427:        /* Handle duplicate files first.  If this file descriptor is
        !           428:         * a duplicate of another one, then the other's buffer and
        !           429:         * other information must be used.
        !           430:         */
        !           431: 
        !           432:        fd = realfd(fd);
        !           433: 
        !           434: 
        !           435:        /* If a read is to be performed on a file, all output to that
        !           436:         * file must first be flushed.  If the file descriptor's last
        !           437:         * function was output, use "newbuf" to flush the output,
        !           438:         * retaining the buffer, and then set the mode to input.  This
        !           439:         * must be done for all entries in "files" which have the same
        !           440:         * major/minor number as the current file.
        !           441:         */
        !           442: 
        !           443: 
        !           444: 
        !           445:        fp = &files[fd];
        !           446:        if (!fp->fd_open) return(-1);           /* File not open */
        !           447:        if (fp->fd_uniq){
        !           448:                if (fp->fd_lastop && fp->fd_buf >= 0)
        !           449:                        newbuf(fp->fd_buf, fd);
        !           450:        } else for(j=0; j<NFDS; j++){
        !           451:                fp = &files[realfd(j)];
        !           452:                if (fp->fd_dev == files[fd].fd_dev
        !           453:                        && fp->fd_ind == files[fd].fd_ind
        !           454:                        && fp->fd_open
        !           455:                        && fp->fd_lastop
        !           456:                        && fp->fd_buf >= 0){
        !           457:                                newbuf(fp->fd_buf, j);
        !           458:                }
        !           459:        }
        !           460: 
        !           461: 
        !           462:        /* The above code nicely took care of any buffer associated
        !           463:         * with the current fd.  Now, set the last operation on this fd
        !           464:         * to read, and if no buffer is currently assigned, get one.
        !           465:         */
        !           466: 
        !           467:        fp = &files[fd];
        !           468:        fp->fd_lastop = 0;
        !           469: 
        !           470:        if (fp->fd_buf < 0)
        !           471:                if (newbuf(-1, fd) < 0) return(read(fd, buffer, length));
        !           472: 
        !           473: 
        !           474:        /* The flag "again" determines whether or not the read buffer
        !           475:         * should be refilled when the end of it is reached.  Basically,
        !           476:         * "again" is set to 0 when a read of less than one buffer length
        !           477:         * occurs.  This way, terminal reads can stop at the carriage
        !           478:         * return, but disc reads can still buffer in BLEN-byte chunks
        !           479:         */
        !           480: 
        !           481:        again = 1;
        !           482: 
        !           483: 
        !           484:        /* The variable "trlog" keeps track of how many bytes have been
        !           485:         * transferred into the buffer supplied by the routine which
        !           486:         * called "readf".  Initially, this number is -1 (EOF).
        !           487:         */
        !           488: 
        !           489:        trlog = -1;
        !           490: 
        !           491: 
        !           492:        /* The main loop is rather simple -- the buffer is continually
        !           493:         * emptied and refilled until all of the requested data has been
        !           494:         * transferred.
        !           495:         */
        !           496: 
        !           497:        bp = &iobuf[fp->fd_buf];
        !           498:        while(1){
        !           499:                if (length <= 0) return(trlog);
        !           500:                if (bp->b_len == 0 && again){
        !           501:                        again = (bp->b_len=read(fd,bp->b_buf,BLEN)) == BLEN;
        !           502:                        bp->b_next = 0;
        !           503:                }
        !           504:                if (bp->b_len <= 0) return(trlog);
        !           505:                if (trlog < 0) trlog++;
        !           506:                change = (bp->b_len < length) ? bp->b_len : length;
        !           507:                for (j=0; j<change; j++)
        !           508:                        buffer[trlog+j] = bp->b_buf[bp->b_next+j];
        !           509:                trlog += change;
        !           510:                bp->b_len -= change;
        !           511:                bp->b_next += change;
        !           512:                length -= change;
        !           513:        }
        !           514: }
        !           515: 
        !           516: 
        !           517: writef(fd, buffer, length)
        !           518: char *buffer;
        !           519: {
        !           520: 
        !           521:        register struct fds *fp;
        !           522:        register struct iobuf *bp;
        !           523:        register j;
        !           524:        int change, trlog, again;
        !           525: 
        !           526: 
        !           527:        /* Handle duplicate files first.  If this file descriptor is
        !           528:         * a duplicate of another one, then the other's buffer and
        !           529:         * other information must be used.
        !           530:         */
        !           531: 
        !           532:        fd = realfd(fd);
        !           533: 
        !           534: 
        !           535:        /* If a write is to be performed on a file, all input from that
        !           536:         * file must first be flushed.  If the file descriptor's last
        !           537:         * function was input, use "newbuf" to flush the input,
        !           538:         * retaining the buffer, and then set the mode to output.  This
        !           539:         * must be done for all entries in "files" which have the same
        !           540:         * major/minor number as the current file.
        !           541:         */
        !           542: 
        !           543:        fp = &files[fd];
        !           544:        if (!fp->fd_open) return(-1);            /* File not open */
        !           545:        if (fp->fd_uniq){
        !           546:                if ((!fp->fd_lastop) && fp->fd_buf >= 0)
        !           547:                        newbuf(fp->fd_buf, fd);
        !           548: 
        !           549:        } else for(j=0; j<NFDS; j++){
        !           550:                fp = &files[realfd(j)];
        !           551:                if (fp->fd_dev == files[fd].fd_dev
        !           552:                        && fp->fd_ind == files[fd].fd_ind
        !           553:                        && fp->fd_open
        !           554:                        && (!fp->fd_lastop)
        !           555:                        && fp->fd_buf >= 0){
        !           556:                                newbuf(fp->fd_buf, j);
        !           557:                }
        !           558:        }
        !           559: 
        !           560: 
        !           561:        /* The above code nicely took care of any buffer associated
        !           562:         * with the current fd.  Now, set the last operation on this fd
        !           563:         * to write, and if no buffer is currently assigned, get one.
        !           564:         */
        !           565: 
        !           566:        fp = &files[fd];
        !           567:        fp->fd_lastop = 1;
        !           568: 
        !           569:        if (fp->fd_buf < 0)
        !           570:                if (newbuf(-1, fd) < 0) return(write(fd,buffer,length));
        !           571: 
        !           572: 
        !           573:        /* The main loop of output, like the main loop for input, is
        !           574:         * rather simple.  In fact, output is easier.  It is only
        !           575:         * necessary to check when the buffer is full and to flush it
        !           576:         * as necessary to the file.
        !           577:         */
        !           578: 
        !           579:        bp = &iobuf[fp->fd_buf];
        !           580:        trlog = 0;
        !           581:        while(1){
        !           582:                if (!length) return(trlog);
        !           583:                if (bp->b_len >= BLEN){
        !           584:                        write(fd, bp->b_buf, bp->b_len);
        !           585:                        bp->b_next = bp->b_len = 0;
        !           586:                }
        !           587: 
        !           588:                change = ((BLEN - bp->b_len) < length) ?
        !           589:                        (BLEN - bp->b_len) : length;
        !           590: 
        !           591:                for (j=0; j<change; j++)
        !           592:                        bp->b_buf[j+bp->b_next] = buffer[j+trlog];
        !           593: 
        !           594:                trlog += change;
        !           595:                bp->b_next = bp->b_len += change;
        !           596:                length -= change;
        !           597:        }
        !           598: }
        !           599: 
        !           600: long lseekf(fd, p1, p2)
        !           601: int fd, p2;
        !           602: long p1;
        !           603: {
        !           604: 
        !           605:        register struct fds *fp;
        !           606:        register j;
        !           607:        long lseek();
        !           608: 
        !           609: 
        !           610:        /* A seek on a file requires a flush of the buffer for that
        !           611:         * file and for any other file descriptors which are pointing
        !           612:         * to the same file.
        !           613:         */
        !           614: 
        !           615:        fd = realfd(fd);                /* Take care of dups */
        !           616:        fp = &files[fd];
        !           617: 
        !           618:        if (!fp->fd_open) return(-1);   /* not open */
        !           619: 
        !           620:        if (fp->fd_uniq){
        !           621:                if (fp->fd_buf >= 0) newbuf(fp->fd_buf, fd);
        !           622:        } else for(j=0; j<NFDS; j++){
        !           623:                fp = &files[j];
        !           624:                if (fp->fd_dev == files[fd].fd_dev
        !           625:                        && fp->fd_ind == files[fd].fd_ind
        !           626:                        && fp->fd_open
        !           627:                        && fp->fd_buf >= 0)
        !           628:                                newbuf(fp->fd_buf, j);
        !           629:        }
        !           630: 
        !           631: 
        !           632:        /* Now that all of the preliminaries are over, the actual
        !           633:         * seek can be performed.
        !           634:         */
        !           635: 
        !           636:        return(lseek(fd, p1, p2));
        !           637: }
        !           638: 
        !           639: fstatf(fd, stat_buf)
        !           640: struct stat *stat_buf;
        !           641: {
        !           642: 
        !           643:        register fd2;
        !           644: 
        !           645:        fd2 = realfd(fd);
        !           646:        newbuf(files[fd2].fd_buf, fd2);
        !           647:        return(fstat(fd, stat_buf));
        !           648: 
        !           649: }
        !           650: 
        !           651: bflush(){
        !           652: 
        !           653:        register j;
        !           654: 
        !           655:        /* Flush all buffers */
        !           656: 
        !           657:        for(j=0; j<NBUF; j++) newbuf(j, -1);
        !           658: }
        !           659: 
        !           660: check()
        !           661: {
        !           662:        register j, k;
        !           663: 
        !           664:        for (j=0; j<NFDS; j++)
        !           665:                if ((k=files[j].fd_buf) >= 0)
        !           666:                        if (iobuf[k].b_fd != j){
        !           667:                                write(2, "CONSISTENCY CHECK!\n", 19);
        !           668:                                if (files[j].fd_dup != j)
        !           669:                                        write(2, "BAD DUP ENTRY\n", 14);
        !           670:                        }
        !           671: 
        !           672: 
        !           673:        for (j=0; j<NBUF; j++)
        !           674:                if ((k=iobuf[j].b_fd) >= 0)
        !           675:                        if (files[k].fd_buf != j)
        !           676:                                write(2, "CONSISTENCY CHECK2!\n", 20);
        !           677: 
        !           678: }
        !           679: 
        !           680: #endif
        !           681: 
        !           682: empty(fd){
        !           683: 
        !           684:        struct stat sbuf;
        !           685:        register struct fds *fp;
        !           686: 
        !           687:        /* Simulate the Rand Corp.'s "empty" system call on a
        !           688:         * V7 system by seeing if the given fd is a pipe, and if
        !           689:         * so, whether or not it is empty.
        !           690:         */
        !           691: 
        !           692: #ifdef NBUF
        !           693:        fp = &files[realfd(fd)];
        !           694: 
        !           695:        if (!fp->fd_pipe || !fp->fd_open)
        !           696:                return(-1);             /* Not a pipe */
        !           697: 
        !           698:        if (fp->fd_buf >= 0 && iobuf[fp->fd_buf].b_len > 0)
        !           699:                return(0);              /* Data pending in buffer */
        !           700: #endif
        !           701: 
        !           702:        if (fstat(fd, &sbuf) < 0)
        !           703:                return(-1);             /* Can't "stat" it */
        !           704: 
        !           705:        return(sbuf.st_size == 0);
        !           706: }

unix.superglobalmegacorp.com

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