File:  [MW Coherent from dump] / coherent / d / bin / dos / dos4.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Wed May 29 04:56:39 2019 UTC (7 years, 2 months ago) by root
Branches: MarkWilliams, MAIN
CVS tags: relic, HEAD
coherent

/* #define DEBUG 1*/
/* dos4.c */

#include "dos0.h"
char *fequiv();
/*
 * Compare two MDIR names.
 * Directories precede ordinary files.
 * Called by qsort().
 */
short
namecmp(mdpp1, mdpp2) MDIR **mdpp1, **mdpp2;
{
	register MDIR *mdp1, *mdp2;
	unsigned long t1, t2;

	mdp1 = *mdpp1;
	mdp2 = *mdpp2;
	if (isdir(mdp1) != isdir(mdp2))
		return (isdir(mdp1)) ? -1 : 1;
	if (nflag) {
		/*
		 * Compare by time with unsigned long compare.
		 * m_junk[10] is really the first byte of the time.
		 * Kludgy but it works.
		 */
		t1 = *(unsigned long *)&mdp1->m_junk[10];
		t2 = *(unsigned long *)&mdp2->m_junk[10];
		if (t1 != t2)
			return (t1 < t2) ? -1 : 1;
	}
	return strncmp(mdp1->m_name, mdp2->m_name, 11);
}

/*
 * Allocate a new DIR and link it into the DIR tree.
 * Initialize it with the supplied information.
 * Return a pointer to it.
 * The MDIR array is not allocated and read until required.
 */
DIR *
newdir(parent, mdp, files)
DIR *parent;
register MDIR *mdp;
short files;
{
	register DIR *dp;

	/* Allocate a new DIR. */
	dbprintf(("newdir(parent=\"%s\" mdp=%x files=%u): \n", (parent==NULL)?"<root>   ":parent->d_dname, mdp, files));
	if ((dp = (DIR *)malloc(sizeof(DIR))) == NULL)
		fatal("directory allocation failed");

	/* Initialize the DIR. */
	dp->d_parent = parent;
	dp->d_child = NULL;
	if (parent == NULL) {
		/* Root. */
		dp->d_sibling = NULL;
		dp->d_cluster = 0;
		strcpy(dp->d_dname, "<root>     ");
	} else {
		/* Subdirectory. */
		dp->d_sibling = parent->d_child;
		parent->d_child = dp;
		dp->d_cluster = mdp->m_cluster;
		strncpy(dp->d_dname, mdp->m_name, 11);
		dp->d_dname[11] = '\0';
	}
	dp->d_files = files;
	dp->d_dirblocks = (files * sizeof(MDIR) + ssize - 1) / ssize;
	dp->d_dir = dp->d_edp = NULL;
	dp->d_dirflag = 0;
	dbprintf(("\"%s\" cl=%x blocks=%u dp=%x\n", dp->d_dname, dp->d_cluster, dp->d_dirblocks, dp));
	return dp;
}

/*
 * Print a nonfatal error message.
 * Set the return status to 1.
 * Uses the nonportable "%r" format.
 */
void
nonfatal(x) char *x;
{
	fprintf(stderr, "dos: %r\n", &x);
	estat = 1;
}

/*
 * Allocate space for an MS-DOS directory.
 * Read in the directory unless dp is not root and its d_cluster is 0.
 */
void
readmdir(dp) register DIR *dp;
{
	register MDIR *mdp;
	register unsigned short n;

	dbprintf(("readmdir(%s) blocks=%u cl=%x\n", dp->d_dname, dp->d_dirblocks, dp->d_cluster));
	if ((mdp = (MDIR *)calloc(dp->d_dirblocks, ssize)) == NULL)
		fatal("directory allocation failed");
	dp->d_dir = mdp;
	dp->d_edp = mdp + dp->d_files;

	if (dp->d_cluster == 0) {
		if (dp->d_parent != NULL)
			return;			/* new subdirectory */
		diskread(mdp, (long)dirbase, dp->d_dirblocks, "directory");
	} else
		for (n = dp->d_cluster ; n <= CLMAX; n = getcluster(n)) {
			diskread(mdp, cltosec(n), clsize, "subdirectory");
			mdp += mdirsize;
		}

	/* Scan through the directory for volume label and subdirectories. */
	for (mdp = dp->d_dir; mdp < dp->d_edp; mdp++) {
		if ((n = mdp->m_name[0]) == MFREE || n == MEMPTY || n == MMDIR)
			continue;
		if (mdp->m_attr & MVOLUME)
			volume = mdp;
		if isdir(mdp)
			newdir(dp, mdp,	dirclusters(mdp) * mdirsize);
	}
}

/*
 * Replace one or more files on the MS-DOS file system.
 */
void
replace(nargs, args) short nargs; char *args[];
{
	register char **ap;
	struct stat s;

	if ((clbuf = malloc(clsize * ssize)) == NULL)
		fatal("cluster buffer allocation failed");
	if (nargs == 0)
		replacedir(NULL);
	else if (!strcmp(args[0], "-") || pflag) {
		pflag = 1;
		if (nargs!=1)
			fatal("replace: exactly one file required with 'p' option");
		replacefile(args[0]);
	} else for (ap=args; nargs; ap++, nargs--) {
		if (stat(*ap, &s) == -1)
			fatal("replace: \"%s\" not found", *ap);

		if (strncmp(*ap, "./", 2) == 0)
			*ap += 2;

		if (strcmp(*ap, ".") == 0)
		{
			replacedir(NULL);
			break;
		}

		base = basehold;
		strcpy(base,*ap);

		if (s.st_mode & S_IFDIR) {
			if (!sflag)
				replacedir(*ap);
		}
		else
			replacefile(*ap);
	}
	free(clbuf);
}

/*
 * Replace a directory; NULL means ".".
 * Replace subdirectories recursively unless sflag.
 */
void
replacedir(name) char *name;
{
	register struct direct *dirp;
	register char *cp;
	short fd;
	struct stat s;
	char dirbuf[sizeof(struct direct) + 1];
	char namebuf[NAMEMAX];

	dbprintf(("replacedir(%s)\n", name));
	if (name == NULL || strcmp(name, ".") == 0) {
		name = ".";
		cp = namebuf;
	} else {
		strcpy(namebuf, name);
		strcat(namebuf, "/");
		cp = &namebuf[strlen(namebuf)];
	}
	dirp = dirbuf;
	dirbuf[sizeof(struct direct)] = '\0';	/* NUL-terminate d_name */
	if ((fd = open(name, 0)) == -1)
		fatal("cannot search directory \"%s\"", name);
	while(read(fd,dirbuf, sizeof(struct direct))==sizeof(struct direct)) {
		if (dirp->d_ino == 0
		 || strcmp(dirp->d_name, ".") == 0
		 || strcmp(dirp->d_name, "..") == 0)
			continue;
		strncpy(cp, dirp->d_name, DIRSIZ);
		cp[strlen(dirp->d_name)] = '\0';

		if (stat(namebuf, &s) == -1)
			fatal("replacedir botch");
		else if (s.st_mode & S_IFDIR) {
			if (!sflag)
				replacedir(namebuf);
		}
		else if (s.st_mode & S_IFREG)
			replacefile(namebuf);
	}
	close(fd);
}

/*
 * Replace a file.
 */
void
replacefile(file) char *file;
{
	register MDIR *mdp;
	register short nread;
	DIR *dp;
	FILE *ifp;
	char *cp, *filename;
	short writesize;
	unsigned short next, prev;
	char *tmp, tmp2[6], *files;

	if (!pflag && !oldstyle) {
		if (!bflag && ((tmp = strrchr(file, '.')) != NULL)) {
			sprintf(tmp2, "%s.", tmp);
			if (!aflag)
				aflag = (strstr(ext, tmp2) != NULL) ? 1 : 0;
		}
	}

	/* Create the file in the appropriate directory. */
	dbprintf(("replacefile(%s)\n", file));
	files = makef(file, 0);

	if ((cp = strrchr(files, '/')) == NULL) {
		filename = files;
		dp = root;
	} else {
		filename = cp + 1;
		*cp = '\0';			/* NUL-terminate dirname */
		dp = creatdir(files);		/* find the directory */
		*cp = '/';			/* restore the / */
	}

	mdp = creatfile(filename, dp);		/* create the file */

	/* Read from the COHERENT file and write the MS-DOS file. */
	if (vflag)
		fprintf(stderr, "r %s\n", file);
	if (pflag)
		ifp = stdin;
	else if ((ifp = fopen(file, "r")) == NULL)
		fatal("replace: cannot open \"%s\"", file);
	writesize = clsize * ssize;
	for (prev = 0; ; prev = next) {
		if ((nread = finput(ifp, clbuf, writesize)) == 0)
			break;
		mdp->m_size += nread;
		next = freecluster();
		if (prev == 0)
			mdp->m_cluster = next;
		else
			putcluster(prev, next);
		diskwrite(clbuf, cltosec(next), clsize, file);
		if (nread < writesize)
			break;
	}
	if (nread < 0)
		fatal("replace: read error on file \"%s\"", file);
	if (!pflag)
		fclose(ifp);
	dostime(mdp, file);
}

#define NUM_D_RES	13

int istrcmp();

char * d_reserved[NUM_D_RES] =
{
    "aux",
    "clock$",
    "con",
    "com1",
    "com2",
    "com3",
    "com4",
    "lpt1",
    "lpt2",
    "lpt3",
    "lpt4",
    "nul",
    "prn"
};

/*
 * Make a full path from base and name
 */
char * makef(name, cr) char * name; short cr;
{
	static char tname[80];
	register char  *t = tname, *h;
	struct stat s;
	short done = 0, rs;
	register MDIR *mdp;
	short srcd, destd, deste;

	if (base1) {
		strcpy(t, base1);
		t += strlen(base1);

		if (cr) {
			srcd = isdir_keep;
			rs = stat(base1, &s);
			deste = (rs == 0);
			destd = (s.st_mode & S_IFDIR);
		}
		else {
			mdp = find(base1,root,NULL);
			deste = (mdp != NULL);
			destd = isdir(mdp);
			if (!pflag)
			{
				stat(base, &s);
				srcd = (s.st_mode & S_IFDIR);
			}
			else
				srcd = 0;
		}

/* dbprintf(("numargs = %d, deste = %d, destd = %d, srcd = %d\n",numargs,deste,destd,srcd));*/

		if (pflag)
			if (destd)
				fatal("Error: <%s> is a directory", base1);
			else
				done = 1;

		if ((numargs > 1) && (deste) && !(destd))
			fatal("Error: <%s> is a file", base1);
		
		if (numargs == 1) {
			if (!deste) {
				if (!srcd)
					done = 1;
			}
			else {
				if (!destd) {
					if (srcd)
						fatal("Error: <%s> is a file"
								, base1);
					else
						done = 1;
				}
			}
		}
	}

	if (!done) {
		if ((h = fequiv(name)) != NULL) {
			if (base1)
				*t++ = '/';
			strcpy(t, h);
		}
	}

	if (cr)
		maketree(tname);

        if ((t = strrchr(tname, '/')) != NULL)
	    t++;
	else
	    t = tname;

	if (bsearch(t, d_reserved, NUM_D_RES, sizeof (char *), istrcmp) != NULL)
	{
	    printf("Dos reserved name used <%s>. Changing filename to <%s!>\n",
			t, t);
            rs = strlen(t);
	    t[rs] = '!';
	    t[rs+1] = '\0';
	}


dbprintf(("base = <%s>, base1 = <%s>\n  name = <%s>, tname = <%s>\n", base, base1, name, tname));
	return tname;
}

istrcmp(a, b)
char *a, **b;
{
    return strcmp(a,*b);
}

char *fequiv(name) char *name;
{
	char *tmp;
	short basesize;

	if (!base)		/* No base at all means a full disk copy */
		return name;
				/* No path means return the whole name */
	if (strchr(name, '/') == NULL)
		return name;

	if (!strcmp(base, name))  /* No wc or subdir means return the fname */
		return strrchr(name, '/') + 1;

	tmp = strrchr(base + 1, '/');

	if (tmp != NULL)
		basesize = tmp-base;
	else
		basesize = strlen(base);

	return name + basesize + 1;
}

maketree(name) char *name;
{

	char *h, c[80];
	struct stat s;

	h = strchr(name, '/');
	while (h) {
		*h = '\0';
		if (stat(name, &s) == -1) {
			sprintf(c, "mkdir %s", name);	
			system(c);
			if (stat(name, &s) == -1)
				fatal("Cannot create directory %s", name);
			}
		*h = '/';
		h = strchr(h+1, '/');		
	}
}
				





/*
 * Produce a listing of the MS-DOS file system.
 */
void
table(nargs, args) short nargs; char *args[];
{
	register unsigned short n, i;
	register char **ap, *npap, *temp;
	register MDIR *mdp;
	DIR *dp;
	short free, bad, reserved;
	char buf[12];

	if (vflag) {
		/* Print media information. */
		free = bad = reserved = 0;
		for (n = 2; n <= maxcluster; n++)
			if ((i = getcluster(n)) == 0)
				++free;
			else if (i == CLBAD)
				++bad;
			else if (i > CLMAX && i < CLBAD)
				++reserved;
		if (volume == NULL)
			printf("Unlabelled disk:\n");
		else {
			strncpy(buf, volume->m_name, 11);
			buf[11] = '\0';
			printf("Volume in Drive %s is labeled %s\n",adev,buf);
		}
		printf("\t%lu bytes free\n",
			(long unsigned)free*clsize*ssize);
		if (bad)
			printf("\t%ld bytes in bad sectors\n",
				(long)bad*clsize*ssize);
		if (reserved)
			printf("\t%ld bytes in reserved sectors\n",
				(long)reserved*clsize*ssize);
		putchar('\n');
	}
	if (nargs == 0)
		tabledir(root, NULL);
	else for (ap = args; *ap != NULL; ap++) {
		if ((mdp = find(*ap, root, &dp)) == NULL)
			nonfatal("%s not found", *ap);
		else {
			npap = (temp = strrchr(*ap, '/')) ? temp+1 : *ap;
			do {
				if((strcmp(npap,cohn(mdp->m_name)) == 0)
							    && isdir(mdp))

					tabledir(dp, cohn(mdp->m_name));
				else
					tablefile(mdp, cohn(mdp->m_name));
			} while (mdp = findnext(&dp));
		}
	}
}

/*
 * Print a sorted directory.
 * Suppress '.', '..' and volume label.
 */
void
tabledir(dp, name) register DIR *dp; char *name;
{
	register MDIR *mdp;
	register MDIR **pp, **beg, **end;
	unsigned char c;

	if (name != NULL)
		printf("Directory %s:\n", name);
	if ((beg = pp = (MDIR **)malloc(dp->d_files * sizeof(MDIR *))) == NULL)
		fatal("cannot allocate directory pointer table");
	for (mdp = dp->d_dir; mdp < dp->d_edp; mdp++)
		if ((c = mdp->m_name[0]) != MFREE && c != MEMPTY && c != MMDIR
		 && (mdp->m_attr & MVOLUME) == 0)
			*pp++ = mdp;
	end = pp;
	qsort(beg, end - beg, sizeof(MDIR *), namecmp);
	for (pp = beg; pp < end; pp++)
		tablefile(*pp, NULL);
	free(beg);
	putchar('\n');
}

/*
 * Print a line describing a file.
 */
void
tablefile(mdp, name) register MDIR *mdp; char *name;
{
	register short attr;

	if (vflag) {
		attr = mdp->m_attr;
		putchar((attr & MRONLY ) ? 'r' : '-');
		putchar((attr & MHIDDEN) ? 'h' : '-');
		putchar((attr & MSYSTEM) ? 's' : '-');
		putchar((attr & MVOLUME) ? 'v' : '-');
		putchar((attr & MARCHIV) ? 'a' : '-');
		putchar((attr & MSUBDIR) ? 'd' : '-');

		printf("  %02d/%02d/%02d %02d:%02d %9ld  ",
			m_month(mdp), m_day(mdp), m_year(mdp)+80,
			m_hour(mdp),  m_min(mdp), (isdir(mdp)) ?
			   (long)dirclusters(mdp)*clsize*ssize : mdp->m_size);
	}

	if (name == NULL) {
		cohname(mdp->m_name, root);
		name = cohfile;
	}
	printf("%s\n", name);
}


/*
 * Convert NUL-terminated name to UPPERCASE in place.
 */
char *
uppercase(name) unsigned char *name;
{
	register unsigned char *s;
	register short c;

	for (s = name; (c = *s) != '\0'; s++)
		if (islower(c))
			*s = toupper(c);
	return name;
}

/*
 * Write the changed directories of the MS-DOS file system.
 */
void
writedir(dp) register DIR *dp;
{
	register MDIR *mdp;
	register unsigned short n;

	if (dp->d_child != NULL)
		writedir(dp->d_child);
	if (dp->d_sibling != NULL)
		writedir(dp->d_sibling);
	mdp = dp->d_dir;
	dbprintf(("writedir(%s) flag=%u cl=%x blocks=%u mdp=%x\n",
	      dp->d_dname, dp->d_dirflag, dp->d_cluster, dp->d_dirblocks, mdp));

	if (dp->d_dirflag == 0)
		return;				/* DIR was unchanged */
	if (dp->d_cluster == 0)			/* Write the root */
		diskwrite(dp->d_dir, (long)dirbase, dp->d_dirblocks, "directory");
	else					/* Write a subdirectory */
		for (mdp = dp->d_dir, n = dp->d_cluster; n <= CLMAX; n = getcluster(n)) {
			diskwrite(mdp, cltosec(n), clsize, "subdirectory");
			mdp += mdirsize;
		}
}

/* end of dos4.c */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.