Annotation of researchv10no/netfs/serv/d7.c, revision 1.1.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.