|
|
1.1 ! root 1: /*#define DEBUG 1*/ ! 2: /* dos.c */ ! 3: ! 4: #include "dos0.h" ! 5: ! 6: /* ! 7: * Convert an MS-DOS filename and path ! 8: * to a NUL-terminated COHERENT filename in cohfile[]. ! 9: * Return a pointer to the NUL terminator. ! 10: */ ! 11: char * ! 12: cohname(name, dp) register char *name; DIR *dp; ! 13: { ! 14: register char *cp; ! 15: ! 16: if (dp == root) ! 17: cp = cohfile; ! 18: else { ! 19: cp = cohname(dp->d_dname, dp->d_parent); ! 20: *cp++ = '/'; ! 21: *cp = '\0'; ! 22: } ! 23: cp = lcname(cp, name, 8); ! 24: name += 8; ! 25: if (*name != ' ') { ! 26: *cp++ = '.'; ! 27: cp = lcname(cp, name, 3); ! 28: } ! 29: return cp; ! 30: } ! 31: ! 32: /* ! 33: * Change the COHERENT time of the given file to the MS-DOS time of mdp. ! 34: * There should be a COHERENT function which converts struct tm to time_t, ! 35: * but in the meantime this does it by hand. What a pain. ! 36: */ ! 37: void ! 38: cohtime(file, mdp) char *file; MDIR *mdp; ! 39: { ! 40: time_t cohtime, times[2]; ! 41: static short mdays[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; ! 42: ! 43: settz(); ! 44: cohtime = ((10 * 365L) + 2); /* days 1/1/70 to 1/1/80 */ ! 45: cohtime += (m_year(mdp) * 365L); /* to 1/1/year */ ! 46: if (m_month(mdp) > 2) /* leap year adjust */ ! 47: cohtime += ((m_year(mdp)+4)/4); ! 48: else ! 49: cohtime += ((m_year(mdp)+3)/4); ! 50: cohtime += mdays[m_month(mdp)-1]; /* to mon/1/year */ ! 51: cohtime += (m_day(mdp)-1); /* to mon/day/year */ ! 52: cohtime *= 24L; /* hours */ ! 53: cohtime += m_hour(mdp); ! 54: cohtime *= 60L; ! 55: cohtime += m_min(mdp); /* minutes */ ! 56: cohtime *= 60L; ! 57: cohtime += m_sec(mdp) * 2; /* seconds */ ! 58: cohtime += timezone; ! 59: times[0] = times[1] = cohtime; ! 60: if (utime(file, times) == -1) ! 61: fatal("cannot set time of file \"%s\"", file); ! 62: } ! 63: ! 64: /* ! 65: * Find or create an MS-DOS directory. ! 66: * Return a pointer to the DIR. ! 67: * Failure is always fatal. ! 68: */ ! 69: DIR * ! 70: creatdir(name) char *name; ! 71: { ! 72: register MDIR *mdp; ! 73: register char *cp; ! 74: DIR *dp, *ndp; ! 75: ! 76: /* Check if directory exists. */ ! 77: ! 78: if ((mdp = find(name, root, &dp)) != NULL) { ! 79: if (!isdir(mdp)) ! 80: { ! 81: if (mdp->m_attr & MVOLUME) ! 82: fatal("\"%s\" is the volume name, not a subdirectory", name); ! 83: else ! 84: fatal("\"%s\" is an MS-DOS file, not a subdirectory", name); ! 85: } ! 86: ! 87: return dp; ! 88: } ! 89: ! 90: /* Directory does not exist, create it. */ ! 91: dbprintf(("creatdir(%s)\n", name)); ! 92: if ((cp = strrchr(name, '/')) == NULL) { ! 93: dp = root; ! 94: mdp = creatfile(name, dp); /* create the dir in root */ ! 95: } else { ! 96: *cp = '\0'; /* NUL-terminate dirname */ ! 97: dp = creatdir(name); /* create the parent */ ! 98: *cp = '/'; /* restore the / */ ! 99: mdp = creatfile(cp + 1, dp); /* create the directory */ ! 100: } ! 101: if (vflag) ! 102: fprintf(stderr, "r %s/\n", name); ! 103: mdp->m_attr = MSUBDIR; ! 104: ndp = newdir(dp, mdp, mdirsize); ! 105: readmdir(ndp); ! 106: mdp->m_cluster = ndp->d_cluster = freecluster(); ! 107: mdp = ndp->d_dir; ! 108: mdirinit(mdp, ndp, ". ", MSUBDIR, ndp->d_cluster); ! 109: mdirinit(++mdp, ndp, ".. ", MSUBDIR, dp->d_cluster); ! 110: return ndp; ! 111: } ! 112: ! 113: /* ! 114: * Create an empty MS-DOS file. ! 115: * Delete the old one if it exists. ! 116: * Return a pointer to the initialized MDIR entry ! 117: * (name initialized, attribute==0, cluster==0, size==0L). ! 118: * Failure is always fatal. ! 119: */ ! 120: MDIR * ! 121: creatfile(name, dp) char *name; DIR *dp; ! 122: { ! 123: register MDIR *mdp; ! 124: unsigned short n, ofiles, next; ! 125: ! 126: /* Check if file exists. */ ! 127: dbprintf(("creatfile(%s, %s)\n", name, dp->d_dname)); ! 128: if ((mdp = find(name, dp, &dp)) != NULL) { ! 129: if isdir(mdp) ! 130: fatal("\"%s\" is an MS-DOS subdirectory", name); ! 131: deletefile(mdp, dp); /* delete the old one */ ! 132: } ! 133: ! 134: /* Find a slot for the file. */ ! 135: for (mdp = dp->d_dir; mdp < dp->d_edp; mdp++) ! 136: if (mdp->m_name[0] == MEMPTY || mdp->m_name[0] == MFREE) ! 137: break; ! 138: if (mdp == dp->d_edp) { ! 139: /* Out of directory space. Fatal on root. */ ! 140: if (dp == root) ! 141: fatal("replace: out of root directory space for \"%s\"", name); ! 142: /* Add a cluster to a subdirectory. */ ! 143: for (n = dp->d_cluster; (next = getcluster(n)) <= CLMAX; n = next) ! 144: ; ! 145: putcluster(n, freecluster()); ! 146: dp->d_dirblocks += clsize; ! 147: ofiles = dp->d_files; ! 148: dp->d_files += mdirsize; ! 149: if ((dp->d_dir = (MDIR *)realloc(dp->d_dir, dp->d_dirblocks * ssize)) == NULL) ! 150: fatal("replace: out of space to grow subdirectory"); ! 151: dbprintf(("creatfile: grow \"%s\" dp=%x at d_dir=%x\n", dp->d_dname, dp, dp->d_dir)); ! 152: dp->d_edp = dp->d_dir + dp->d_files; ! 153: for (mdp = dp->d_dir + ofiles + 1; mdp < dp->d_edp; mdp++) ! 154: mdp->m_name[0] = MFREE; ! 155: mdp = dp->d_dir + ofiles; ! 156: } ! 157: mdirinit(mdp, dp, dosname(name), MARCHIV, 0); ! 158: return mdp; ! 159: } ! 160: ! 161: /* ! 162: * Delete specified files. ! 163: */ ! 164: void ! 165: delete(nargs, args) short nargs; char *args[]; ! 166: { ! 167: register MDIR *mdp; ! 168: register char **ap; ! 169: DIR *dp; ! 170: ! 171: if (nargs == 0) ! 172: fatal("delete: must specify files"); ! 173: for (ap = args; *ap != NULL; ap++) { ! 174: if (vflag) ! 175: fprintf(stderr, "d %s\n", *ap); ! 176: if ((mdp = find(*ap, root, &dp)) == NULL) ! 177: nonfatal("delete: \"%s\" not found", *ap); ! 178: else { ! 179: do { ! 180: if isdir(mdp) ! 181: deletedir(mdp, dp, cohn(mdp->m_name)); ! 182: else ! 183: deletefile(mdp, dp); ! 184: } while (mdp = findnext(&dp)); ! 185: } ! 186: } ! 187: } ! 188: ! 189: /* ! 190: * Delete a subdirectory. ! 191: * Make sure it is empty first. ! 192: */ ! 193: void ! 194: deletedir(mdp, dp, name) MDIR *mdp; DIR *dp; char *name; ! 195: { ! 196: register MDIR *mdp2; ! 197: register DIR **dpp; ! 198: short c; ! 199: ! 200: /* Make sure subdirectory is empty. */ ! 201: for (mdp2 = dp->d_dir; mdp2 < dp->d_edp; mdp2++) ! 202: if ((c = mdp2->m_name[0])!=MFREE && c!=MEMPTY && c!=MMDIR) { ! 203: nonfatal("delete: subdirectory \"%s\" not empty",name); ! 204: return; ! 205: } ! 206: ! 207: /* Delete the subdirectory entry and free its MDIR. */ ! 208: deletefile(mdp, dp->d_parent); ! 209: free(dp->d_dir); ! 210: ! 211: /* Remove the DIR from the chain and free it. */ ! 212: for (dpp = &(dp->d_parent->d_child); *dpp != NULL; dpp = &((*dpp)->d_sibling)) ! 213: if (*dpp == dp) ! 214: break; ! 215: if (*dpp == NULL) ! 216: fatal("deletedir botch"); ! 217: *dpp = dp->d_sibling; ! 218: free(dp); ! 219: } ! 220: ! 221: /* ! 222: * Delete a file. ! 223: * Free the clusters in its FAT chain. ! 224: * Free the directory entry. ! 225: * Set the dirflag requiring the directory to be updated. ! 226: */ ! 227: void ! 228: deletefile(mdp, dp) MDIR *mdp; DIR *dp; ! 229: { ! 230: register unsigned short n, next; ! 231: ! 232: if ((mdp->m_attr & MRONLY) && !fflag) ! 233: { ! 234: nonfatal("cannot delete %s\n", cohn(mdp->m_name)); ! 235: return; ! 236: } ! 237: ! 238: dp->d_dirflag = 1; ! 239: mdp->m_name[0] = MEMPTY; /* zap the MDIR entry */ ! 240: if (mdp->m_cluster == 0) ! 241: return; /* no chain */ ! 242: for (n = mdp->m_cluster; n <= CLMAX; n = next) { ! 243: next = getcluster(n); ! 244: putcluster(n, CLFREE); ! 245: } ! 246: mdp->m_cluster = CLFREE; ! 247: } ! 248: ! 249: /* ! 250: * Return the size in clusters of the directory starting at n. ! 251: */ ! 252: unsigned short ! 253: dirclusters(mdp) MDIR *mdp; ! 254: { ! 255: register unsigned short n, count; ! 256: ! 257: for (n = mdp->m_cluster, count = 1; (n = getcluster(n)) <= CLMAX; ++count) ! 258: ; ! 259: return count; ! 260: } ! 261: ! 262: /* ! 263: * Map a COHERENT filename to an 11-character MS-DOS name (plus NUL terminator) ! 264: * in the static buffer and return a pointer to it. ! 265: * There is no good way, thanks to different filename lengths and '.'. ! 266: * Special hacks: ".profile" -> "_PROFILE", "a.b.c" -> "A_B.C". ! 267: */ ! 268: char * ! 269: dosname(name) register char *name; ! 270: { ! 271: register char *s, *dotp; ! 272: char c; ! 273: static char buf[16]; ! 274: ! 275: dotp = strrchr(name, '.'); ! 276: if (dotp == name) ! 277: dotp = NULL; ! 278: for (s = buf; name != dotp && (c = *name) != '\0'; name++) ! 279: if (s < &buf[8]) /* copy name */ ! 280: *s++ = (c == '.') ? '_' : c; ! 281: while (s < &buf[8]) ! 282: *s++ = ' '; /* space-pad name */ ! 283: if (name++ == dotp) ! 284: for ( ; *name != '\0'; name++) ! 285: if (s <= &buf[11]) ! 286: *s++ = *name; /* copy extension */ ! 287: while (s < &buf[11]) ! 288: *s++ = ' '; /* space-pad extension */ ! 289: *s = '\0'; /* NUL terminate */ ! 290: uppercase(buf); /* map to UPPER */ ! 291: return buf; ! 292: } ! 293: ! 294: /* ! 295: * Set the time of an MS-DOS directory entry. ! 296: * Use the mtime of file if kflag and file is not NULL, ! 297: * otherwise use the current time. ! 298: */ ! 299: void ! 300: dostime(mdp, file) register MDIR *mdp; char *file; ! 301: { ! 302: register struct tm *tmp; ! 303: struct stat s; ! 304: time_t t; ! 305: ! 306: if (kflag && file != NULL) { ! 307: if (stat(file, &s) == -1) ! 308: fatal("cannot stat \"%s\"", file); ! 309: t = s.st_mtime; ! 310: } else ! 311: t = time(NULL); ! 312: tmp = localtime(&t); ! 313: mdp->m_time = ! 314: c_sec(tmp->tm_sec/2) | c_min(tmp->tm_min) | c_hour(tmp->tm_hour); ! 315: mdp->m_date = ! 316: c_day(tmp->tm_mday)|c_month(tmp->tm_mon+1)|c_year(tmp->tm_year-80); ! 317: } ! 318: ! 319: /* ! 320: * creat a directory on a dos disk ! 321: */ ! 322: void ! 323: createdir(nargs, args) short nargs; char *args[]; ! 324: { ! 325: creatdir(*args); ! 326: } ! 327: ! 328: ! 329: /* ! 330: * Extract files from MS-DOS file system. ! 331: */ ! 332: void ! 333: extract(nargs, args) short nargs; char *args[]; ! 334: { ! 335: register MDIR *mdp; ! 336: register char **ap; ! 337: char *argsd[512], *argsf[512]; ! 338: short dnargs = 0, fnargs = 0; ! 339: char *tmp; ! 340: DIR *dp; ! 341: ! 342: if ((clbuf = malloc(clsize * ssize)) == NULL) ! 343: fatal("cluster buffer allocation failed"); ! 344: if (pflag && nargs!=1) ! 345: fatal("extract: exactly one file required with 'p' option"); ! 346: if (nargs == 0) ! 347: extractdir(root); ! 348: else { ! 349: if ((mdp = find(args[0], root, &dp)) == NULL) ! 350: nonfatal("extract: file \"%s\" not found", *ap); ! 351: else { ! 352: do { ! 353: cohname(mdp->m_name, dp); ! 354: if (isdir(mdp)) { ! 355: if (!sflag) { ! 356: argsd[dnargs] = ! 357: malloc(strlen(cohfile)+1); ! 358: strcpy(argsd[dnargs++], ! 359: cohfile); ! 360: } ! 361: } ! 362: else { ! 363: argsf[fnargs] = ! 364: malloc(strlen(cohfile) + 1); ! 365: strcpy(argsf[fnargs++],cohfile); ! 366: } ! 367: } while (mdp = findnext(&dp)); ! 368: numargs = fnargs + (sflag ? 0 : dnargs); ! 369: if (fnargs > 0) { ! 370: for (ap = argsf; fnargs ; ap++, fnargs--) { ! 371: isdir_keep = 0; ! 372: mdp = find(*ap, root, &dp); ! 373: base = basehold; ! 374: strcpy(base,*ap); ! 375: extractfile(mdp, dp); ! 376: } ! 377: } ! 378: if ((!sflag) && (dnargs > 0)) { ! 379: for (ap = argsd; dnargs ; ap++, dnargs--) { ! 380: isdir_keep = 1; ! 381: mdp = find(*ap, root, &dp); ! 382: base = basehold; ! 383: strcpy(base,*ap); ! 384: extractdir(dp); ! 385: } ! 386: } ! 387: } ! 388: } ! 389: free(clbuf); ! 390: } ! 391: ! 392: /* ! 393: * Extract a directory. ! 394: * Extract subdirectories recursively unless sflag. ! 395: */ ! 396: void ! 397: extractdir(dp) register DIR *dp; ! 398: { ! 399: register MDIR *mdp; ! 400: DIR *dp2; ! 401: unsigned char c; ! 402: struct stat s; ! 403: short freeflag; ! 404: ! 405: freeflag = 0; ! 406: if (!sflag) { ! 407: if (dp->d_dir == NULL) { ! 408: readmdir(dp); /* read the DOS directory */ ! 409: freeflag = 1; /* and set a flag */ ! 410: } ! 411: if (dp != root) { ! 412: cohname(dp->d_dname, dp->d_parent); ! 413: if (stat(cohfile, &s) == -1) { ! 414: /* COHERENT directory not found, create it. */ ! 415: if (vflag) ! 416: fprintf(stderr, "x %s/\n", cohfile); ! 417: if (oldstyle) ! 418: if (system(strcat(strcpy(cmd, "mkdir "), cohfile)) != 0) ! 419: fatal("cannot create directory \"%s\"", cohfile); ! 420: } else if ((s.st_mode & S_IFDIR) == 0) ! 421: fatal("\"%s\" exists but is not a directory", ! 422: cohfile); ! 423: } ! 424: for (dp2 = dp->d_child; dp2 != NULL; dp2 = dp2->d_sibling) ! 425: extractdir(dp2); /* extract subdirectory */ ! 426: } ! 427: for (mdp = dp->d_dir; mdp < dp->d_edp; mdp++) ! 428: if ((c = mdp->m_name[0]) != MEMPTY && c != MFREE && c != MMDIR && !isdir(mdp)) ! 429: extractfile(mdp, dp); ! 430: if (freeflag) { ! 431: free(dp->d_dir); ! 432: dp->d_dir = dp->d_edp = NULL; ! 433: } ! 434: } ! 435: ! 436: /* ! 437: * Extract a file. ! 438: */ ! 439: void ! 440: extractfile(mdp, dp) register MDIR *mdp; DIR *dp; ! 441: { ! 442: register unsigned short cluster; ! 443: short readsize, i; ! 444: long size; ! 445: FILE *ofp; ! 446: char *tmp, tmp2[6], *mcohfile; ! 447: ! 448: if (mdp->m_attr & MVOLUME) ! 449: return; ! 450: ! 451: tmp = &(mdp->m_name[8]); ! 452: if (!oldstyle) { ! 453: if (!bflag && (*tmp != ' ')) { ! 454: tmp2[0] = '.'; ! 455: for (i=0; i< 3; i++) { ! 456: if (tmp[i] != ' ') ! 457: tmp2[i+1] = tolower(tmp[i]); ! 458: else ! 459: break; ! 460: } ! 461: tmp2[i+1] = '.'; ! 462: tmp2[i+2] = '\0'; ! 463: if (!aflag) ! 464: aflag = (strstr(ext, tmp2) != NULL) ? 1 : 0; ! 465: } ! 466: } ! 467: ! 468: dbprintf(("bflag=%d, aflag=%d, mdp->m_name=%s, tmp2=%s\n", bflag, aflag, mdp->m_name, tmp2)); ! 469: ! 470: /* Convert filename to COHERENT format and open the output file. */ ! 471: cohname(mdp->m_name, dp); ! 472: ! 473: if (pflag) ! 474: ofp = stdout; ! 475: else if ((ofp = fopen(mcohfile = makef(cohfile, 1), "w")) == NULL) ! 476: fatal("extract: cannot create file \"%s\"", mcohfile); ! 477: ! 478: if (vflag) ! 479: fprintf(stderr, "x %s\n", mcohfile); ! 480: ! 481: /* Read the MS-DOS file and write it to the COHERENT file. */ ! 482: readsize = clsize * ssize; ! 483: size = mdp->m_size; ! 484: for(cluster= mdp->m_cluster; size > 0; cluster = getcluster(cluster)){ ! 485: if (cluster > CLMAX) ! 486: fatal("extract: early EOF on file \"%s\"",mcohfile); ! 487: if (diskread(clbuf, cltosec(cluster), clsize)) ! 488: fatal("extract: read error on file \"%s\"", mcohfile); ! 489: if (size < readsize) ! 490: readsize = size; ! 491: foutput(mcohfile, ofp, clbuf, readsize); ! 492: size -= readsize; ! 493: } ! 494: if (!pflag) ! 495: fclose(ofp); ! 496: if (kflag) ! 497: cohtime(mcohfile, mdp); ! 498: } ! 499: ! 500: /* end of dos2.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.