|
|
1.1 ! root 1: /* #define DEBUG 1*/ ! 2: /* dos4.c */ ! 3: ! 4: #include "dos0.h" ! 5: char *fequiv(); ! 6: /* ! 7: * Compare two MDIR names. ! 8: * Directories precede ordinary files. ! 9: * Called by qsort(). ! 10: */ ! 11: short ! 12: namecmp(mdpp1, mdpp2) MDIR **mdpp1, **mdpp2; ! 13: { ! 14: register MDIR *mdp1, *mdp2; ! 15: unsigned long t1, t2; ! 16: ! 17: mdp1 = *mdpp1; ! 18: mdp2 = *mdpp2; ! 19: if (isdir(mdp1) != isdir(mdp2)) ! 20: return (isdir(mdp1)) ? -1 : 1; ! 21: if (nflag) { ! 22: /* ! 23: * Compare by time with unsigned long compare. ! 24: * m_junk[10] is really the first byte of the time. ! 25: * Kludgy but it works. ! 26: */ ! 27: t1 = *(unsigned long *)&mdp1->m_junk[10]; ! 28: t2 = *(unsigned long *)&mdp2->m_junk[10]; ! 29: if (t1 != t2) ! 30: return (t1 < t2) ? -1 : 1; ! 31: } ! 32: return strncmp(mdp1->m_name, mdp2->m_name, 11); ! 33: } ! 34: ! 35: /* ! 36: * Allocate a new DIR and link it into the DIR tree. ! 37: * Initialize it with the supplied information. ! 38: * Return a pointer to it. ! 39: * The MDIR array is not allocated and read until required. ! 40: */ ! 41: DIR * ! 42: newdir(parent, mdp, files) ! 43: DIR *parent; ! 44: register MDIR *mdp; ! 45: short files; ! 46: { ! 47: register DIR *dp; ! 48: ! 49: /* Allocate a new DIR. */ ! 50: dbprintf(("newdir(parent=\"%s\" mdp=%x files=%u): \n", (parent==NULL)?"<root> ":parent->d_dname, mdp, files)); ! 51: if ((dp = (DIR *)malloc(sizeof(DIR))) == NULL) ! 52: fatal("directory allocation failed"); ! 53: ! 54: /* Initialize the DIR. */ ! 55: dp->d_parent = parent; ! 56: dp->d_child = NULL; ! 57: if (parent == NULL) { ! 58: /* Root. */ ! 59: dp->d_sibling = NULL; ! 60: dp->d_cluster = 0; ! 61: strcpy(dp->d_dname, "<root> "); ! 62: } else { ! 63: /* Subdirectory. */ ! 64: dp->d_sibling = parent->d_child; ! 65: parent->d_child = dp; ! 66: dp->d_cluster = mdp->m_cluster; ! 67: strncpy(dp->d_dname, mdp->m_name, 11); ! 68: dp->d_dname[11] = '\0'; ! 69: } ! 70: dp->d_files = files; ! 71: dp->d_dirblocks = (files * sizeof(MDIR) + ssize - 1) / ssize; ! 72: dp->d_dir = dp->d_edp = NULL; ! 73: dp->d_dirflag = 0; ! 74: dbprintf(("\"%s\" cl=%x blocks=%u dp=%x\n", dp->d_dname, dp->d_cluster, dp->d_dirblocks, dp)); ! 75: return dp; ! 76: } ! 77: ! 78: /* ! 79: * Print a nonfatal error message. ! 80: * Set the return status to 1. ! 81: * Uses the nonportable "%r" format. ! 82: */ ! 83: void ! 84: nonfatal(x) char *x; ! 85: { ! 86: fprintf(stderr, "dos: %r\n", &x); ! 87: estat = 1; ! 88: } ! 89: ! 90: /* ! 91: * Allocate space for an MS-DOS directory. ! 92: * Read in the directory unless dp is not root and its d_cluster is 0. ! 93: */ ! 94: void ! 95: readmdir(dp) register DIR *dp; ! 96: { ! 97: register MDIR *mdp; ! 98: register unsigned short n; ! 99: ! 100: dbprintf(("readmdir(%s) blocks=%u cl=%x\n", dp->d_dname, dp->d_dirblocks, dp->d_cluster)); ! 101: if ((mdp = (MDIR *)calloc(dp->d_dirblocks, ssize)) == NULL) ! 102: fatal("directory allocation failed"); ! 103: dp->d_dir = mdp; ! 104: dp->d_edp = mdp + dp->d_files; ! 105: ! 106: if (dp->d_cluster == 0) { ! 107: if (dp->d_parent != NULL) ! 108: return; /* new subdirectory */ ! 109: diskread(mdp, (long)dirbase, dp->d_dirblocks, "directory"); ! 110: } else ! 111: for (n = dp->d_cluster ; n <= CLMAX; n = getcluster(n)) { ! 112: diskread(mdp, cltosec(n), clsize, "subdirectory"); ! 113: mdp += mdirsize; ! 114: } ! 115: ! 116: /* Scan through the directory for volume label and subdirectories. */ ! 117: for (mdp = dp->d_dir; mdp < dp->d_edp; mdp++) { ! 118: if ((n = mdp->m_name[0]) == MFREE || n == MEMPTY || n == MMDIR) ! 119: continue; ! 120: if (mdp->m_attr & MVOLUME) ! 121: volume = mdp; ! 122: if isdir(mdp) ! 123: newdir(dp, mdp, dirclusters(mdp) * mdirsize); ! 124: } ! 125: } ! 126: ! 127: /* ! 128: * Replace one or more files on the MS-DOS file system. ! 129: */ ! 130: void ! 131: replace(nargs, args) short nargs; char *args[]; ! 132: { ! 133: register char **ap; ! 134: struct stat s; ! 135: ! 136: if ((clbuf = malloc(clsize * ssize)) == NULL) ! 137: fatal("cluster buffer allocation failed"); ! 138: if (nargs == 0) ! 139: replacedir(NULL); ! 140: else if (!strcmp(args[0], "-") || pflag) { ! 141: pflag = 1; ! 142: if (nargs!=1) ! 143: fatal("replace: exactly one file required with 'p' option"); ! 144: replacefile(args[0]); ! 145: } else for (ap=args; nargs; ap++, nargs--) { ! 146: if (stat(*ap, &s) == -1) ! 147: fatal("replace: \"%s\" not found", *ap); ! 148: ! 149: if (strncmp(*ap, "./", 2) == 0) ! 150: *ap += 2; ! 151: ! 152: if (strcmp(*ap, ".") == 0) ! 153: { ! 154: replacedir(NULL); ! 155: break; ! 156: } ! 157: ! 158: base = basehold; ! 159: strcpy(base,*ap); ! 160: ! 161: if (s.st_mode & S_IFDIR) { ! 162: if (!sflag) ! 163: replacedir(*ap); ! 164: } ! 165: else ! 166: replacefile(*ap); ! 167: } ! 168: free(clbuf); ! 169: } ! 170: ! 171: /* ! 172: * Replace a directory; NULL means ".". ! 173: * Replace subdirectories recursively unless sflag. ! 174: */ ! 175: void ! 176: replacedir(name) char *name; ! 177: { ! 178: register struct direct *dirp; ! 179: register char *cp; ! 180: short fd; ! 181: struct stat s; ! 182: char dirbuf[sizeof(struct direct) + 1]; ! 183: char namebuf[NAMEMAX]; ! 184: ! 185: dbprintf(("replacedir(%s)\n", name)); ! 186: if (name == NULL || strcmp(name, ".") == 0) { ! 187: name = "."; ! 188: cp = namebuf; ! 189: } else { ! 190: strcpy(namebuf, name); ! 191: strcat(namebuf, "/"); ! 192: cp = &namebuf[strlen(namebuf)]; ! 193: } ! 194: dirp = dirbuf; ! 195: dirbuf[sizeof(struct direct)] = '\0'; /* NUL-terminate d_name */ ! 196: if ((fd = open(name, 0)) == -1) ! 197: fatal("cannot search directory \"%s\"", name); ! 198: while(read(fd,dirbuf, sizeof(struct direct))==sizeof(struct direct)) { ! 199: if (dirp->d_ino == 0 ! 200: || strcmp(dirp->d_name, ".") == 0 ! 201: || strcmp(dirp->d_name, "..") == 0) ! 202: continue; ! 203: strncpy(cp, dirp->d_name, DIRSIZ); ! 204: cp[strlen(dirp->d_name)] = '\0'; ! 205: ! 206: if (stat(namebuf, &s) == -1) ! 207: fatal("replacedir botch"); ! 208: else if (s.st_mode & S_IFDIR) { ! 209: if (!sflag) ! 210: replacedir(namebuf); ! 211: } ! 212: else if (s.st_mode & S_IFREG) ! 213: replacefile(namebuf); ! 214: } ! 215: close(fd); ! 216: } ! 217: ! 218: /* ! 219: * Replace a file. ! 220: */ ! 221: void ! 222: replacefile(file) char *file; ! 223: { ! 224: register MDIR *mdp; ! 225: register short nread; ! 226: DIR *dp; ! 227: FILE *ifp; ! 228: char *cp, *filename; ! 229: short writesize; ! 230: unsigned short next, prev; ! 231: char *tmp, tmp2[6], *files; ! 232: ! 233: if (!pflag && !oldstyle) { ! 234: if (!bflag && ((tmp = strrchr(file, '.')) != NULL)) { ! 235: sprintf(tmp2, "%s.", tmp); ! 236: if (!aflag) ! 237: aflag = (strstr(ext, tmp2) != NULL) ? 1 : 0; ! 238: } ! 239: } ! 240: ! 241: /* Create the file in the appropriate directory. */ ! 242: dbprintf(("replacefile(%s)\n", file)); ! 243: files = makef(file, 0); ! 244: ! 245: if ((cp = strrchr(files, '/')) == NULL) { ! 246: filename = files; ! 247: dp = root; ! 248: } else { ! 249: filename = cp + 1; ! 250: *cp = '\0'; /* NUL-terminate dirname */ ! 251: dp = creatdir(files); /* find the directory */ ! 252: *cp = '/'; /* restore the / */ ! 253: } ! 254: ! 255: mdp = creatfile(filename, dp); /* create the file */ ! 256: ! 257: /* Read from the COHERENT file and write the MS-DOS file. */ ! 258: if (vflag) ! 259: fprintf(stderr, "r %s\n", file); ! 260: if (pflag) ! 261: ifp = stdin; ! 262: else if ((ifp = fopen(file, "r")) == NULL) ! 263: fatal("replace: cannot open \"%s\"", file); ! 264: writesize = clsize * ssize; ! 265: for (prev = 0; ; prev = next) { ! 266: if ((nread = finput(ifp, clbuf, writesize)) == 0) ! 267: break; ! 268: mdp->m_size += nread; ! 269: next = freecluster(); ! 270: if (prev == 0) ! 271: mdp->m_cluster = next; ! 272: else ! 273: putcluster(prev, next); ! 274: diskwrite(clbuf, cltosec(next), clsize, file); ! 275: if (nread < writesize) ! 276: break; ! 277: } ! 278: if (nread < 0) ! 279: fatal("replace: read error on file \"%s\"", file); ! 280: if (!pflag) ! 281: fclose(ifp); ! 282: dostime(mdp, file); ! 283: } ! 284: ! 285: #define NUM_D_RES 13 ! 286: ! 287: int istrcmp(); ! 288: ! 289: char * d_reserved[NUM_D_RES] = ! 290: { ! 291: "aux", ! 292: "clock$", ! 293: "con", ! 294: "com1", ! 295: "com2", ! 296: "com3", ! 297: "com4", ! 298: "lpt1", ! 299: "lpt2", ! 300: "lpt3", ! 301: "lpt4", ! 302: "nul", ! 303: "prn" ! 304: }; ! 305: ! 306: /* ! 307: * Make a full path from base and name ! 308: */ ! 309: char * makef(name, cr) char * name; short cr; ! 310: { ! 311: static char tname[80]; ! 312: register char *t = tname, *h; ! 313: struct stat s; ! 314: short done = 0, rs; ! 315: register MDIR *mdp; ! 316: short srcd, destd, deste; ! 317: ! 318: if (base1) { ! 319: strcpy(t, base1); ! 320: t += strlen(base1); ! 321: ! 322: if (cr) { ! 323: srcd = isdir_keep; ! 324: rs = stat(base1, &s); ! 325: deste = (rs == 0); ! 326: destd = (s.st_mode & S_IFDIR); ! 327: } ! 328: else { ! 329: mdp = find(base1,root,NULL); ! 330: deste = (mdp != NULL); ! 331: destd = isdir(mdp); ! 332: if (!pflag) ! 333: { ! 334: stat(base, &s); ! 335: srcd = (s.st_mode & S_IFDIR); ! 336: } ! 337: else ! 338: srcd = 0; ! 339: } ! 340: ! 341: /* dbprintf(("numargs = %d, deste = %d, destd = %d, srcd = %d\n",numargs,deste,destd,srcd));*/ ! 342: ! 343: if (pflag) ! 344: if (destd) ! 345: fatal("Error: <%s> is a directory", base1); ! 346: else ! 347: done = 1; ! 348: ! 349: if ((numargs > 1) && (deste) && !(destd)) ! 350: fatal("Error: <%s> is a file", base1); ! 351: ! 352: if (numargs == 1) { ! 353: if (!deste) { ! 354: if (!srcd) ! 355: done = 1; ! 356: } ! 357: else { ! 358: if (!destd) { ! 359: if (srcd) ! 360: fatal("Error: <%s> is a file" ! 361: , base1); ! 362: else ! 363: done = 1; ! 364: } ! 365: } ! 366: } ! 367: } ! 368: ! 369: if (!done) { ! 370: if ((h = fequiv(name)) != NULL) { ! 371: if (base1) ! 372: *t++ = '/'; ! 373: strcpy(t, h); ! 374: } ! 375: } ! 376: ! 377: if (cr) ! 378: maketree(tname); ! 379: ! 380: if ((t = strrchr(tname, '/')) != NULL) ! 381: t++; ! 382: else ! 383: t = tname; ! 384: ! 385: if (bsearch(t, d_reserved, NUM_D_RES, sizeof (char *), istrcmp) != NULL) ! 386: { ! 387: printf("Dos reserved name used <%s>. Changing filename to <%s!>\n", ! 388: t, t); ! 389: rs = strlen(t); ! 390: t[rs] = '!'; ! 391: t[rs+1] = '\0'; ! 392: } ! 393: ! 394: ! 395: dbprintf(("base = <%s>, base1 = <%s>\n name = <%s>, tname = <%s>\n", base, base1, name, tname)); ! 396: return tname; ! 397: } ! 398: ! 399: istrcmp(a, b) ! 400: char *a, **b; ! 401: { ! 402: return strcmp(a,*b); ! 403: } ! 404: ! 405: char *fequiv(name) char *name; ! 406: { ! 407: char *tmp; ! 408: short basesize; ! 409: ! 410: if (!base) /* No base at all means a full disk copy */ ! 411: return name; ! 412: /* No path means return the whole name */ ! 413: if (strchr(name, '/') == NULL) ! 414: return name; ! 415: ! 416: if (!strcmp(base, name)) /* No wc or subdir means return the fname */ ! 417: return strrchr(name, '/') + 1; ! 418: ! 419: tmp = strrchr(base + 1, '/'); ! 420: ! 421: if (tmp != NULL) ! 422: basesize = tmp-base; ! 423: else ! 424: basesize = strlen(base); ! 425: ! 426: return name + basesize + 1; ! 427: } ! 428: ! 429: maketree(name) char *name; ! 430: { ! 431: ! 432: char *h, c[80]; ! 433: struct stat s; ! 434: ! 435: h = strchr(name, '/'); ! 436: while (h) { ! 437: *h = '\0'; ! 438: if (stat(name, &s) == -1) { ! 439: sprintf(c, "mkdir %s", name); ! 440: system(c); ! 441: if (stat(name, &s) == -1) ! 442: fatal("Cannot create directory %s", name); ! 443: } ! 444: *h = '/'; ! 445: h = strchr(h+1, '/'); ! 446: } ! 447: } ! 448: ! 449: ! 450: ! 451: ! 452: ! 453: ! 454: /* ! 455: * Produce a listing of the MS-DOS file system. ! 456: */ ! 457: void ! 458: table(nargs, args) short nargs; char *args[]; ! 459: { ! 460: register unsigned short n, i; ! 461: register char **ap, *npap, *temp; ! 462: register MDIR *mdp; ! 463: DIR *dp; ! 464: short free, bad, reserved; ! 465: char buf[12]; ! 466: ! 467: if (vflag) { ! 468: /* Print media information. */ ! 469: free = bad = reserved = 0; ! 470: for (n = 2; n <= maxcluster; n++) ! 471: if ((i = getcluster(n)) == 0) ! 472: ++free; ! 473: else if (i == CLBAD) ! 474: ++bad; ! 475: else if (i > CLMAX && i < CLBAD) ! 476: ++reserved; ! 477: if (volume == NULL) ! 478: printf("Unlabelled disk:\n"); ! 479: else { ! 480: strncpy(buf, volume->m_name, 11); ! 481: buf[11] = '\0'; ! 482: printf("Volume in Drive %s is labeled %s\n",adev,buf); ! 483: } ! 484: printf("\t%lu bytes free\n", ! 485: (long unsigned)free*clsize*ssize); ! 486: if (bad) ! 487: printf("\t%ld bytes in bad sectors\n", ! 488: (long)bad*clsize*ssize); ! 489: if (reserved) ! 490: printf("\t%ld bytes in reserved sectors\n", ! 491: (long)reserved*clsize*ssize); ! 492: putchar('\n'); ! 493: } ! 494: if (nargs == 0) ! 495: tabledir(root, NULL); ! 496: else for (ap = args; *ap != NULL; ap++) { ! 497: if ((mdp = find(*ap, root, &dp)) == NULL) ! 498: nonfatal("%s not found", *ap); ! 499: else { ! 500: npap = (temp = strrchr(*ap, '/')) ? temp+1 : *ap; ! 501: do { ! 502: if((strcmp(npap,cohn(mdp->m_name)) == 0) ! 503: && isdir(mdp)) ! 504: ! 505: tabledir(dp, cohn(mdp->m_name)); ! 506: else ! 507: tablefile(mdp, cohn(mdp->m_name)); ! 508: } while (mdp = findnext(&dp)); ! 509: } ! 510: } ! 511: } ! 512: ! 513: /* ! 514: * Print a sorted directory. ! 515: * Suppress '.', '..' and volume label. ! 516: */ ! 517: void ! 518: tabledir(dp, name) register DIR *dp; char *name; ! 519: { ! 520: register MDIR *mdp; ! 521: register MDIR **pp, **beg, **end; ! 522: unsigned char c; ! 523: ! 524: if (name != NULL) ! 525: printf("Directory %s:\n", name); ! 526: if ((beg = pp = (MDIR **)malloc(dp->d_files * sizeof(MDIR *))) == NULL) ! 527: fatal("cannot allocate directory pointer table"); ! 528: for (mdp = dp->d_dir; mdp < dp->d_edp; mdp++) ! 529: if ((c = mdp->m_name[0]) != MFREE && c != MEMPTY && c != MMDIR ! 530: && (mdp->m_attr & MVOLUME) == 0) ! 531: *pp++ = mdp; ! 532: end = pp; ! 533: qsort(beg, end - beg, sizeof(MDIR *), namecmp); ! 534: for (pp = beg; pp < end; pp++) ! 535: tablefile(*pp, NULL); ! 536: free(beg); ! 537: putchar('\n'); ! 538: } ! 539: ! 540: /* ! 541: * Print a line describing a file. ! 542: */ ! 543: void ! 544: tablefile(mdp, name) register MDIR *mdp; char *name; ! 545: { ! 546: register short attr; ! 547: ! 548: if (vflag) { ! 549: attr = mdp->m_attr; ! 550: putchar((attr & MRONLY ) ? 'r' : '-'); ! 551: putchar((attr & MHIDDEN) ? 'h' : '-'); ! 552: putchar((attr & MSYSTEM) ? 's' : '-'); ! 553: putchar((attr & MVOLUME) ? 'v' : '-'); ! 554: putchar((attr & MARCHIV) ? 'a' : '-'); ! 555: putchar((attr & MSUBDIR) ? 'd' : '-'); ! 556: ! 557: printf(" %02d/%02d/%02d %02d:%02d %9ld ", ! 558: m_month(mdp), m_day(mdp), m_year(mdp)+80, ! 559: m_hour(mdp), m_min(mdp), (isdir(mdp)) ? ! 560: (long)dirclusters(mdp)*clsize*ssize : mdp->m_size); ! 561: } ! 562: ! 563: if (name == NULL) { ! 564: cohname(mdp->m_name, root); ! 565: name = cohfile; ! 566: } ! 567: printf("%s\n", name); ! 568: } ! 569: ! 570: ! 571: /* ! 572: * Convert NUL-terminated name to UPPERCASE in place. ! 573: */ ! 574: char * ! 575: uppercase(name) unsigned char *name; ! 576: { ! 577: register unsigned char *s; ! 578: register short c; ! 579: ! 580: for (s = name; (c = *s) != '\0'; s++) ! 581: if (islower(c)) ! 582: *s = toupper(c); ! 583: return name; ! 584: } ! 585: ! 586: /* ! 587: * Write the changed directories of the MS-DOS file system. ! 588: */ ! 589: void ! 590: writedir(dp) register DIR *dp; ! 591: { ! 592: register MDIR *mdp; ! 593: register unsigned short n; ! 594: ! 595: if (dp->d_child != NULL) ! 596: writedir(dp->d_child); ! 597: if (dp->d_sibling != NULL) ! 598: writedir(dp->d_sibling); ! 599: mdp = dp->d_dir; ! 600: dbprintf(("writedir(%s) flag=%u cl=%x blocks=%u mdp=%x\n", ! 601: dp->d_dname, dp->d_dirflag, dp->d_cluster, dp->d_dirblocks, mdp)); ! 602: ! 603: if (dp->d_dirflag == 0) ! 604: return; /* DIR was unchanged */ ! 605: if (dp->d_cluster == 0) /* Write the root */ ! 606: diskwrite(dp->d_dir, (long)dirbase, dp->d_dirblocks, "directory"); ! 607: else /* Write a subdirectory */ ! 608: for (mdp = dp->d_dir, n = dp->d_cluster; n <= CLMAX; n = getcluster(n)) { ! 609: diskwrite(mdp, cltosec(n), clsize, "subdirectory"); ! 610: mdp += mdirsize; ! 611: } ! 612: } ! 613: ! 614: /* end of dos4.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.