示例#1
0
/*
 * This is a special fast verify which basically checks the attributes
 * and then, if all is OK, checks the size and mod time using the same
 * stat and statvfs structures.
 */
int
fverify(int fix, char *ftype, char *path, struct ainfo *ainfo,
    struct cinfo *cinfo)
{
	int retval;

	/* return success if attribute checks are disabled */

	if (get_disable_attribute_check()) {
		return (0);
	}

	if ((retval = averify(fix, ftype, path, ainfo)) == 0) {
		if (*ftype == 'f' || *ftype == 'i') {
			if (cinfo->size != status.st_size) {
				reperr(pkg_gt(WRN_QV_SIZE), path);
				retval = VE_CONT;
			}
			/* pcfs doesn't support modification times */
			if (strcmp(vfsstatus.f_basetype, "pcfs") != 0) {
				if (cinfo->modtime != status.st_mtime) {
					reperr(pkg_gt(WRN_QV_MTIME), path);
					retval = VE_CONT;
				}
			}
		}
	}

	return (retval);
}
示例#2
0
/*
 * Remove the thing that's currently in place so we can put down the package
 * object. If we're replacing a directory with a directory, leave it alone.
 * Returns 1 if all OK and 0 if failed.
 */
static int
clear_target(char *path, char *ftype, int is_a_dir)
{
	int retcode = 1;

	if (is_a_dir) {	/* if there's a directory there already ... */
		/* ... and this isn't, ... */
		if ((*ftype != 'd') && (*ftype != 'x')) {
			if (rmdir(path)) {	/* try to remove it. */
				reperr(pkg_gt(ERR_RMDIR), path);
				retcode = 0;
			}
		}
	} else {
		if (remove(path)) {
			if (errno != ENOENT) {
				retcode = 0;	/* It didn't work. */
			}
		}
	}

	return (retcode);
}
示例#3
0
/*
 * Name:	averify
 * Description:	This function verifies and (if fix > 0) fixes the attributes
 *		of the file at the path provided.
 * Arguments:	fix - 0 - do not fix entries, 1 - fix entries
 *		ftype - single character "type" the entry is supposed to be
 *		path - path to file
 *		ainfo - attribute info structure representing the attributes
 *			the entry is supposed to be
 * NOTE:	attributes are links and permissions
 * Possible return values:
 * - 0 = successful
 * - VE_EXIST = path name does not exist
 * - VE_FTYPE = path file type is not recognized, is not supported,
 *		or is not what was expected
 * - VE_ATTR = path mode/group/user is not what was expected
 * - VE_CONT = mod time/link target/major/minor/size/file system type/current
 *		directory is not what was expected
 * - VE_FAIL = utime/target directory/link/stat/symlink/mknod/chmod/statvfs/
 *		chown failed
 */
int
averify(int fix, char *ftype, char *path, struct ainfo *ainfo)
{
	struct group	*grp; 	/* group entry buffer */
	struct passwd	*pwd;
	int		n;
	int		setval;
	int		uid, gid;
	int		dochown;
	int		retcode;
	int		statError = 0;
	int		targ_is_dir = 0;	/* replacing a directory */
	char		myftype;
	char		buf[PATH_MAX];
	ino_t		my_ino;
	dev_t		my_dev;
	char 		cwd[MAXPATHLEN];
	char 		*cd;
	char 		*c;

	setval = (*ftype == '?');
	retcode = 0;
	reperr(NULL);

	if (get_disable_attribute_check()) {
		return (0);
	}

	if (*ftype == 'l') {
		if (stat(path, &status) < 0) {
			retcode = VE_EXIST;
			reperr(pkg_gt(ERR_EXIST));
		}

		my_ino = status.st_ino;
		my_dev = status.st_dev;

		/* Get copy of the current working directory */
		if (getcwd(cwd, MAXPATHLEN) == NULL) {
			reperr(pkg_gt(ERR_GETWD));
			return (VE_FAIL);
		}

		/*
		 * Change to the directory in which the hard
		 * link is to be created.
		 */
		cd = strdup(path);
		c = strrchr(cd, '/');
		if (c) {
			/* bugid 4247895 */
			if (strcmp(cd, c) == 0)
				(void) strcpy(cd, "/");
			else
				*c = NULL;

			if (chdir(cd) != 0) {
				reperr(pkg_gt(ERR_CHDIR), cd);
				return (VE_FAIL);
			}
		}
		free(cd);

		if (retcode || (status.st_nlink < 2) ||
		    (stat(ainfo->local, &status) < 0) ||
		    (my_dev != status.st_dev) || (my_ino != status.st_ino)) {
			if (fix) {
				/*
				 * Don't want to do a hard link to a
				 * directory.
				 */
				if (!isdir(ainfo->local)) {
					(void) chdir(cwd);
					reperr(pkg_gt(ERR_LINKISDIR),
					    ainfo->local);
					return (VE_FAIL);
				}
				/* Now do the link. */
				if (!clear_target(path, ftype, targ_is_dir))
					return (VE_FAIL);

				if (link(ainfo->local, path)) {
					(void) chdir(cwd);
					reperr(pkg_gt(ERR_LINKFAIL),
					    ainfo->local);
					return (VE_FAIL);
				}
				retcode = 0;
			} else {
				/* Go back to previous working directory */
				if (chdir(cwd) != 0)
					reperr(pkg_gt(ERR_CHDIR), cwd);

				reperr(pkg_gt(ERR_LINK), ainfo->local);
				return (VE_CONT);
			}
		}

		/* Go back to previous working directory */
		if (chdir(cwd) != 0) {
			reperr(pkg_gt(ERR_CHDIR), cwd);
			return (VE_CONT);
		}

		return (retcode);
	}

	retcode = 0;

	/* If we are to process symlinks the old way then we follow the link */
	if (nonABI_symlinks()) {
		if ((*ftype == 's') ? lstat(path, &status) :
			stat(path, &status)) {
			reperr(pkg_gt(ERR_EXIST));
			retcode = VE_EXIST;
			myftype = '?';
			statError++;
		}
	/* If not then we inspect the target of the link */
	} else {
		if ((n = lstat(path, &status)) == -1) {
			reperr(pkg_gt(ERR_EXIST));
			retcode = VE_EXIST;
			myftype = '?';
			statError++;
		}
	}
	if (!statError) {
		/* determining actual type of existing object */
		switch (status.st_mode & S_IFMT) {
		    case S_IFLNK:
			myftype = 's';
			break;

		    case S_IFIFO:
			myftype = 'p';
			break;

		    case S_IFCHR:
			myftype = 'c';
			break;

		    case S_IFDIR:
			myftype = 'd';
			targ_is_dir = 1;
			break;

		    case S_IFBLK:
			myftype = 'b';
			break;

		    case S_IFREG:
		    case 0:
			myftype = 'f';
			break;

		    case S_IFDOOR:
			myftype = 'D';
			break;

		    default:
			reperr(pkg_gt(ERR_UNKNOWN));
			return (VE_FTYPE);
		}
	}

	if (setval) {
		/*
		 * Check to make sure that a package or an installf that uses
		 * wild cards '?' to assume the ftype of an object on the
		 * system is not assuming a door ftype. Doors are not supported
		 * but should be ignored.
		 */
		if (myftype == 'D') {
			reperr(pkg_gt(ERR_FTYPED), path);
			retcode = VE_FTYPE;
			return (VE_FTYPE);
		} else {
			*ftype = myftype;
		}
	} else if (!retcode && (*ftype != myftype) &&
	    ((myftype != 'f') || !strchr("ilev", *ftype)) &&
	    ((myftype != 'd') || (*ftype != 'x'))) {
		reperr(pkg_gt(ERR_FTYPE), *ftype, myftype);
		retcode = VE_FTYPE;
	}

	if (!retcode && (*ftype == 's')) {
		/* make sure that symbolic link is correct */
		n = readlink(path, buf, PATH_MAX);
		if (n < 0) {
			reperr(pkg_gt(ERR_SLINK), ainfo->local);
			retcode = VE_CONT;
		} else if (ainfo->local != NULL) {
			buf[n] = '\0';
			if (strcmp(buf, ainfo->local)) {
				reperr(pkg_gt(ERR_SLINK), ainfo->local);
				retcode = VE_CONT;
			}
		} else if (ainfo->local == NULL) {
			/*
			 * Since a sym link target exists, insert it
			 * into the ainfo structure
			 */
			buf[n] = '\0';
			ainfo->local = strdup(buf);
		}
	}

	if (retcode) {
		/* The path doesn't exist or is different than it should be. */
		if (fix) {
			/*
			 * Clear the way for the write. If it won't clear,
			 * there's nothing we can do.
			 */
			if (!clear_target(path, ftype, targ_is_dir))
				return (VE_FAIL);

			if ((*ftype == 'd') || (*ftype == 'x')) {
				char	*pt, *p;

				/* Try to make it the easy way */
				if (mkdir(path, ainfo->mode)) {
					/*
					 * Failing that, walk through the
					 * parent directories creating
					 * whatever is needed.
					 */
					p = strdup(path);
					pt = (*p == '/') ? p+1 : p;
					do {
						if (pt = strchr(pt, '/'))
							*pt = '\0';
						if (access(p, 0) &&
						    mkdir(p, ainfo->mode))
							break;
						if (pt)
							*pt++ = '/';
					} while (pt);
					free(p);
				}
				if (stat(path, &status) < 0) {
					reperr(pkg_gt(ERR_DIRFAIL));
					return (VE_FAIL);
				}
			} else if (*ftype == 's') {
				if (symlink(ainfo->local, path)) {
					reperr(pkg_gt(ERR_SLINKFAIL),
					    ainfo->local);
					return (VE_FAIL);
				}

			} else if (*ftype == 'c') {
				int wilddevno = 0;
				/*
				 * The next three if's support 2.4 and older
				 * packages that use "?" as device numbers.
				 * This should be considered for removal by
				 * release 2.7 or so.
				 */
				if (ainfo->major == BADMAJOR) {
					ainfo->major = 0;
					wilddevno = 1;
				}

				if (ainfo->minor == BADMINOR) {
					ainfo->minor = 0;
					wilddevno = 1;
				}

				if (wilddevno) {
					wilddevno = 0;
					logerr(MSG_WLDDEVNO, path,
					    ainfo->major, ainfo->minor);
				}

				if (mknod(path, ainfo->mode | S_IFCHR,
				    makedev(ainfo->major, ainfo->minor)) ||
				    (stat(path, &status) < 0)) {
					reperr(pkg_gt(ERR_CDEVFAIL));
					return (VE_FAIL);
				}
			} else if (*ftype == 'b') {
				int wilddevno = 0;
				/*
				 * The next three if's support 2.4 and older
				 * packages that use "?" as device numbers.
				 * This should be considered for removal by
				 * release 2.7 or so.
				 */
				if (ainfo->major == BADMAJOR) {
					ainfo->major = 0;
					wilddevno = 1;
				}

				if (ainfo->minor == BADMINOR) {
					ainfo->minor = 0;
					wilddevno = 1;
				}

				if (wilddevno) {
					wilddevno = 0;
					logerr(MSG_WLDDEVNO, path,
					    ainfo->major, ainfo->minor);
				}

				if (mknod(path, ainfo->mode | S_IFBLK,
				    makedev(ainfo->major, ainfo->minor)) ||
				    (stat(path, &status) < 0)) {
					reperr(pkg_gt(ERR_BDEVFAIL));
					return (VE_FAIL);
				}
			} else if (*ftype == 'p') {
				if (mknod(path, ainfo->mode | S_IFIFO, NULL) ||
				    (stat(path, &status) < 0)) {
					reperr(pkg_gt(ERR_PIPEFAIL));
					return (VE_FAIL);
				}
			} else
				return (retcode);

		} else
			return (retcode);
	}

	if (*ftype == 's')
		return (0); /* don't check anything else */
	if (*ftype == 'i')
		return (0); /* don't check anything else */

	retcode = 0;
	if ((myftype == 'c') || (myftype == 'b')) {
		if (setval || (ainfo->major == BADMAJOR))
			ainfo->major = major(status.st_rdev);
		if (setval || (ainfo->minor == BADMINOR))
			ainfo->minor = minor(status.st_rdev);
		/* check major & minor */
		if (status.st_rdev != makedev(ainfo->major, ainfo->minor)) {
			reperr(pkg_gt(ERR_MAJMIN), ainfo->major, ainfo->minor,
			    major(status.st_rdev), minor(status.st_rdev));
			retcode = VE_CONT;
		}
	}

	/* compare specified mode w/ actual mode excluding sticky bit */
	if (setval || (ainfo->mode == BADMODE) || (ainfo->mode == WILDCARD))
		ainfo->mode = status.st_mode & 07777;
	else if ((ainfo->mode & 06777) != (status.st_mode & 06777)) {
		if (fix) {
			if ((ainfo->mode == BADMODE) ||
			    (chmod(path, ainfo->mode) < 0))
				retcode = VE_FAIL;
		} else {
			reperr(pkg_gt(ERR_PERM), ainfo->mode,
				status.st_mode & 07777);
			if (!retcode)
				retcode = VE_ATTR;
		}
	}

	dochown = 0;

	/* get group entry for specified group */
	if (setval || strcmp(ainfo->group, BADGROUP) == 0) {
		grp = cgrgid(status.st_gid);
		if (grp)
			(void) strcpy(ainfo->group, grp->gr_name);
		else {
			if (!retcode)
				retcode = VE_ATTR;
			reperr(pkg_gt(ERR_BADGRPID), status.st_gid);
		}
		gid = status.st_gid;
	} else if ((grp = cgrnam(ainfo->group)) == NULL) {
		reperr(pkg_gt(ERR_BADGRPNM), ainfo->group);
		if (!retcode)
			retcode = VE_ATTR;
	} else if ((gid = grp->gr_gid) != status.st_gid) {
		if (fix) {
			/* save specified GID */
			gid = grp->gr_gid;
			dochown++;
		} else {
			if ((grp = cgrgid((int)status.st_gid)) ==
			    (struct group *)NULL) {
				reperr(pkg_gt(ERR_GROUP), ainfo->group,
				    "(null)");
			} else {
				reperr(pkg_gt(ERR_GROUP), ainfo->group,
				    grp->gr_name);
			}
			if (!retcode)
				retcode = VE_ATTR;
		}
	}

	/* get password entry for specified owner */
	if (setval || strcmp(ainfo->owner, BADOWNER) == 0) {
		pwd = cpwuid((int)status.st_uid);
		if (pwd)
			(void) strcpy(ainfo->owner, pwd->pw_name);
		else {
			if (!retcode)
				retcode = VE_ATTR;
			reperr(pkg_gt(ERR_BADUSRID), status.st_uid);
		}
		uid = status.st_uid;
	} else if ((pwd = cpwnam(ainfo->owner)) == NULL) {
		/* UID does not exist in password file */
		reperr(pkg_gt(ERR_BADUSRNM), ainfo->owner);
		if (!retcode)
			retcode = VE_ATTR;
	} else if ((uid = pwd->pw_uid) != status.st_uid) {
		/* get owner name for actual UID */
		if (fix) {
			uid = pwd->pw_uid;
			dochown++;
		} else {
			pwd = cpwuid((int)status.st_uid);
			if (pwd == NULL)
				reperr(pkg_gt(ERR_BADUSRID),
				    (int)status.st_uid);
			else
				reperr(pkg_gt(ERR_OWNER), ainfo->owner,
				    pwd->pw_name);

			if (!retcode)
				retcode = VE_ATTR;
		}
	}

	if (statvfs(path, &vfsstatus) < 0) {
		reperr(pkg_gt(ERR_EXIST));
		retcode = VE_FAIL;
	} else {
		if (dochown) {
			/* pcfs doesn't support file ownership */
			if (strcmp(vfsstatus.f_basetype, "pcfs") != 0 &&
			    chown(path, uid, gid) < 0) {
				retcode = VE_FAIL; /* chown failed */
			}
		}
	}

	if (retcode == VE_FAIL)
		reperr(pkg_gt(ERR_ATTRFAIL));
	return (retcode);
}
示例#4
0
/*
 * Name:	compute_checksum
 * Description:	generate checksum for specified file
 * Arguments:	r_cksumerr (int *) [RO, *RW]
 *			- pointer to integer that is set on return to:
 *				== 0 - no error occurred
 *				!= 0 - error occurred
 *		a_path (char *) [RO, *RO]
 *			- pointer to string representing path to file to
 *			  generate checksum of
 * Returns:	unsigned long - results:
 *			- If *r_cksumerr == 0, checksum of specified file
 *			- If *r_cksumerr != 0, undefined
 */
unsigned long
compute_checksum(int *r_cksumerr, char *a_path)
{
	CHECKSUM_T	suma;	/* to split four-bytes into 2 two-byte values */
	CHECKSUM_T	tempa;
	int		fd;
	uint32_t	lg;	/* running checksum value */
	uint32_t	buf[CHUNK/4]; /* to read CHUNK bytes */
	uint32_t	lsavhi;	/* high order two-bytes of four-byte checksum */
	uint32_t	lsavlo;	/* low order two-bytes of four-byte checksum */
	int		leap = sizeof (uint32_t);
	int		notyet = 0;
	int		nread;
	struct stat64	sbuf;

	/* reset error flag */
	*r_cksumerr = 0;

	/* open file and obtain -> where file is mapped/read */
	if ((fd = open(a_path, O_RDONLY)) < 0) {
		*r_cksumerr = 1;
		reperr(pkg_gt(ERR_NO_CKSUM));
		perror(ERR_NO_CKSUM);
		return (0);
	}

	if (fstat64(fd, &sbuf) != 0) {
		*r_cksumerr = 1;
		reperr(pkg_gt(ERR_NO_CKSUM));
		perror(ERR_NO_CKSUM);
		return (0);
	}

	/* initialize checksum value */
	lg = 0;

	/*
	 * Read CHUNK bytes off the file at a time; Read size of long bytes
	 * from memory at a time and process them.
	 * If last read, then read remnant bytes and process individually.
	 */
	errno = 0;
	while ((nread = read(fd, (void*)buf,
		    (sbuf.st_size < CHUNK) ? sbuf.st_size : CHUNK)) > 0) {
		uchar_t *s;
		uint32_t *p = buf;

		notyet = nread % leap;
		nread -= notyet;

		for (; nread > 0; nread -= leap) {
			lg += ((((*p)>>24)&0xFF) & WDMSK);
			lg += ((((*p)>>16)&0xFF) & WDMSK);
			lg += ((((*p)>>8)&0xFF) & WDMSK);
			lg += (((*p)&0xFF) & WDMSK);
			p++;
		}
		s = (uchar_t *)p;
		/* leftover bytes less than four in number */
		while (notyet--)
			lg += (((uint32_t)(*s++)) & WDMSK);
	}

	/* wind up */
	(void) close(fd);

	/* compute checksum components */
	suma.lg = lg;
	tempa.lg = (suma.hl.lo & WDMSK) + (suma.hl.hi & WDMSK);
	lsavhi = (uint32_t)tempa.hl.hi;
	lsavlo = (uint32_t)tempa.hl.lo;

	/* return final checksum value */
	return (lsavhi+lsavlo);
}
示例#5
0
int
cverify(int fix, char *ftype, char *path, struct cinfo *cinfo,
	int allow_checksum)
{
	struct stat	status; 	/* file status buffer */
	struct utimbuf	times;
	unsigned long	mycksum;
	int		setval, retcode;
	char		tbuf1[512];
	char		tbuf2[512];
	int		cksumerr;

	setval = (*ftype == '?');
	retcode = 0;
	reperr(NULL);

	if (stat(path, &status) < 0) {
		reperr(pkg_gt(ERR_EXIST));
		return (VE_EXIST);
	}

	/* -1	requires modtimes to be the same */
	/*  0   reports modtime failure */
	/*  1   fixes modtimes */

	if (setval || (cinfo->modtime == BADCONT)) {
		cinfo->modtime = status.st_mtime;
	} else if (status.st_mtime != cinfo->modtime) {
		if (fix > 0) {
			/* reset times on the file */
			times.actime = cinfo->modtime;
			times.modtime = cinfo->modtime;
			if (utime(path, &times)) {
				reperr(pkg_gt(ERR_MODFAIL));
				retcode = VE_FAIL;
			}
		} else if (fix < 0) {
			/* modtimes must be the same */
			if (strftime(tbuf1, sizeof (tbuf1), DATEFMT,
				localtime(&cinfo->modtime)) == 0) {
				reperr(pkg_gt(ERR_MEM));
			}
			if (strftime(tbuf2, sizeof (tbuf2), DATEFMT,
				localtime(&status.st_mtime)) == 0) {
				reperr(pkg_gt(ERR_MEM));
			}
			reperr(pkg_gt(ERR_MTIME), tbuf1, tbuf2);
			retcode = VE_CONT;
		}
	}

	if (setval || (cinfo->size == (fsblkcnt_t)BADCONT)) {
		cinfo->size = status.st_size;
	} else if (status.st_size != cinfo->size) {
		if (!retcode) {
			retcode = VE_CONT;
		}
		reperr(pkg_gt(ERR_SIZE), cinfo->size, status.st_size);
	}

	cksumerr = 0;

	/*
	 * see if checksumming should be done: if checksumming is allowed,
	 * and checksumming is enabled, then checksum the file.
	 */

	/* return if no need to compute checksum */

	if ((allow_checksum == 0) || (enable_checksum == 0)) {
		return (retcode);
	}

	/* compute checksum */

	mycksum = compute_checksum(&cksumerr, path);

	/* set value if not set or if checksum cannot be computed */

	if (setval || (cinfo->cksum == BADCONT)) {
		cinfo->cksum = mycksum;
		return (retcode);
	}

	/* report / return error if checksums mismatch or there is an error */

	if ((mycksum != cinfo->cksum) || cksumerr) {
		if (!retcode) {
			retcode = VE_CONT;
		}
		if (!cksumerr) {
			reperr(pkg_gt(ERR_CKSUM), cinfo->cksum, mycksum);
		}
	}

	return (retcode);
}
示例#6
0
void /*FUNCTION*/ initcommon()
{
	int nerr;

	/*=====================================================================
	 * PURPOSE: Variable initialization of ALL common blocks.
	 *=====================================================================
	 * MODULE/LEVEL:  EXM/4
	 *=====================================================================
	 * GLOBAL INPUT:
	 *    MACH:    KWSNGL, KWMULT, KWCONC
	 *    MEM:     MMEM, MEPSL
	 *    CSF:     KTOKDL, NTOKDL, KMSGDL, NMSGDL
	 *=====================================================================
	 * GLOBAL OUTPUT:
	 *    MEM:     SACMEM
	 *=====================================================================
	 * MODIFICATION HISTORY:
	 *    920414:  Moved block data initialization to initsac as a new
	 *             procedure, initblkdata, while portint to IBM RISC 6000.
	 *    920410:  Added nlevelsgt data initialization after taking it out
	 *             of getvlist and getvlist2, moving common to inc/vars.
	 *
	 *    920309:  Added include dload and initialization of global nfiles.
	 *    920330:  Added block data initialization of common variables.
	 *             Added include gem, dfm, cnv, vars. Added initialization 
	 *             of ndsflcnt - files in data-set storage.
	 *    911107:  Added nerr check and exti on initcomlists.
	 *    900405:  Added call to INITCONTATTR.
	 *    900305:  Added call to INIXYZ.
	 *    880520:  Fixed bug in call to endgraphics.
	 *    870527:  Deleted call to INIWVT.
	 *    870513:  Deleted call to INIOFM.
	 *    870317:  Added call to INIICM.
	 *    870301:  Added call to create global variable store.
	 *    860407:  Added call to INIAM.
	 *    860327:  Added call to INIWVT.
	 *             Moved call to DELIMS from INISAC to here.
	 *    860218:  Added call to WILDCH.
	 *    830309:  Added call to end graphics library.
	 *    810514:  Added call to INISNF
	 *    810414:  Original version.
	 *=====================================================================
	 * DOCUMENTED/REVIEWED:  900305
	 *===================================================================== */
	/* PROCEDURE: */
	/* - Terminate graphics library. */
	endgraphics( &nerr );

	/* - SAC's common blocks. */

	inibom();
	inicom();
	inicpf();
	inidfm();
	inieam();
	iniexm();
	inifks();
	inigem();
	inigam();
	inihdr();
	inilhf();
	inisam();
	iniscm();
	inispe();
	initok();
	inisss();
	iniuom();
	initcomlists( &nerr );
	if( nerr == 901 )
		exit(1);
	initsite();
	inismm();
	inibbs();
	iniicm();
	inivars();
	inixyz();
	initcontattr();

	/* - SACMEM array manager. */

	iniam( &cmmem );

	/* - Blackboard store. */

	createbbs( &nerr );
	reperr(nerr);
	sac_report_files_in_memory(&nerr);

	/* - Initialize wildcard patterns with system values. */

	wildch( KWSNGL, KWMULT, KWCONC );

       
	return;

} /* end of function */