|
|
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 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.