File:  [Research Unix] / researchv10no / cmd / odist / ape / tryperm.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:21:35 2018 UTC (8 years, 1 month ago) by root
Branches: belllabs, MAIN
CVS tags: researchv10, HEAD
researchv10 Norman

#include <ctype.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "../pkg/ar.h"
#include "dist.h"

/* determine if we can create the given pathname.  not a generally useful
   function since it destroys the pathname in the process... */
static int
cancreate(char *path, int recurse)
{
	char *slash;

	for (;;) {
		slash = strrchr(path, '/');
		if (! slash)
			return 0;	/* supposed to be absolute */
		*slash = '\0';
		if (!*path)
			break;
		if (access(path, W_OK) == 0)
			return 1;
		if (!recurse)		/* for remove we check only one directory */
			return 0;
		if (access(path, F_OK) == 0)
			return 0;
	}
	return access("/", W_OK) == 0;
}
		
/*
 * try the instructions of the package on the given fd against the
 * permissions currently in the file system.  return 1 if we think we
 * ought to go ahead and try inspkg.
 */
int
tryperm(int fd)
{
	char armag[SARMAG];
	struct ar_hdr arhdr;
	long size;
	char temp[L_tmpnam];
	int tfd;
	FILE *tfp;
	int cmd, c, nf, retval;
	char *path;

	/* return 1 so inspkg will be called and barf for us */
	if (read(fd, armag, sizeof armag) != SARMAG || strncmp(armag, ARMAG, SARMAG))
		return 1;
	if (read(fd, (char *) &arhdr, sizeof arhdr) != sizeof arhdr)
		return 1;
	size = strtol(arhdr.ar_size, 0, 10);
	tmpnam(temp);
	close(creat(temp, 0600));	/* ape deficiency */
	tfd = open(temp, O_RDWR);
	if (tfd < 0) {
		eprintf("can't create temp file %s for tryperm", temp);
		remove(temp);		/* just in case something's *real* weird */
		exit(1);
	}
	if (fdcopy(tfd, fd, size, 0) != size) {
		close(tfd);
		remove(temp);
		eprintf("can't extract Instructions in tryperm");
		return 1;		/* inspkg will (presumably) barf for us */
	}
	lseek(tfd, 0L, 0);
	tfp = fdopen(tfd, "r");

	/* now that we have the instructions file, do the real meat.  */
	retval = 1;
	while ((cmd = getc(tfp)) != EOF) {
		switch (cmd) {
		case 'b':	/* b <mode> <dmaj> <dmin> <uid> <gid> <path> */
		case 'c':	/* c <mode> <dmaj> <dmin> <uid> <gid> <path> */
			nf = 6;
			break;
		case 'd':	/* d <mode> <uid> <gid> <path> */
		case 'f':	/* f <component> <uid> <gid> <path> */
			nf = 4;
			break;
		case 'l':	/* l <path1> <path2> */
		case 's':	/* s <path1> <path2> */
			nf = 2;
			break;
		case 'r':	/* r <path> */
		case 'x':	/* x <command> */
		case 'X':	/* X <path> */
			nf = 1;
			break;
		default:
			goto reterr;
		}

		/* get the last field of the line */
		while (nf--) {
			while ((c = getc(tfp)) != EOF)
				if (!isspace(c))
					break;
			if (c == EOF)
				goto reterr;
			ungetc(c, tfp);
			path = getpath(tfp);
		}

		/* eat the newline */
		if (getc(tfp) != '\n')
			goto reterr;

		switch (cmd) {
		case 'X':
		case 'x':
			break;

		case 'r':
			if (access(path, F_OK) != 0)
				break;
			if (cancreate(path, 0))
				break;
			retval = 0;
			goto out;

		default:
			if (cancreate(path, 1))
				break;
			retval = 0;
			goto out;
		}
	}

 out:
	fclose(tfp);
	remove(temp);
	return retval;

 reterr:
	/* there was some kind of bug in the format of the package.  return 1
	   and later on inspkg will generate an appropriate error message to
	   be returned to the remote system */
	fclose(tfp);	
	remove(temp);
	return 1;
}

unix.superglobalmegacorp.com

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