Annotation of researchv10no/netfs/serv/d7.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * read a V7 PDP-11 dump tape as a filesystem
        !             3:  */
        !             4: #include <stdio.h>
        !             5: #include <rf.h>
        !             6: #include <sys/types.h>
        !             7: #include <sys/stat.h>
        !             8: #include <errno.h>
        !             9: 
        !            10: /*
        !            11:  * PDP-11 integers
        !            12:  */
        !            13: #define        p11s(c) ((c)[0]|((c)[1]<<8))
        !            14: #define        p11l(c) ((c)[2]|((c)[3]<<8)|((c)[0]<<16)|((c)[1]<<24))  /* wretched FP-11 */
        !            15: #define        P11S    2       /* size of PDP-11 short */
        !            16: #define        P11L    4       /* size of PDP-11 long */
        !            17: 
        !            18: /*
        !            19:  * PDP-11 disk inode offsets
        !            20:  */
        !            21: 
        !            22: #define        DI_MODE 0       /* (short) */
        !            23: #define        DI_NLINK 2      /* (short) */
        !            24: #define        DI_UID  4       /* (short) */
        !            25: #define        DI_GID  6       /* (short) */
        !            26: #define        DI_SIZE 8       /* (long) */
        !            27: #define        DI_ADDR 12      /* 40 bytes */
        !            28: #define        DI_ATIME 52     /* (long) */
        !            29: #define        DI_MTIME 56     /* (long) */
        !            30: #define        DI_CTIME 60     /* (long) */
        !            31: #define        DILEN   64
        !            32: 
        !            33: /*
        !            34:  * PDP-11 directory entry
        !            35:  */
        !            36: 
        !            37: #define        D_INO   0       /* (short) */
        !            38: #define        D_NAME  2       /* 14 characters */
        !            39: #define        DNSIZE  14
        !            40: #define        DLEN    16
        !            41: 
        !            42: /*
        !            43:  * dump records
        !            44:  */
        !            45: 
        !            46: #define        TBSIZE  512
        !            47: 
        !            48: #define        MAGIC   (int)60011
        !            49: 
        !            50: #define        TS_TAPE 1
        !            51: #define        TS_INODE 2
        !            52: #define        TS_BITS 3
        !            53: #define        TS_ADDR 4
        !            54: #define        TS_END  5
        !            55: #define        TS_CLRI 6
        !            56: 
        !            57: struct spcl11 {                /* header as found on the tape */
        !            58:        unsigned char c_type[P11S];
        !            59:        unsigned char c_date[P11L];
        !            60:        unsigned char c_ddate[P11L];
        !            61:        unsigned char c_volume[P11S];
        !            62:        unsigned char c_tapea[P11L];
        !            63:        unsigned char c_inumber[P11S];
        !            64:        unsigned char c_magic[P11S];
        !            65:        unsigned char c_checksum[P11S];
        !            66:        unsigned char c_dinode[DILEN];
        !            67:        unsigned char c_count[P11S];
        !            68:        unsigned char c_addr[TBSIZE];
        !            69: };
        !            70: 
        !            71: struct spcl {          /* header we use internally */
        !            72:        int c_type;
        !            73:        int c_inumber;
        !            74:        unsigned char c_dinode[DILEN];
        !            75:        int c_count;
        !            76:        char c_addr[TBSIZE];
        !            77: };
        !            78: 
        !            79: /*
        !            80:  * our data
        !            81:  */
        !            82: 
        !            83: typedef unsigned int taddr_t;
        !            84: 
        !            85: #define        MAXINO  10000   /* dynamic would be better */
        !            86: static taddr_t iaddr[MAXINO];  /* offset of TS_INODE for this file */
        !            87: 
        !            88: static int devfd;
        !            89: static Rfile *root;
        !            90: int fserrno;
        !            91: 
        !            92: struct spcl *getspcl();
        !            93: taddr_t curtblock();
        !            94: Rfile *getino();
        !            95: 
        !            96: char *malloc();
        !            97: long lseek();
        !            98: 
        !            99: /*
        !           100:  * init
        !           101:  */
        !           102: Rfile *
        !           103: fsinit(argc, argv)
        !           104: int argc;
        !           105: char **argv;
        !           106: {
        !           107: 
        !           108:        if (argc <= 1)
        !           109:                rfpanic("no device\n");
        !           110:        if ((devfd = open(argv[1], 0)) < 0)
        !           111:                rfpanic("%s: cannot open\n", argv[1]);
        !           112:        scantape();
        !           113:        if ((root = getino(2)) == NULL)
        !           114:                rfpanic("no root\n");
        !           115:        return (root);
        !           116: }
        !           117: 
        !           118: /*
        !           119:  * look up a file
        !           120:  */
        !           121: Rfile *
        !           122: fswalk(df, name)
        !           123: Rfile *df;
        !           124: char *name;
        !           125: {
        !           126:        int ino;
        !           127: 
        !           128:        if ((ino = dsearch(df, name)) == 0) {
        !           129:                fserrno = ENOENT;
        !           130:                return (NULL);
        !           131:        }
        !           132:        if (df == root) {       /* "." and ".." magic */
        !           133:                if (strcmp(name, ".") == 0)
        !           134:                        return (df);
        !           135:                if (strcmp(name, "..") == 0) {
        !           136:                        fserrno = 0;    /* pseudo-error */
        !           137:                        return (NULL);
        !           138:                }
        !           139:        }
        !           140:        return (getino(ino));
        !           141: }
        !           142: 
        !           143: /*
        !           144:  * all done with a file
        !           145:  */
        !           146: fsdone(f)
        !           147: Rfile *f;
        !           148: {
        !           149:        free(f->fs);
        !           150:        free((char *)f);
        !           151:        return (0);
        !           152: }
        !           153: 
        !           154: /*
        !           155:  * read data
        !           156:  */
        !           157: int
        !           158: fsread(f, off, buf, len)
        !           159: register Rfile *f;
        !           160: long off;
        !           161: char *buf;
        !           162: int len;
        !           163: {
        !           164:        char blk[TBSIZE];
        !           165:        int rest;
        !           166:        long bno;
        !           167: 
        !           168:        switch (f->mode & S_IFMT) {
        !           169:        case S_IFREG:
        !           170:        case S_IFDIR:
        !           171:                break;
        !           172: 
        !           173:        default:
        !           174:                return (0);
        !           175:        }
        !           176:        if (off >= f->size)
        !           177:                return (0);
        !           178:        if (off + len > f->size)
        !           179:                len = f->size - off;
        !           180:        bno = off / TBSIZE;
        !           181:        if (getblk(f, bno, blk) == 0)
        !           182:                return (-1);
        !           183:        rest = (bno + 1)*TBSIZE - off;
        !           184:        if (len > rest)
        !           185:                len = rest;
        !           186:        memcpy(buf, blk + (off % TBSIZE), len);
        !           187:        return (len);
        !           188: }
        !           189: 
        !           190: /*
        !           191:  * read a piece of a directory
        !           192:  * -- cheap out for now: just return one
        !           193:  */
        !           194: int
        !           195: fsdirread(f, off, buf, len, offp)
        !           196: register Rfile *f;
        !           197: long off;
        !           198: char *buf;
        !           199: int len;
        !           200: long *offp;
        !           201: {
        !           202:        int stlen;
        !           203:        register unsigned char *de;
        !           204:        unsigned char blk[TBSIZE];
        !           205:        unsigned char one[TBSIZE];
        !           206:        int n, ino;
        !           207: 
        !           208:        if (off % DLEN) {
        !           209:                fserrno = EINVAL;
        !           210:                return (-1);
        !           211:        }
        !           212:        stlen = len;
        !           213:        de = &blk[TBSIZE];
        !           214:        for (; off < f->size; de += DLEN, off += DLEN) {
        !           215:                if (de >= &blk[TBSIZE]) {
        !           216:                        if (getblk(f, off/TBSIZE, blk) == 0)
        !           217:                                break;
        !           218:                        de = &blk[off%TBSIZE];
        !           219:                }
        !           220:                ino = p11s(&de[D_INO]);
        !           221:                if (ino == 0)
        !           222:                        continue;
        !           223:                n = sprintf(one, "%d\t%.14s", ino, &de[D_NAME]);
        !           224:                n++;    /* need the NUL too */
        !           225:                if (n > len)
        !           226:                        break;
        !           227:                memcpy(buf, one, n);
        !           228:                len -= n;
        !           229:                buf += n;
        !           230:        }
        !           231:        *offp = off;
        !           232:        return (stlen - len);
        !           233: }
        !           234: 
        !           235: /*
        !           236:  * search a directory
        !           237:  */
        !           238: int
        !           239: dsearch(f, name)
        !           240: Rfile *f;
        !           241: char *name;
        !           242: {
        !           243:        unsigned char dbuf[TBSIZE];
        !           244:        register unsigned char *de;
        !           245:        register int ino;
        !           246:        register long b, size;
        !           247: 
        !           248:        for (b = 0, size = f->size; size > 0; b++, size -= TBSIZE) {
        !           249:                if (getblk(f, b, dbuf) == 0)
        !           250:                        continue;
        !           251:                for (de = dbuf; de < &dbuf[TBSIZE]; de += DLEN) {
        !           252:                        ino = p11s(&de[D_INO]);
        !           253:                        if (ino == 0)
        !           254:                                continue;
        !           255:                        if (strncmp(&de[D_NAME], name, DNSIZE) == 0)
        !           256:                                return (ino);
        !           257:                }
        !           258:        }
        !           259:        return (0);
        !           260: }
        !           261: 
        !           262: /*
        !           263:  * retrieve file data
        !           264:  */
        !           265: Rfile *
        !           266: getino(i)
        !           267: int i;
        !           268: {
        !           269:        register Rfile *f;
        !           270:        register struct spcl *sp;
        !           271:        long nblocks;
        !           272: 
        !           273:        if (i >= MAXINO || i < 0 || iaddr[i] == 0) {
        !           274:                rflog("%d: bad i-number\n", i);
        !           275:                fserrno = EINVAL;
        !           276:                return (NULL);
        !           277:        }
        !           278:        lseek(devfd, (long)iaddr[i] * TBSIZE, 0);
        !           279:        if ((sp = getspcl()) == NULL
        !           280:        ||  sp->c_type != TS_INODE) {
        !           281:                rflog("%d: can't find header\n", i);
        !           282:                fserrno = EIO;
        !           283:                return (NULL);
        !           284:        }
        !           285:        if (sp->c_inumber != i) {
        !           286:                rflog("%d: found header for %d instead\n",
        !           287:                        i, sp->c_inumber);
        !           288:                fserrno = EIO;
        !           289:                return (NULL);
        !           290:        }
        !           291:        if ((f = (Rfile *)malloc(sizeof(Rfile))) == NULL) {
        !           292:                rflog("%d: no memory for header\n", i);
        !           293:                fserrno = ENOMEM;
        !           294:                return (NULL);
        !           295:        }
        !           296:        f->ino = i;
        !           297:        f->dev = 0;
        !           298:        f->mode = p11s(&sp->c_dinode[DI_MODE]); /* understood same bits */
        !           299:        f->nlink = p11s(&sp->c_dinode[DI_NLINK]);
        !           300:        f->uid = p11s(&sp->c_dinode[DI_UID]);
        !           301:        f->gid = p11s(&sp->c_dinode[DI_GID]);
        !           302:        f->rdev = 0;
        !           303:        f->size = p11l(&sp->c_dinode[DI_SIZE]);
        !           304:        f->ta = p11l(&sp->c_dinode[DI_ATIME]);
        !           305:        f->tm = p11l(&sp->c_dinode[DI_MTIME]);
        !           306:        f->tc = p11l(&sp->c_dinode[DI_CTIME]);
        !           307:        nblocks = (f->size + TBSIZE - 1)/TBSIZE;
        !           308:        if ((f->fs = malloc(nblocks * sizeof(taddr_t))) == NULL) {
        !           309:                rflog("%d: no mem for %d block addresses\n", i, nblocks);
        !           310:                fserrno = ENOMEM;
        !           311:                free((char *)f);
        !           312:                return (NULL);
        !           313:        }
        !           314:        scanfile(sp, (taddr_t *)f->fs, nblocks);
        !           315:        return (f);
        !           316: }
        !           317: 
        !           318: /*
        !           319:  * read a TBSIZE block from file
        !           320:  */
        !           321: getblk(f, bno, buf)
        !           322: register Rfile *f;
        !           323: long bno;
        !           324: char *buf;
        !           325: {
        !           326: 
        !           327:        if (bno * TBSIZE > f->size) {
        !           328:                fserrno = 0;
        !           329:                return (0);
        !           330:        }
        !           331:        lseek(devfd, (long)((taddr_t *)f->fs)[bno] * TBSIZE, 0);
        !           332:        if (read(devfd, buf, TBSIZE) != TBSIZE) {
        !           333:                rflog("%d: bno %ld: errno %d\n", f->ino, bno, errno);
        !           334:                fserrno = errno;
        !           335:                return (0);
        !           336:        }
        !           337:        return (1);
        !           338: }
        !           339: 
        !           340: /*
        !           341:  * scan the tape,
        !           342:  * remember where all the file records are
        !           343:  */
        !           344: 
        !           345: scantape()
        !           346: {
        !           347:        register struct spcl *sp;
        !           348:        register int i;
        !           349: 
        !           350:        for (;;) {
        !           351:                if ((sp = getspcl()) == NULL) {
        !           352:                        rflog("unexpected tape EOF\n");
        !           353:                        return;
        !           354:                }
        !           355:                switch (sp->c_type) {
        !           356:                case TS_END:
        !           357:                        return;
        !           358: 
        !           359:                case TS_TAPE:
        !           360:                        continue;
        !           361: 
        !           362:                case TS_BITS:
        !           363:                case TS_CLRI:
        !           364:                        lseek(devfd, (long)sp->c_count * TBSIZE, 1);
        !           365:                        continue;
        !           366: 
        !           367:                case TS_ADDR:
        !           368:                        rflog("unexpected TS_ADDR i %d\n", sp->c_inumber);
        !           369:                        continue;
        !           370: 
        !           371:                default:
        !           372:                        rflog("ill spcl type %d i %d\n",
        !           373:                                sp->c_type, sp->c_inumber);
        !           374:                        continue;
        !           375: 
        !           376:                case TS_INODE:
        !           377:                        i = sp->c_inumber;
        !           378:                        if (i <= 0 || i >= MAXINO)
        !           379:                                rflog("ill TS_FILE i %d\n", i);
        !           380:                        else
        !           381:                                iaddr[i] = curtblock() - 1;
        !           382:                        scanfile(sp, (taddr_t *)NULL,
        !           383:                                (p11l(&sp->c_dinode[DI_SIZE])+TBSIZE-1)/TBSIZE);
        !           384:                        continue;
        !           385:                }
        !           386:        }
        !           387: }
        !           388: 
        !           389: /*
        !           390:  * skip lightly through a file,
        !           391:  * remembering where the blocks are
        !           392:  * ip is an array of tape addresses;
        !           393:  * n is the length of the array, if present,
        !           394:  * which is the same as the number of blocks expected
        !           395:  * call with the TS_INODE record,
        !           396:  * since that contains the first list of blocks
        !           397:  */
        !           398: 
        !           399: scanfile(sp, ip, n)
        !           400: register struct spcl *sp;
        !           401: register taddr_t *ip;
        !           402: register int n;
        !           403: {
        !           404:        register int i;
        !           405:        taddr_t tblock;
        !           406: 
        !           407:        tblock = curtblock();
        !           408:        while (n) {
        !           409:                for (i = 0; i < sp->c_count; i++) {
        !           410:                        if (sp->c_count == 0) {         /* hole */
        !           411:                                if (ip)
        !           412:                                        *ip++ = 0;
        !           413:                        } else {                        /* real */
        !           414:                                if (ip)
        !           415:                                        *ip++ = tblock;
        !           416:                                tblock++;
        !           417:                        }
        !           418:                        if (--n <= 0)
        !           419:                                break;
        !           420:                }
        !           421:                lseek(devfd, (long)tblock*TBSIZE, 0);   /* past data */
        !           422:                if (n <= 0)
        !           423:                        return;
        !           424:                /*
        !           425:                 * more: get TS_ADDR
        !           426:                 */
        !           427:                if ((sp = getspcl()) == NULL) {
        !           428:                        rflog("unexpected tape EOF\n");
        !           429:                        return;
        !           430:                }
        !           431:                if (sp->c_type != TS_ADDR) {
        !           432:                        rflog("wanted TS_ADDR, got type %d i %d\n",
        !           433:                                sp->c_type, sp->c_inumber);
        !           434:                        unspcl();
        !           435:                        return;
        !           436:                }
        !           437:                tblock++;               /* count the header we just read */
        !           438:        }
        !           439: }
        !           440: 
        !           441: struct spcl *
        !           442: getspcl()
        !           443: {
        !           444:        char buf[TBSIZE];
        !           445:        static struct spcl s;
        !           446:        register struct spcl11 *tp;
        !           447:        int nbad;
        !           448: 
        !           449:        nbad = 0;
        !           450:        tp = (struct spcl11 *)buf;
        !           451:        for (;;) {
        !           452:                if (read(devfd, buf, TBSIZE) != TBSIZE) {
        !           453:                        rflog("tape scan read, errno %d\n", errno);
        !           454:                        return (NULL);
        !           455:                }
        !           456:                if (p11s(tp->c_magic) != MAGIC) {
        !           457:                        nbad++;
        !           458:                        continue;
        !           459:                }
        !           460:                s.c_type = p11s(tp->c_type);
        !           461:                s.c_inumber = p11s(tp->c_inumber);
        !           462:                s.c_count = p11s(tp->c_count);
        !           463:                /* a sanity check or two would go well here */
        !           464:                memcpy(s.c_dinode, tp->c_dinode, DILEN);
        !           465:                memcpy(s.c_addr, tp->c_addr, s.c_count);
        !           466:                if (nbad)
        !           467:                        rflog("skipped %d to type %d i %d\n",
        !           468:                                nbad, s.c_type, s.c_inumber);
        !           469:                return (&s);
        !           470:        }
        !           471: }
        !           472: 
        !           473: /*
        !           474:  * reread the current header: cheap hack
        !           475:  */
        !           476: unspcl()
        !           477: {
        !           478:        lseek(devfd, (long)-TBSIZE, 1);
        !           479: }
        !           480: 
        !           481: taddr_t
        !           482: curtblock()
        !           483: {
        !           484:        return (lseek(devfd, 0L, 1)/TBSIZE);
        !           485: }
        !           486: 

unix.superglobalmegacorp.com

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