File:  [MW Coherent from dump] / coherent / d / bin / mkdir.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

/*
 * mkdir.c
 * 5/10/90
 * Usage: mkdir [ -rp ] dir ...
 * Make directories.
 *
 * Changes by michael 5/10/93
 *      implemented -p option
 *
 * Changes by steve 5/10/90:
 *	in getchild(), bumped strncpy count by 1 to return NUL-terminated result
 *	in getparent(), hacked bogus "ending slash" code so that e.g.
 *		getparent("/foo") returns "/" rather than ""
 *
 * Changes by steve 4/12/90:
 *	corrected fatal() call
 *	added success return status to mkdir()
 *	improved return status of getchild()
 *	implemented -r option
 */

#include	<sys/dir.h>
#include	<sys/ino.h>
#include	<signal.h>
#include	<stdio.h>
#include	<errno.h>


#define	equal(s1, s2)	(strcmp(s1, s2) == 0)

int	interrupted;
int	rflag;

char	*getparent(),
	*getchild(),
	*concat(),
	*malloc(),
	*strcat(),
	*strcpy(),
	*strncpy();

/*
 * main
 * Interrupts are handled to prevent the formation of mangled directories.
 */
main(argc, argv)
register char	**argv;
{
	register int status = 0;

	catch(SIGINT);
	catch(SIGHUP);
	signal(SIGQUIT, SIG_IGN);

	if (argc > 1 && argv[1][0] == '-' &&
			(argv[1][1] == 'r' || argv[1][1] == 'p')) {
		++rflag;
		--argc;
		++argv;
	}
	if (*++argv == NULL) {
		fprintf(stderr, "Usage: mkdir [-rp] dir ...\n");
		exit(1);
	} else
		while (*argv) {
			if (mkdir(*argv++) < 0)
			 	status = 1;		/* error */
			if (interrupted)
				exit(1);
		}
	exit(status);
}

/*
 * Make a directory.
 * If the parent exists and is writeable, the directory and its "." and
 * ".." links are created.
 */
int
mkdir(dir)
register char	*dir;
{
	register char	*parent,
			*child;

	if ((child = getchild(dir)) == NULL) {
		error("cannot get child name %s", dir);
		return -1;
	} else if (equal(child, ".") || equal(child, "..")) {
		error("%s not allowed", dir);
		return -1;
	}
	if ((parent = getparent(dir)) == NULL)
		return -1;
	if (access(parent, 03)) {
		if (rflag && errno == ENOENT) {
			/* Make parent recursively. */
			if (mkdir(parent) != 0) {
				free(parent);
				return -1;
			}
		} else {
			switch (errno) {
			case ENOENT:
				error("parent directory %s does not exist", parent);
				break;
			case EACCES:
				error("no permission to mkdir in %s", parent);
				break;
			default:
				noway(dir);
				break;
			}
			free(parent);
			return -1;
		}
	}
	if (mknod(dir, IFDIR|0777, 0)) {
		switch (errno) {
		case EEXIST:
			error("%s already exists", dir);
			break;
		case EPERM:
			error("not the super-user");
			break;
		default:
			noway(dir);
			break;
		}
		free(parent);
		return -1;
	} else if (link(dir, concat(dir, "/."))) {
		linkerr(dir, ".");
		free(parent);
		return -1;
	} else if (link(parent, concat(dir, "/.."))) {
		linkerr(dir, "..");
		free(parent);
		return -1;
	}
	free(parent);
	return (chown(dir, getuid(), getgid()) < 0) ? -1 : 0;
}


/*
 * Return name of parent in an allocated buffer.
 */
char	*
getparent(dir)
char	*dir;
{
	register	i;
	register char	*p;
	char		*par;
	int 		tmp;

	i = strlen(dir);
	par = malloc(i+1);
	if (par == NULL) {
		nomemory();
		return NULL;
	}
	strcpy(par, dir);

	for (p=par+i; p>par; )
		if (*--p != '/')
			break;
	for (++p; *--p!='/'; )
		if (p == par) {
			*p = '.';
			break;
		}
	*++p = 0;
	tmp = strlen(par) - 1;
	if (tmp > 0 && par[tmp] == '/')
		par[tmp] = 0;			/* kill any ending slash */
	return par;
}

/*
 * Return rightmost component of pathname
 * in a statically allocated buffer.
 */
char	*
getchild(dir)
register char	*dir;
{
	register char	*p,
			*q;
	int		i;
	static char	ch[DIRSIZ+1];

	p = &dir[strlen(dir)];
	do {
		if (p == dir)
			fatal("illegal directory name");
	} while (*--p == '/');
	q = p;
	while (q > dir)
		if (*--q == '/') {
			++q;
			break;
		}
	i = p+1 - q;
	if (i > DIRSIZ)
		i = DIRSIZ;
	return strncpy(ch, q, i+1);
}


/*
 * Return concatenation of 's1' and 's2' in a malloc'ed buffer.
 * Free the previous buffer.
 */
char	*
concat(s1, s2)
char	*s1,
	*s2;
{
	static char	*str;

	if (str)
		free(str);
	str = malloc(strlen(s1)+strlen(s2)+1);
	if (str == NULL) {
		nomemory();
		return -1;
	}
	strcpy(str, s1);
	return strcat(str, s2);
}


/*
 * Recover from link failure.
 * In the event that "." or ".." cannot be created, remove all traces
 * of the directory.
 */
linkerr(dir, name)
char	*dir,
	*name;
{
	unlink(concat(dir, "/."));
	unlink(concat(dir, "/.."));
	unlink(dir);
	error("link to %s failed", name);
	return -1;
}


nomemory()
{
	error("out of memory");
	return -1;
}


noway(dir)
char	*dir;
{
	error("cannot make %s", dir);
	return -1;
}


onintr()
{
	signal(SIGINT, SIG_IGN);
	signal(SIGHUP, SIG_IGN);
	++interrupted;
}


catch(sig)
{
	if (signal(sig, SIG_IGN) == SIG_DFL)
		signal(sig, onintr);
}

error(arg1)
char	*arg1;
{
	fprintf(stderr, "mkdir: %r\n", &arg1);
}

fatal(arg1)
char 	*arg1;
{
	error(arg1);
	exit(1);
}

/* end of mkdir.c */

unix.superglobalmegacorp.com

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