|
|
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.