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