Annotation of coherent/d/bin/dos/dos3.c, revision 1.1.1.1

1.1       root        1: /* #define DEBUG 1 */
                      2: /* dos3.c */
                      3: 
                      4: #include "dos0.h"
                      5: 
                      6: MDIR *smdp;
                      7: DIR *sdp;
                      8: char *scp, *sname;
                      9: char *trim();
                     10: 
                     11: /*
                     12:  * Find the given filename relative to the given directory.
                     13:  * Return a pointer to the MDIR identifying the file, or NULL if not found.
                     14:  * Store a DIR pointer through the supplied dpp.
                     15:  * The stored DIR pointer gives the containing DIR for non-directory files
                     16:  * and the subdirectory DIR for directories.
                     17:  */
                     18: MDIR *
                     19: find(name, dp, dpp) char *name; register DIR *dp; DIR **dpp;
                     20: {
                     21:        register MDIR *mdp;
                     22:        register char *s;
                     23:        register char *cp;
                     24:        char *tname;
                     25: 
                     26:        dbprintf(("find(%s)\n", name));
                     27:        if ((s = strchr(name, '/')) == NULL)
                     28:        {
                     29:                /* No pathname, look for name in the directory. */
                     30:                tname = trim(name);
                     31:                cp = dosname(tname);
                     32:                for (mdp = dp->d_dir; mdp < dp->d_edp; mdp++)
                     33:                {
                     34:                        s = mdp->m_name;
                     35:                        if ((*s == MEMPTY) || (*s == MFREE))
                     36:                                continue;
                     37:                        dbprintf(("lmatch(%s,%s) = %d\n", tname, cohn(s),
                     38:                                                    lmatch(tname, cohn(s))));
                     39:                        if (lmatch(tname, cohn(s)) == 1)
                     40:                        {
                     41:                                if((strncmp (s, cp, 11) ==0) && isdir(mdp))
                     42:                                {
                     43:                                        /* Subdirectory, find its DIR. */
                     44:                                        for (dp = dp->d_child; dp != NULL;
                     45:                                                           dp = dp->d_sibling)
                     46:                                                if (strncmp(dp->d_dname, cp,
                     47:                                                                    11) == 0)
                     48:                                                        break;
                     49:                                        if (dp == NULL)
                     50:                                                fatal("find subdirectory botch");
                     51:                                        /* Read in the MDIR if necessary. */
                     52:                                        if (dp->d_dir == NULL)
                     53:                                                readmdir(dp);
                     54:                                }
                     55:                                if (dpp != NULL)
                     56:                                        *dpp = dp;
                     57:                                smdp = mdp;
                     58:                                scp = cp;
                     59:                                sdp = dp;
                     60:                                sname = name;
                     61:                                return mdp;
                     62:                        }
                     63:                }
                     64:                return NULL;
                     65:        }
                     66:        else if (s == name)
                     67:                return find(++s, dp, dpp);   /* "/foo" means look for "foo" */
                     68:        /* Explicit pathname, find the directory and recur. */
                     69:        *s = '\0';                      /* NUL-terminate dirname */
                     70:        cp = dosname(name);
                     71:        *s++ = '/';                     /* Restore the '/' */
                     72:        for (dp = dp->d_child; dp != NULL; dp = dp->d_sibling)
                     73:                if (strncmp(dp->d_dname, cp, 11) == 0)
                     74:                        break;
                     75:        if (dp == NULL)
                     76:                return NULL;            /* Not found */
                     77:        if (dp->d_dir == NULL)
                     78:                readmdir(dp);
                     79:        return find(s, dp, dpp);
                     80: }
                     81: 
                     82: MDIR *
                     83: findnext(dpp) DIR **dpp;
                     84: {
                     85:        register MDIR *mdp = ++smdp;
                     86:        register char *s;
                     87:        register char *cp = scp;
                     88:        register DIR *dp = sdp;
                     89: 
                     90:        dbprintf(("findnext(%s)\n", sname));
                     91:        for (; mdp < dp->d_edp; mdp++)
                     92:        {
                     93:                s = mdp->m_name;
                     94:                if ((*s == MEMPTY) || (*s == MFREE))
                     95:                        continue;
                     96:                dbprintf(("lmatch(%s,%s) = %d\n", sname, cohn(s), lmatch(sname, cohn(s))));
                     97:                if (lmatch(sname, cohn(s)) == 1)
                     98:                {
                     99:                        if ((strncmp (s, cp, 11) ==0) && isdir(mdp))
                    100:                        {
                    101:                                /* Subdirectory, find its DIR. */
                    102:                                for (dp = dp->d_child; dp != NULL;
                    103:                                                        dp = dp->d_sibling)
                    104:                                if (strncmp(dp->d_dname, cp, 11) == 0)
                    105:                                        break;
                    106:                                if (dp == NULL)
                    107:                                        fatal("find subdirectory botch");
                    108:                                /* Read in the MDIR if necessary. */
                    109:                                if (dp->d_dir == NULL)
                    110:                                        readmdir(dp);
                    111:                        }
                    112:                        if (dpp != NULL)
                    113:                                *dpp = dp;
                    114:                        smdp = mdp;
                    115:                        return mdp;
                    116:                }
                    117:        }
                    118:        return NULL;
                    119: }
                    120: 
                    121: 
                    122: /*
                    123:  * See if a pattern matches a string.
                    124:  * '\' escapes the next character.
                    125:  */
                    126: lmatch(pp, sp)
                    127: register char *pp;
                    128: register char *sp;
                    129: {
                    130:        short c2;
                    131:        register short c1;
                    132:        
                    133:        if ((*sp == '.') && ((sp[1] == '.') || (sp[1] == '\0')))
                    134:                return 0;
                    135: 
                    136:        if ((strcspn(pp, " ") == 0) && (strcspn(sp, " ") == 0))
                    137:                return 1;
                    138:        while ((c1=*pp++)) {
                    139:                switch (c1) {
                    140:                case '?':
                    141:                        if (*sp++)
                    142:                                continue;
                    143:                        return (0);
                    144:                case '*':
                    145:                        do {
                    146:                                if (lmatch(pp, sp))
                    147:                                        return (1);
                    148:                        } while (*sp++);
                    149:                        return (0);
                    150:                case '[':
                    151:                        if ((c2=*sp++) == '\0')
                    152:                                return (0);
                    153:                        for (;;) {
                    154:                                if ((c1=*pp++) == '\0' || c1 == ']')
                    155:                                        return (0);
                    156:                                if (c1 == '\\' && (c1=*pp++) == '\0')
                    157:                                        return (0);
                    158:                                if (c1 == c2)
                    159:                                        break;
                    160:                                if (*pp == '-') {
                    161:                                        pp += 1;
                    162:                                        if (c2 < c1)
                    163:                                                continue;
                    164:                                        if ((c1=*pp++) == '\0')
                    165:                                                return (0);
                    166:                                        if (c1 == '\\' && (c1=*pp++) == '\0')
                    167:                                                return (0);
                    168:                                        if (c2 <= c1)
                    169:                                                break;
                    170:                                }
                    171:                        }
                    172:                        while ((c1 = *pp++) != ']') {
                    173:                                if (c1 == '\0')
                    174:                                        return (0);
                    175:                                if (c1 == '\\' && *pp++ == '\0')
                    176:                                        return (0);
                    177:                        }
                    178:                        continue;
                    179:                case '\\':
                    180:                        if ((c1=*pp++) == '\0')
                    181:                                return (0);
                    182:                        /* fall through */
                    183:                default:
                    184:                        if (c1 == *sp++)
                    185:                                continue;
                    186:                        return (0);
                    187:                }
                    188:        }
                    189:        return (*sp=='\0');
                    190: }
                    191: 
                    192: 
                    193: char *
                    194: trim(name) register char *name;
                    195: {
                    196:        register char *s, *dotp;
                    197:        char c;
                    198:        static char buf[16];
                    199: 
                    200:        dotp = strrchr(name, '.');
                    201:        if (dotp == name)
                    202:                dotp = NULL;
                    203:        for (s = buf; name != dotp && (c = *name) != '\0'; name++)
                    204:                if (s < &buf[8])                /* copy name */
                    205:                        *s++ = (c == '.') ? '_' : c;
                    206:        if (name++ == dotp) {
                    207:                *s++ = '.';
                    208:                for ( ; *name != '\0'; name++)
                    209:                        if (s < &buf[12])
                    210:                                *s++ = *name;   /* copy extension */
                    211:        }
                    212:        *s = '\0';                              /* NUL terminate */
                    213:        return buf;
                    214: }
                    215: 
                    216: char * cohn(name) char * name;
                    217: {
                    218:        static char lname[22];
                    219:        char *tmp = lname;
                    220:        short i = 0;
                    221: 
                    222:        do {
                    223:                if (*name == ' ')
                    224:                        *name++;
                    225:                else {
                    226:                        *(tmp++) = tolower(*name);
                    227:                        name++;
                    228:                }
                    229:                i++;
                    230:        } while (i<8);
                    231: 
                    232:        if ((*name != ' ')) {
                    233:                *(tmp++) = '.';
                    234:                do {
                    235:                        if (*name == ' ')
                    236:                                *name++;
                    237:                        else {
                    238:                                *(tmp++) = tolower(*name);
                    239:                                name++;
                    240:                        }
                    241:                        i++;
                    242:                } while (i<11);
                    243:        }
                    244:        *tmp = '\0';
                    245: 
                    246:        return lname;
                    247: }
                    248: 
                    249: 
                    250: /*
                    251:  * Input up to nb characters into bp from COHERENT file fp,
                    252:  * taking into account the ASCII flag.
                    253:  * Pad to nb characters with NUL or CTRLZ.
                    254:  * Return the number of characters actually read.
                    255:  */
                    256: short
                    257: finput(fp, bp, nb) FILE *fp; register char *bp; unsigned short nb;
                    258: {
                    259:        register short c;
                    260:        register unsigned short n, n2;
                    261:        register char *ep;
                    262:        static char needlf = 0;
                    263: 
                    264:        if (!aflag) {
                    265:                n2 = n = read(fileno(fp), bp, nb);
                    266:                while (n2 && n < nb)
                    267:                {
                    268:                        n2 = read(fileno(fp), bp + n, nb - n);
                    269:                        n += n2;
                    270:                }
                    271:                for (ep = bp+nb, bp += n; bp < ep; )
                    272:                        *bp++ = '\0';
                    273:                return n;
                    274:        }
                    275:        for (n = 0, ep = bp+nb; bp < ep; ) {
                    276:                if (needlf) {
                    277:                        c = '\n';
                    278:                        needlf = 0;
                    279:                } else {
                    280:                        if ((c = getc(fp)) == '\r')
                    281:                                continue;
                    282:                        else if (c == '\n') {
                    283:                                c = '\r';
                    284:                                needlf++;
                    285:                        } else if (c == EOF)
                    286:                                c = CTRLZ;
                    287:                }
                    288:                if (c == CTRLZ)
                    289:                        break;
                    290:                n++;
                    291:                *bp++ = c;
                    292:        }
                    293:        while (bp < ep)
                    294:                *bp++ = CTRLZ;                          /* pad with EOFs */
                    295:        return n;
                    296: }
                    297: 
                    298: /*
                    299:  * Format an MS-DOS filesystem.
                    300:  * The optional argument is a boot block.
                    301:  */
                    302: void
                    303: format(nargs, args) short nargs; char *args[];
                    304: {
                    305:        register char *cp;
                    306:        short i, c;
                    307:        char *bp;
                    308:        unsigned short nsize;
                    309:        struct stat sbuf;
                    310: 
                    311:        /* Prompt to make sure. */
                    312:        printf("Are you sure you want to build an MS-DOS filesystem on device %s? ", device);
                    313:        fflush(stdout);
                    314:        c = getchar();
                    315:        while (c != '\n' && (i = getchar()) != '\n' && i != EOF)
                    316:                ;
                    317:        if (c != 'y' && c != 'Y') {
                    318:                rm_lock();
                    319:                exit(1);
                    320:        }
                    321:        if (nargs > 1)
                    322:                fatal("format: only one bootstrap file allowed");
                    323: 
                    324:        /* Get BPB for the specified format. */
                    325:        if (fstat(fsfd, &sbuf) < 0)
                    326:                fatal("format: cannot stat");
                    327:        i = sbuf.st_rdev;
                    328:        if (major(i) != FL_MAJOR)
                    329:                fatal("format: illegal device major number");
                    330:        switch (minor(i) & 0x0F) {
                    331:        case  0:        bpb = &s8floppy;        break;
                    332:        case  3:        bpb = &s9floppy;        break;
                    333:        case  9:        bpb = &d8floppy;        break;
                    334:        case 12:        bpb = &d9floppy;        break;
                    335:        case 13:        bpb = &q9floppy;        break;
                    336:        case 14:        bpb = &d15floppy;       break;
                    337:        case 15:        bpb = &d18floppy;       break;
                    338:        default:
                    339:                fatal("format: unsupported diskette type %d", minor(i) & 0x0F);
                    340:        }
                    341:        setglobals();
                    342: 
                    343:        /* Read boot block or build one. */
                    344:        if (nargs > 0) {
                    345:                if ((i=open(args[0], 0)) < 0)
                    346:                        fatal("format: cannot open boot block file \"%s\"", args[0]);
                    347:                if (read(i, bootb, BBSIZE) != BBSIZE)
                    348:                        fatal("format: boot block read error");
                    349:                close(i);
                    350:        } else {
                    351:                /* Patch in "jmp short ." with required flag byte. */
                    352:                bootb[0] = 0xEB;                /* JMP short */
                    353:                bootb[1] = 0xFE;                /* . (PC-relative) */
                    354:                bootb[2] = 0x90;                /* required flag */
                    355:                strncpy(&bootb[3], "COHERENT", 8);
                    356:                for (cp=&bootb[BPBOFF], bp=bpb, i=0; i < sizeof(BPB); i++)
                    357:                        *cp++ = *bp++;          /* copy the BPB */
                    358:        }
                    359:        if (write(fsfd, bootb, BBSIZE) != BBSIZE)
                    360:                fatal("format: boot block write error");
                    361: 
                    362:        /* Write the FATs (media id and zero bytes). */
                    363:        if (fatbytes != 1)
                    364:                fatal("format: fatbytes=%d", fatbytes);
                    365:        nsize = (maxcluster + 1) * sizeof(short);
                    366:        if (nsize < fatsize * ssize)
                    367:                nsize = fatsize * ssize;
                    368:        if ((fatcache = calloc(nsize, 1)) == NULL)
                    369:                fatal("format: FAT allocation failed");
                    370:        fatcache[0] = 0xFF00 | bpb->b_media;
                    371:        fatcache[1] = CLEOF;
                    372:        fatcfirst = 0;
                    373:        fatccount = fatsize;
                    374:        fatcflag = 1;
                    375:        writefat();
                    376:        free(fatcache);
                    377: 
                    378:        /* Write the directory (all zero bytes). */
                    379:        if ((cp = calloc(dirsize, ssize)) == NULL)
                    380:                fatal("format: directory allocation failed");
                    381:        diskwrite(cp, (long)dirbase, dirsize, "directory");
                    382:        free(cp);
                    383: }
                    384: 
                    385: /*
                    386:  * Output nb characters from bp to COHERENT file fp,
                    387:  * taking into account the ASCII flag.
                    388:  * Return the number of characters actually written.
                    389:  */
                    390: short
                    391: foutput(fn, fp, bp, nb) char *fn; FILE *fp; register char *bp; unsigned short nb;
                    392: {
                    393:        register unsigned short n;
                    394:        register char *ep;
                    395: 
                    396:        if (!aflag) {
                    397:                if (write(fileno(fp), bp, nb) != nb)
                    398:                        fatal("extract: write error on file \"%s\"", fn);
                    399:                return nb;
                    400:        }
                    401:        for (n = 0, ep = bp+nb; bp < ep; bp++) {
                    402:                if (*bp == '\r')
                    403:                        continue;
                    404:                else if (*bp == CTRLZ)
                    405:                        break;
                    406:                n++;
                    407:                putc(*bp, fp);
                    408:        }
                    409:        if (ferror(fp))
                    410:                fatal("extract: write error on file \"%s\"", fn);
                    411:        return n;
                    412: }
                    413: 
                    414: /*
                    415:  * Return the next free cluster on the diskette.
                    416:  * Stick an EOF marker in the cluster.
                    417:  * Failure is fatal.
                    418:  */
                    419: unsigned short
                    420: freecluster()
                    421: {
                    422:        register unsigned short n;
                    423: 
                    424:        for (n = 2; n <= maxcluster; n++)
                    425:                if (getcluster(n) == CLFREE) {
                    426:                        putcluster(n, CLEOF);
                    427:                        return n;
                    428:                }
                    429:        fatal("out of space on MS-DOS disk");
                    430: }
                    431: 
                    432: /*
                    433:  * Read the key for the command.
                    434:  * Set globals accordingly.
                    435:  * Return the required device mode for the command.
                    436:  */
                    437: short
                    438: key(s) register char *s;
                    439: {
                    440:        register short c, nfun;
                    441: 
                    442:        nfun = 0;
                    443:        bflag = 1;                      /* assume binary */
                    444:        if (*s == '-')
                    445:                ++s;                    /* ignore optional '-' */
                    446:        while ((c = *s++) != '\0')
                    447:                switch (c) {
                    448: 
                    449:                /* Functions. */
                    450:                case 'd':       fun = delete;   ++nfun; break;
                    451:                case 'F':       fun = format;   ++nfun; break;
                    452:                case 'l':       fun = label;    ++nfun; break;
                    453:                case 'r':       fun = replace;  ++nfun; break;
                    454:                case 't':       fun = table;    ++nfun; break;
                    455:                case 'x':       fun = extract;  ++nfun; break;
                    456: 
                    457:                /* Flags. */
                    458:                case 'a':       aflag++;       bflag--; break;
                    459:                case 'c':       cflag++;                break;
                    460:                case 'k':       kflag++;                break;
                    461:                case 'n':       nflag++;                break;
                    462:                case 'p':       pflag++;                break;
                    463:                case 's':       sflag++;                break;
                    464:                case 'v':       vflag++;                break;
                    465:                case 'V':
                    466:                        fprintf(stderr, "dos: V%s\n", VERSION);
                    467:                        break;
                    468:                case '1':
                    469:                case '2':
                    470:                case '3':
                    471:                case '4':
                    472:                case '5':
                    473:                case '6':
                    474:                case '7':
                    475:                case '8':
                    476:                case '9':
                    477:                        xpart = c - '0';
                    478:                        break;
                    479: 
                    480:                default:
                    481:                        usage();
                    482:                }
                    483: 
                    484:        if (nfun == 0)
                    485:                fun = table;                    /* default */
                    486:        else if (nfun > 1)
                    487:                fatal("must specify one function [dFlrtx]");
                    488:        return (cflag || fun==table || fun==extract) ? 0 : 2;
                    489: }
                    490: 
                    491: /*
                    492:  * Label a disk with a volume label.
                    493:  */
                    494: void
                    495: label(nargs, args) short nargs; char *args[];
                    496: {
                    497:        char tmp[13], *b;
                    498:        short i;
                    499: 
                    500:        if (nargs > 1)
                    501:                fatal("label: single argument required");
                    502:        else if (nargs == 0) {
                    503:                if (volume == NULL)
                    504:                        printf("Volume in Drive %s is unlabeled.\n",adev);
                    505:                else {
                    506:                        strncpy(tmp, volume->m_name, 11);
                    507:                        tmp[11] = '\0';
                    508:                        printf("Volume in Drive %s is labeled %s.\n",adev,tmp);
                    509:                }
                    510:        }
                    511:        else {
                    512:                if ((i = strlen(args[0])) > 8) {
                    513:                        if (i > 11)
                    514:                                args[0][11] = '\0';
                    515:                        strncpy(tmp, args[0], 8);
                    516:                        tmp[8] = '.';
                    517:                        strcpy(&tmp[9], &args[0][8]);
                    518:                                
                    519:                        b = tmp;
                    520:                }
                    521:                else
                    522:                        b= args[0];
                    523:                
                    524:                if (volume != NULL)
                    525:                        deletefile(volume, root);
                    526:                if (find(b, root, NULL) != NULL)
                    527:                        fatal("label: file \"%s\" already exists", b);
                    528:                if (strchr(b, '/') != NULL)
                    529:                        fatal("label: label cannot use character '/'");
                    530:                volume = creatfile(b, root);
                    531:                volume->m_attr = MVOLUME;
                    532:        }
                    533: }
                    534: 
                    535: /*
                    536:  * Initialize an MDIR with the current time and date,
                    537:  * the given name, attribute and cluster, and size 0L.
                    538:  * Set the flag requiring the DIR to be written.
                    539:  */
                    540: void
                    541: mdirinit(mdp, dp, name, attr, cluster)
                    542: register MDIR *mdp;
                    543: DIR *dp;
                    544: char *name;
                    545: unsigned short attr, cluster;
                    546: {
                    547:        register short i;
                    548: 
                    549:        dbprintf(("mdirinit(mdp=%x dp=\"%s\" name=\"%s\" attr=%x cl=%x)\n", mdp, dp->d_dname, name, attr, cluster));
                    550:        strncpy(mdp->m_name, name, 11);
                    551:        mdp->m_attr = attr;
                    552:        for (i=0; i<10; i++)
                    553:                mdp->m_junk[i] = 0;
                    554:        dostime(mdp, NULL);
                    555:        mdp->m_cluster = cluster;
                    556:        mdp->m_size = 0;
                    557:        dp->d_dirflag = 1;
                    558: }
                    559: 
                    560: /* end of dos3.c */

unix.superglobalmegacorp.com

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