xref: /illumos-gate/usr/src/lib/libpkg/common/verify.c (revision 3970c098)
15c51f124SMoriah Waterland /*
25c51f124SMoriah Waterland  * CDDL HEADER START
35c51f124SMoriah Waterland  *
45c51f124SMoriah Waterland  * The contents of this file are subject to the terms of the
55c51f124SMoriah Waterland  * Common Development and Distribution License (the "License").
65c51f124SMoriah Waterland  * You may not use this file except in compliance with the License.
75c51f124SMoriah Waterland  *
85c51f124SMoriah Waterland  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95c51f124SMoriah Waterland  * or http://www.opensolaris.org/os/licensing.
105c51f124SMoriah Waterland  * See the License for the specific language governing permissions
115c51f124SMoriah Waterland  * and limitations under the License.
125c51f124SMoriah Waterland  *
135c51f124SMoriah Waterland  * When distributing Covered Code, include this CDDL HEADER in each
145c51f124SMoriah Waterland  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155c51f124SMoriah Waterland  * If applicable, add the following below this CDDL HEADER, with the
165c51f124SMoriah Waterland  * fields enclosed by brackets "[]" replaced with your own identifying
175c51f124SMoriah Waterland  * information: Portions Copyright [yyyy] [name of copyright owner]
185c51f124SMoriah Waterland  *
195c51f124SMoriah Waterland  * CDDL HEADER END
205c51f124SMoriah Waterland  */
215c51f124SMoriah Waterland 
225c51f124SMoriah Waterland /*
235c51f124SMoriah Waterland  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
245c51f124SMoriah Waterland  * Use is subject to license terms.
255c51f124SMoriah Waterland  */
265c51f124SMoriah Waterland 
275c51f124SMoriah Waterland /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
285c51f124SMoriah Waterland /* All Rights Reserved */
295c51f124SMoriah Waterland 
305c51f124SMoriah Waterland 
315c51f124SMoriah Waterland 
325c51f124SMoriah Waterland #include <stdio.h>
335c51f124SMoriah Waterland #include <limits.h>
345c51f124SMoriah Waterland #include <stdlib.h>
355c51f124SMoriah Waterland #include <unistd.h>
365c51f124SMoriah Waterland #include <utime.h>
375c51f124SMoriah Waterland #include <sys/types.h>
385c51f124SMoriah Waterland #include <sys/param.h>
395c51f124SMoriah Waterland #include <sys/stat.h>
405c51f124SMoriah Waterland #include <sys/statvfs.h>
415c51f124SMoriah Waterland #include <grp.h>
425c51f124SMoriah Waterland #include <pwd.h>
435c51f124SMoriah Waterland #include <errno.h>
445c51f124SMoriah Waterland #include <string.h>
455c51f124SMoriah Waterland #include <stdarg.h>
465c51f124SMoriah Waterland #include <fcntl.h>
475c51f124SMoriah Waterland #include <sys/mkdev.h>
485c51f124SMoriah Waterland #include "pkgstrct.h"
495c51f124SMoriah Waterland #include "pkglib.h"
505c51f124SMoriah Waterland #include "pkglibmsgs.h"
515c51f124SMoriah Waterland #include "pkglocale.h"
525c51f124SMoriah Waterland 
535c51f124SMoriah Waterland #define	WDMSK	0xFFFF
545c51f124SMoriah Waterland #define	DATEFMT	"%D %r"
555c51f124SMoriah Waterland #define	LONG_BOUNDARY	((sizeof (unsigned long))-1)
565c51f124SMoriah Waterland #define	CHUNK	1024*1024
575c51f124SMoriah Waterland 
585c51f124SMoriah Waterland static char	theErrBuf[PATH_MAX+512] = {'\0'};
595c51f124SMoriah Waterland static char	*theErrStr = NULL;
605c51f124SMoriah Waterland 
615c51f124SMoriah Waterland /* checksum disable switch */
625c51f124SMoriah Waterland static int	enable_checksum = 1;
635c51f124SMoriah Waterland 
645c51f124SMoriah Waterland /* attribute disable flag */
655c51f124SMoriah Waterland static int	disable_attributes = 0;
665c51f124SMoriah Waterland 
675c51f124SMoriah Waterland /* non-ABI symlinks supported */
685c51f124SMoriah Waterland static int	nonabi_symlinks;
695c51f124SMoriah Waterland 
705c51f124SMoriah Waterland /*
715c51f124SMoriah Waterland  * forward declarations
725c51f124SMoriah Waterland  */
735c51f124SMoriah Waterland 
745c51f124SMoriah Waterland static int	clear_target(char *path, char *ftype, int is_a_dir);
755c51f124SMoriah Waterland 
765c51f124SMoriah Waterland unsigned	long compute_checksum(int *r_err, char *path);
775c51f124SMoriah Waterland 
785c51f124SMoriah Waterland /* union used to generate checksum */
795c51f124SMoriah Waterland typedef union hilo {
805c51f124SMoriah Waterland 	struct part {
815c51f124SMoriah Waterland 		uint16_t hi;
825c51f124SMoriah Waterland 		uint16_t lo;
835c51f124SMoriah Waterland 	} hl;
845c51f124SMoriah Waterland 	uint32_t	lg;
855c51f124SMoriah Waterland } CHECKSUM_T;
865c51f124SMoriah Waterland 
875c51f124SMoriah Waterland /*PRINTFLIKE1*/
88b46ec01aSok static void
reperr(char * fmt,...)895c51f124SMoriah Waterland reperr(char *fmt, ...)
905c51f124SMoriah Waterland {
915c51f124SMoriah Waterland 	char	*pt;
925c51f124SMoriah Waterland 	ssize_t	ptln;
935c51f124SMoriah Waterland 	va_list	ap;
945c51f124SMoriah Waterland 	int	n;
955c51f124SMoriah Waterland 
965c51f124SMoriah Waterland 	if (fmt == (char *)NULL) {
975c51f124SMoriah Waterland 		theErrBuf[0] = '\0';
985c51f124SMoriah Waterland 	} else {
995c51f124SMoriah Waterland 		if (n = strlen(theErrBuf)) {
1005c51f124SMoriah Waterland 			pt = theErrBuf + n;
1015c51f124SMoriah Waterland 			*pt++ = '\n';
1025c51f124SMoriah Waterland 			*pt = '\0';
1035c51f124SMoriah Waterland 			ptln = sizeof (theErrBuf)-n;
1045c51f124SMoriah Waterland 		} else {
1055c51f124SMoriah Waterland 			pt = theErrBuf;
1065c51f124SMoriah Waterland 			ptln = sizeof (theErrBuf);
1075c51f124SMoriah Waterland 		}
1085c51f124SMoriah Waterland 		va_start(ap, fmt);
1095c51f124SMoriah Waterland 		(void) vsnprintf(pt, ptln, fmt, ap);
1105c51f124SMoriah Waterland 		va_end(ap);
1115c51f124SMoriah Waterland 	}
1125c51f124SMoriah Waterland }
1135c51f124SMoriah Waterland 
1145c51f124SMoriah Waterland /*
1155c51f124SMoriah Waterland  * Name:	cverify
1165c51f124SMoriah Waterland  * Description:	This function verifies and (if fix > 0) fixes the contents
1175c51f124SMoriah Waterland  *		of the file at the path provided
1185c51f124SMoriah Waterland  * Arguments:	fix - 0 - do not fix entries, 1 - fix entries
1195c51f124SMoriah Waterland  *		ftype - single character "type" the entry is supposed to be
1205c51f124SMoriah Waterland  *		path - path to file
1215c51f124SMoriah Waterland  *		cinfo - content info structure representing the contents
1225c51f124SMoriah Waterland  *			the entry is supposed to contain
1235c51f124SMoriah Waterland  *		allow_checksum - determine if checksumming should be disabled:
1245c51f124SMoriah Waterland  *		 == 0 - do not perform checksum ever - override enable_checksum.
1255c51f124SMoriah Waterland  *		 != 0 - use the default checksum flag "enable_checksum" to
1265c51f124SMoriah Waterland  *			determine if checksumming should be done.
1275c51f124SMoriah Waterland  * NOTE:	modification and creation times can be repaired; the contents
1285c51f124SMoriah Waterland  *		of the file cannot be corrected if the checksum indicates that
1295c51f124SMoriah Waterland  *		the contents are not correct - VE_CONT will be returned in this
1305c51f124SMoriah Waterland  *		case.
1315c51f124SMoriah Waterland  * Possible return values:
1325c51f124SMoriah Waterland  * - 0 = successful
1335c51f124SMoriah Waterland  * - VE_EXIST = path name does not exist
1345c51f124SMoriah Waterland  * - VE_FTYPE = path file type is not recognized, is not supported,
1355c51f124SMoriah Waterland  *		or is not what was expected
1365c51f124SMoriah Waterland  * - VE_ATTR = path mode/group/user is not what was expected
1375c51f124SMoriah Waterland  * - VE_CONT = mod time/link target/major/minor/size/file system type/current
1385c51f124SMoriah Waterland  *		directory is not what was expected
1395c51f124SMoriah Waterland  * - VE_FAIL = utime/target directory/link/stat/symlink/mknod/chmod/statvfs/
1405c51f124SMoriah Waterland  *		chown failed
1415c51f124SMoriah Waterland  */
1425c51f124SMoriah Waterland 
1435c51f124SMoriah Waterland int
cverify(int fix,char * ftype,char * path,struct cinfo * cinfo,int allow_checksum)1445c51f124SMoriah Waterland cverify(int fix, char *ftype, char *path, struct cinfo *cinfo,
145*3970c098SToomas Soome     int allow_checksum)
1465c51f124SMoriah Waterland {
147*3970c098SToomas Soome 	struct stat	status;		/* file status buffer */
1485c51f124SMoriah Waterland 	struct utimbuf	times;
1495c51f124SMoriah Waterland 	unsigned long	mycksum;
1505c51f124SMoriah Waterland 	int		setval, retcode;
1515c51f124SMoriah Waterland 	char		tbuf1[512];
1525c51f124SMoriah Waterland 	char		tbuf2[512];
1535c51f124SMoriah Waterland 	int		cksumerr;
1545c51f124SMoriah Waterland 
1555c51f124SMoriah Waterland 	setval = (*ftype == '?');
1565c51f124SMoriah Waterland 	retcode = 0;
1575c51f124SMoriah Waterland 	reperr(NULL);
1585c51f124SMoriah Waterland 
1595c51f124SMoriah Waterland 	if (stat(path, &status) < 0) {
1605c51f124SMoriah Waterland 		reperr(pkg_gt(ERR_EXIST));
1615c51f124SMoriah Waterland 		return (VE_EXIST);
1625c51f124SMoriah Waterland 	}
1635c51f124SMoriah Waterland 
1645c51f124SMoriah Waterland 	/* -1	requires modtimes to be the same */
1655c51f124SMoriah Waterland 	/*  0   reports modtime failure */
1665c51f124SMoriah Waterland 	/*  1   fixes modtimes */
1675c51f124SMoriah Waterland 
1685c51f124SMoriah Waterland 	if (setval || (cinfo->modtime == BADCONT)) {
1695c51f124SMoriah Waterland 		cinfo->modtime = status.st_mtime;
1705c51f124SMoriah Waterland 	} else if (status.st_mtime != cinfo->modtime) {
1715c51f124SMoriah Waterland 		if (fix > 0) {
1725c51f124SMoriah Waterland 			/* reset times on the file */
1735c51f124SMoriah Waterland 			times.actime = cinfo->modtime;
1745c51f124SMoriah Waterland 			times.modtime = cinfo->modtime;
1755c51f124SMoriah Waterland 			if (utime(path, &times)) {
1765c51f124SMoriah Waterland 				reperr(pkg_gt(ERR_MODFAIL));
1775c51f124SMoriah Waterland 				retcode = VE_FAIL;
1785c51f124SMoriah Waterland 			}
1795c51f124SMoriah Waterland 		} else if (fix < 0) {
1805c51f124SMoriah Waterland 			/* modtimes must be the same */
1815c51f124SMoriah Waterland 			if (strftime(tbuf1, sizeof (tbuf1), DATEFMT,
182*3970c098SToomas Soome 			    localtime(&cinfo->modtime)) == 0) {
1835c51f124SMoriah Waterland 				reperr(pkg_gt(ERR_MEM));
1845c51f124SMoriah Waterland 			}
1855c51f124SMoriah Waterland 			if (strftime(tbuf2, sizeof (tbuf2), DATEFMT,
186*3970c098SToomas Soome 			    localtime(&status.st_mtime)) == 0) {
1875c51f124SMoriah Waterland 				reperr(pkg_gt(ERR_MEM));
1885c51f124SMoriah Waterland 			}
1895c51f124SMoriah Waterland 			reperr(pkg_gt(ERR_MTIME), tbuf1, tbuf2);
1905c51f124SMoriah Waterland 			retcode = VE_CONT;
1915c51f124SMoriah Waterland 		}
1925c51f124SMoriah Waterland 	}
1935c51f124SMoriah Waterland 
1945c51f124SMoriah Waterland 	if (setval || (cinfo->size == (fsblkcnt_t)BADCONT)) {
1955c51f124SMoriah Waterland 		cinfo->size = status.st_size;
1965c51f124SMoriah Waterland 	} else if (status.st_size != cinfo->size) {
1975c51f124SMoriah Waterland 		if (!retcode) {
1985c51f124SMoriah Waterland 			retcode = VE_CONT;
1995c51f124SMoriah Waterland 		}
2005c51f124SMoriah Waterland 		reperr(pkg_gt(ERR_SIZE), cinfo->size, status.st_size);
2015c51f124SMoriah Waterland 	}
2025c51f124SMoriah Waterland 
2035c51f124SMoriah Waterland 	cksumerr = 0;
2045c51f124SMoriah Waterland 
2055c51f124SMoriah Waterland 	/*
2065c51f124SMoriah Waterland 	 * see if checksumming should be done: if checksumming is allowed,
2075c51f124SMoriah Waterland 	 * and checksumming is enabled, then checksum the file.
2085c51f124SMoriah Waterland 	 */
2095c51f124SMoriah Waterland 
2105c51f124SMoriah Waterland 	/* return if no need to compute checksum */
2115c51f124SMoriah Waterland 
2125c51f124SMoriah Waterland 	if ((allow_checksum == 0) || (enable_checksum == 0)) {
2135c51f124SMoriah Waterland 		return (retcode);
2145c51f124SMoriah Waterland 	}
2155c51f124SMoriah Waterland 
2165c51f124SMoriah Waterland 	/* compute checksum */
2175c51f124SMoriah Waterland 
2185c51f124SMoriah Waterland 	mycksum = compute_checksum(&cksumerr, path);
2195c51f124SMoriah Waterland 
2205c51f124SMoriah Waterland 	/* set value if not set or if checksum cannot be computed */
2215c51f124SMoriah Waterland 
2225c51f124SMoriah Waterland 	if (setval || (cinfo->cksum == BADCONT)) {
2235c51f124SMoriah Waterland 		cinfo->cksum = mycksum;
2245c51f124SMoriah Waterland 		return (retcode);
2255c51f124SMoriah Waterland 	}
2265c51f124SMoriah Waterland 
2275c51f124SMoriah Waterland 	/* report / return error if checksums mismatch or there is an error */
2285c51f124SMoriah Waterland 
2295c51f124SMoriah Waterland 	if ((mycksum != cinfo->cksum) || cksumerr) {
2305c51f124SMoriah Waterland 		if (!retcode) {
2315c51f124SMoriah Waterland 			retcode = VE_CONT;
2325c51f124SMoriah Waterland 		}
2335c51f124SMoriah Waterland 		if (!cksumerr) {
2345c51f124SMoriah Waterland 			reperr(pkg_gt(ERR_CKSUM), cinfo->cksum, mycksum);
2355c51f124SMoriah Waterland 		}
2365c51f124SMoriah Waterland 	}
2375c51f124SMoriah Waterland 
2385c51f124SMoriah Waterland 	return (retcode);
2395c51f124SMoriah Waterland }
2405c51f124SMoriah Waterland 
2415c51f124SMoriah Waterland /*
2425c51f124SMoriah Waterland  * Name:	compute_checksum
2435c51f124SMoriah Waterland  * Description:	generate checksum for specified file
2445c51f124SMoriah Waterland  * Arguments:	r_cksumerr (int *) [RO, *RW]
2455c51f124SMoriah Waterland  *			- pointer to integer that is set on return to:
2465c51f124SMoriah Waterland  *				== 0 - no error occurred
2475c51f124SMoriah Waterland  *				!= 0 - error occurred
2485c51f124SMoriah Waterland  *		a_path (char *) [RO, *RO]
2495c51f124SMoriah Waterland  *			- pointer to string representing path to file to
2505c51f124SMoriah Waterland  *			  generate checksum of
2515c51f124SMoriah Waterland  * Returns:	unsigned long - results:
2525c51f124SMoriah Waterland  *			- If *r_cksumerr == 0, checksum of specified file
2535c51f124SMoriah Waterland  *			- If *r_cksumerr != 0, undefined
2545c51f124SMoriah Waterland  */
2555c51f124SMoriah Waterland unsigned long
compute_checksum(int * r_cksumerr,char * a_path)2565c51f124SMoriah Waterland compute_checksum(int *r_cksumerr, char *a_path)
2575c51f124SMoriah Waterland {
2585c51f124SMoriah Waterland 	CHECKSUM_T	suma;	/* to split four-bytes into 2 two-byte values */
2595c51f124SMoriah Waterland 	CHECKSUM_T	tempa;
2605c51f124SMoriah Waterland 	int		fd;
2615c51f124SMoriah Waterland 	uint32_t	lg;	/* running checksum value */
2625c51f124SMoriah Waterland 	uint32_t	buf[CHUNK/4]; /* to read CHUNK bytes */
2635c51f124SMoriah Waterland 	uint32_t	lsavhi;	/* high order two-bytes of four-byte checksum */
2645c51f124SMoriah Waterland 	uint32_t	lsavlo;	/* low order two-bytes of four-byte checksum */
2655c51f124SMoriah Waterland 	int		leap = sizeof (uint32_t);
2665c51f124SMoriah Waterland 	int		notyet = 0;
2675c51f124SMoriah Waterland 	int		nread;
2685c51f124SMoriah Waterland 	struct stat64	sbuf;
2695c51f124SMoriah Waterland 
2705c51f124SMoriah Waterland 	/* reset error flag */
2715c51f124SMoriah Waterland 	*r_cksumerr = 0;
2725c51f124SMoriah Waterland 
2735c51f124SMoriah Waterland 	/* open file and obtain -> where file is mapped/read */
2745c51f124SMoriah Waterland 	if ((fd = open(a_path, O_RDONLY)) < 0) {
2755c51f124SMoriah Waterland 		*r_cksumerr = 1;
2765c51f124SMoriah Waterland 		reperr(pkg_gt(ERR_NO_CKSUM));
2775c51f124SMoriah Waterland 		perror(ERR_NO_CKSUM);
2785c51f124SMoriah Waterland 		return (0);
2795c51f124SMoriah Waterland 	}
2805c51f124SMoriah Waterland 
2815c51f124SMoriah Waterland 	if (fstat64(fd, &sbuf) != 0) {
2825c51f124SMoriah Waterland 		*r_cksumerr = 1;
2835c51f124SMoriah Waterland 		reperr(pkg_gt(ERR_NO_CKSUM));
2845c51f124SMoriah Waterland 		perror(ERR_NO_CKSUM);
2855c51f124SMoriah Waterland 		return (0);
2865c51f124SMoriah Waterland 	}
2875c51f124SMoriah Waterland 
2885c51f124SMoriah Waterland 	/* initialize checksum value */
2895c51f124SMoriah Waterland 	lg = 0;
2905c51f124SMoriah Waterland 
2915c51f124SMoriah Waterland 	/*
2925c51f124SMoriah Waterland 	 * Read CHUNK bytes off the file at a time; Read size of long bytes
2935c51f124SMoriah Waterland 	 * from memory at a time and process them.
2945c51f124SMoriah Waterland 	 * If last read, then read remnant bytes and process individually.
2955c51f124SMoriah Waterland 	 */
2965c51f124SMoriah Waterland 	errno = 0;
2975c51f124SMoriah Waterland 	while ((nread = read(fd, (void*)buf,
298*3970c098SToomas Soome 	    (sbuf.st_size < CHUNK) ? sbuf.st_size : CHUNK)) > 0) {
2995c51f124SMoriah Waterland 		uchar_t *s;
3005c51f124SMoriah Waterland 		uint32_t *p = buf;
3015c51f124SMoriah Waterland 
3025c51f124SMoriah Waterland 		notyet = nread % leap;
3035c51f124SMoriah Waterland 		nread -= notyet;
3045c51f124SMoriah Waterland 
3055c51f124SMoriah Waterland 		for (; nread > 0; nread -= leap) {
3065c51f124SMoriah Waterland 			lg += ((((*p)>>24)&0xFF) & WDMSK);
3075c51f124SMoriah Waterland 			lg += ((((*p)>>16)&0xFF) & WDMSK);
3085c51f124SMoriah Waterland 			lg += ((((*p)>>8)&0xFF) & WDMSK);
3095c51f124SMoriah Waterland 			lg += (((*p)&0xFF) & WDMSK);
3105c51f124SMoriah Waterland 			p++;
3115c51f124SMoriah Waterland 		}
3125c51f124SMoriah Waterland 		s = (uchar_t *)p;
3135c51f124SMoriah Waterland 		/* leftover bytes less than four in number */
3145c51f124SMoriah Waterland 		while (notyet--)
3155c51f124SMoriah Waterland 			lg += (((uint32_t)(*s++)) & WDMSK);
3165c51f124SMoriah Waterland 	}
3175c51f124SMoriah Waterland 
3185c51f124SMoriah Waterland 	/* wind up */
3195c51f124SMoriah Waterland 	(void) close(fd);
3205c51f124SMoriah Waterland 
3215c51f124SMoriah Waterland 	/* compute checksum components */
3225c51f124SMoriah Waterland 	suma.lg = lg;
3235c51f124SMoriah Waterland 	tempa.lg = (suma.hl.lo & WDMSK) + (suma.hl.hi & WDMSK);
3245c51f124SMoriah Waterland 	lsavhi = (uint32_t)tempa.hl.hi;
3255c51f124SMoriah Waterland 	lsavlo = (uint32_t)tempa.hl.lo;
3265c51f124SMoriah Waterland 
3275c51f124SMoriah Waterland 	/* return final checksum value */
3285c51f124SMoriah Waterland 	return (lsavhi+lsavlo);
3295c51f124SMoriah Waterland }
3305c51f124SMoriah Waterland 
331*3970c098SToomas Soome static	struct stat	status;		/* file status buffer */
332*3970c098SToomas Soome static	struct statvfs	vfsstatus;	/* filesystem status buffer */
3335c51f124SMoriah Waterland 
3345c51f124SMoriah Waterland /*
3355c51f124SMoriah Waterland  * Remove the thing that's currently in place so we can put down the package
3365c51f124SMoriah Waterland  * object. If we're replacing a directory with a directory, leave it alone.
3375c51f124SMoriah Waterland  * Returns 1 if all OK and 0 if failed.
3385c51f124SMoriah Waterland  */
3395c51f124SMoriah Waterland static int
clear_target(char * path,char * ftype,int is_a_dir)3405c51f124SMoriah Waterland clear_target(char *path, char *ftype, int is_a_dir)
3415c51f124SMoriah Waterland {
3425c51f124SMoriah Waterland 	int retcode = 1;
3435c51f124SMoriah Waterland 
3445c51f124SMoriah Waterland 	if (is_a_dir) {	/* if there's a directory there already ... */
3455c51f124SMoriah Waterland 		/* ... and this isn't, ... */
3465c51f124SMoriah Waterland 		if ((*ftype != 'd') && (*ftype != 'x')) {
3475c51f124SMoriah Waterland 			if (rmdir(path)) {	/* try to remove it. */
3485c51f124SMoriah Waterland 				reperr(pkg_gt(ERR_RMDIR), path);
3495c51f124SMoriah Waterland 				retcode = 0;
3505c51f124SMoriah Waterland 			}
3515c51f124SMoriah Waterland 		}
3525c51f124SMoriah Waterland 	} else {
3535c51f124SMoriah Waterland 		if (remove(path)) {
3545c51f124SMoriah Waterland 			if (errno != ENOENT) {
3555c51f124SMoriah Waterland 				retcode = 0;	/* It didn't work. */
3565c51f124SMoriah Waterland 			}
3575c51f124SMoriah Waterland 		}
3585c51f124SMoriah Waterland 	}
3595c51f124SMoriah Waterland 
3605c51f124SMoriah Waterland 	return (retcode);
3615c51f124SMoriah Waterland }
3625c51f124SMoriah Waterland 
3635c51f124SMoriah Waterland /*
3645c51f124SMoriah Waterland  * Name:	averify
3655c51f124SMoriah Waterland  * Description:	This function verifies and (if fix > 0) fixes the attributes
3665c51f124SMoriah Waterland  *		of the file at the path provided.
3675c51f124SMoriah Waterland  * Arguments:	fix - 0 - do not fix entries, 1 - fix entries
3685c51f124SMoriah Waterland  *		ftype - single character "type" the entry is supposed to be
3695c51f124SMoriah Waterland  *		path - path to file
3705c51f124SMoriah Waterland  *		ainfo - attribute info structure representing the attributes
3715c51f124SMoriah Waterland  *			the entry is supposed to be
3725c51f124SMoriah Waterland  * NOTE:	attributes are links and permissions
3735c51f124SMoriah Waterland  * Possible return values:
3745c51f124SMoriah Waterland  * - 0 = successful
3755c51f124SMoriah Waterland  * - VE_EXIST = path name does not exist
3765c51f124SMoriah Waterland  * - VE_FTYPE = path file type is not recognized, is not supported,
3775c51f124SMoriah Waterland  *		or is not what was expected
3785c51f124SMoriah Waterland  * - VE_ATTR = path mode/group/user is not what was expected
3795c51f124SMoriah Waterland  * - VE_CONT = mod time/link target/major/minor/size/file system type/current
3805c51f124SMoriah Waterland  *		directory is not what was expected
3815c51f124SMoriah Waterland  * - VE_FAIL = utime/target directory/link/stat/symlink/mknod/chmod/statvfs/
3825c51f124SMoriah Waterland  *		chown failed
3835c51f124SMoriah Waterland  */
3845c51f124SMoriah Waterland int
averify(int fix,char * ftype,char * path,struct ainfo * ainfo)3855c51f124SMoriah Waterland averify(int fix, char *ftype, char *path, struct ainfo *ainfo)
3865c51f124SMoriah Waterland {
387*3970c098SToomas Soome 	struct group	*grp;	/* group entry buffer */
3885c51f124SMoriah Waterland 	struct passwd	*pwd;
3895c51f124SMoriah Waterland 	int		n;
3905c51f124SMoriah Waterland 	int		setval;
3915c51f124SMoriah Waterland 	int		uid, gid;
3925c51f124SMoriah Waterland 	int		dochown;
3935c51f124SMoriah Waterland 	int		retcode;
394b46ec01aSok 	int		statError = 0;
3955c51f124SMoriah Waterland 	int		targ_is_dir = 0;	/* replacing a directory */
3965c51f124SMoriah Waterland 	char		myftype;
3975c51f124SMoriah Waterland 	char		buf[PATH_MAX];
3985c51f124SMoriah Waterland 	ino_t		my_ino;
3995c51f124SMoriah Waterland 	dev_t		my_dev;
400*3970c098SToomas Soome 	char		cwd[MAXPATHLEN];
401*3970c098SToomas Soome 	char		*cd;
402*3970c098SToomas Soome 	char		*c;
4035c51f124SMoriah Waterland 
4045c51f124SMoriah Waterland 	setval = (*ftype == '?');
4055c51f124SMoriah Waterland 	retcode = 0;
4065c51f124SMoriah Waterland 	reperr(NULL);
4075c51f124SMoriah Waterland 
4085c51f124SMoriah Waterland 	if (get_disable_attribute_check()) {
4095c51f124SMoriah Waterland 		return (0);
4105c51f124SMoriah Waterland 	}
4115c51f124SMoriah Waterland 
4125c51f124SMoriah Waterland 	if (*ftype == 'l') {
4135c51f124SMoriah Waterland 		if (stat(path, &status) < 0) {
4145c51f124SMoriah Waterland 			retcode = VE_EXIST;
4155c51f124SMoriah Waterland 			reperr(pkg_gt(ERR_EXIST));
4165c51f124SMoriah Waterland 		}
4175c51f124SMoriah Waterland 
4185c51f124SMoriah Waterland 		my_ino = status.st_ino;
4195c51f124SMoriah Waterland 		my_dev = status.st_dev;
4205c51f124SMoriah Waterland 
4215c51f124SMoriah Waterland 		/* Get copy of the current working directory */
4225c51f124SMoriah Waterland 		if (getcwd(cwd, MAXPATHLEN) == NULL) {
4234656d474SGarrett D'Amore 			reperr(pkg_gt(ERR_GETWD));
4245c51f124SMoriah Waterland 			return (VE_FAIL);
4255c51f124SMoriah Waterland 		}
4265c51f124SMoriah Waterland 
4275c51f124SMoriah Waterland 		/*
4285c51f124SMoriah Waterland 		 * Change to the directory in which the hard
4295c51f124SMoriah Waterland 		 * link is to be created.
4305c51f124SMoriah Waterland 		 */
4315c51f124SMoriah Waterland 		cd = strdup(path);
4325c51f124SMoriah Waterland 		c = strrchr(cd, '/');
4335c51f124SMoriah Waterland 		if (c) {
4345c51f124SMoriah Waterland 			/* bugid 4247895 */
4355c51f124SMoriah Waterland 			if (strcmp(cd, c) == 0)
4364656d474SGarrett D'Amore 				(void) strcpy(cd, "/");
4375c51f124SMoriah Waterland 			else
438*3970c098SToomas Soome 				*c = '\0';
4395c51f124SMoriah Waterland 
4405c51f124SMoriah Waterland 			if (chdir(cd) != 0) {
4415c51f124SMoriah Waterland 				reperr(pkg_gt(ERR_CHDIR), cd);
4425c51f124SMoriah Waterland 				return (VE_FAIL);
4435c51f124SMoriah Waterland 			}
4445c51f124SMoriah Waterland 		}
4455c51f124SMoriah Waterland 		free(cd);
4465c51f124SMoriah Waterland 
4475c51f124SMoriah Waterland 		if (retcode || (status.st_nlink < 2) ||
4485c51f124SMoriah Waterland 		    (stat(ainfo->local, &status) < 0) ||
4495c51f124SMoriah Waterland 		    (my_dev != status.st_dev) || (my_ino != status.st_ino)) {
4505c51f124SMoriah Waterland 			if (fix) {
4515c51f124SMoriah Waterland 				/*
4525c51f124SMoriah Waterland 				 * Don't want to do a hard link to a
4535c51f124SMoriah Waterland 				 * directory.
4545c51f124SMoriah Waterland 				 */
4555c51f124SMoriah Waterland 				if (!isdir(ainfo->local)) {
4564656d474SGarrett D'Amore 					(void) chdir(cwd);
4575c51f124SMoriah Waterland 					reperr(pkg_gt(ERR_LINKISDIR),
4585c51f124SMoriah Waterland 					    ainfo->local);
4595c51f124SMoriah Waterland 					return (VE_FAIL);
4605c51f124SMoriah Waterland 				}
4615c51f124SMoriah Waterland 				/* Now do the link. */
4625c51f124SMoriah Waterland 				if (!clear_target(path, ftype, targ_is_dir))
4635c51f124SMoriah Waterland 					return (VE_FAIL);
4645c51f124SMoriah Waterland 
4655c51f124SMoriah Waterland 				if (link(ainfo->local, path)) {
4664656d474SGarrett D'Amore 					(void) chdir(cwd);
4675c51f124SMoriah Waterland 					reperr(pkg_gt(ERR_LINKFAIL),
4685c51f124SMoriah Waterland 					    ainfo->local);
4695c51f124SMoriah Waterland 					return (VE_FAIL);
4705c51f124SMoriah Waterland 				}
4715c51f124SMoriah Waterland 				retcode = 0;
4725c51f124SMoriah Waterland 			} else {
4735c51f124SMoriah Waterland 				/* Go back to previous working directory */
4745c51f124SMoriah Waterland 				if (chdir(cwd) != 0)
4755c51f124SMoriah Waterland 					reperr(pkg_gt(ERR_CHDIR), cwd);
4765c51f124SMoriah Waterland 
4775c51f124SMoriah Waterland 				reperr(pkg_gt(ERR_LINK), ainfo->local);
4785c51f124SMoriah Waterland 				return (VE_CONT);
4795c51f124SMoriah Waterland 			}
4805c51f124SMoriah Waterland 		}
4815c51f124SMoriah Waterland 
4825c51f124SMoriah Waterland 		/* Go back to previous working directory */
4835c51f124SMoriah Waterland 		if (chdir(cwd) != 0) {
4845c51f124SMoriah Waterland 			reperr(pkg_gt(ERR_CHDIR), cwd);
4855c51f124SMoriah Waterland 			return (VE_CONT);
4865c51f124SMoriah Waterland 		}
4875c51f124SMoriah Waterland 
4885c51f124SMoriah Waterland 		return (retcode);
4895c51f124SMoriah Waterland 	}
4905c51f124SMoriah Waterland 
4915c51f124SMoriah Waterland 	retcode = 0;
4925c51f124SMoriah Waterland 
493b46ec01aSok 	/* If we are to process symlinks the old way then we follow the link */
494b46ec01aSok 	if (nonABI_symlinks()) {
495b46ec01aSok 		if ((*ftype == 's') ? lstat(path, &status) :
496*3970c098SToomas Soome 		    stat(path, &status)) {
497b46ec01aSok 			reperr(pkg_gt(ERR_EXIST));
498b46ec01aSok 			retcode = VE_EXIST;
499b46ec01aSok 			myftype = '?';
500b46ec01aSok 			statError++;
501b46ec01aSok 		}
502b46ec01aSok 	/* If not then we inspect the target of the link */
503b46ec01aSok 	} else {
504b46ec01aSok 		if ((n = lstat(path, &status)) == -1) {
505b46ec01aSok 			reperr(pkg_gt(ERR_EXIST));
506b46ec01aSok 			retcode = VE_EXIST;
507b46ec01aSok 			myftype = '?';
508b46ec01aSok 			statError++;
509b46ec01aSok 		}
510b46ec01aSok 	}
511b46ec01aSok 	if (!statError) {
512b46ec01aSok 		/* determining actual type of existing object */
513b46ec01aSok 		switch (status.st_mode & S_IFMT) {
514*3970c098SToomas Soome 		case S_IFLNK:
515b46ec01aSok 			myftype = 's';
516b46ec01aSok 			break;
517b46ec01aSok 
518*3970c098SToomas Soome 		case S_IFIFO:
519b46ec01aSok 			myftype = 'p';
520b46ec01aSok 			break;
521b46ec01aSok 
522*3970c098SToomas Soome 		case S_IFCHR:
523b46ec01aSok 			myftype = 'c';
524b46ec01aSok 			break;
525b46ec01aSok 
526*3970c098SToomas Soome 		case S_IFDIR:
527b46ec01aSok 			myftype = 'd';
528b46ec01aSok 			targ_is_dir = 1;
529b46ec01aSok 			break;
530b46ec01aSok 
531*3970c098SToomas Soome 		case S_IFBLK:
532b46ec01aSok 			myftype = 'b';
533b46ec01aSok 			break;
534b46ec01aSok 
535*3970c098SToomas Soome 		case S_IFREG:
536*3970c098SToomas Soome 		case 0:
537b46ec01aSok 			myftype = 'f';
538b46ec01aSok 			break;
539b46ec01aSok 
540*3970c098SToomas Soome 		case S_IFDOOR:
541b46ec01aSok 			myftype = 'D';
542b46ec01aSok 			break;
543b46ec01aSok 
544*3970c098SToomas Soome 		default:
545b46ec01aSok 			reperr(pkg_gt(ERR_UNKNOWN));
546b46ec01aSok 			return (VE_FTYPE);
547b46ec01aSok 		}
548b46ec01aSok 	}
5495c51f124SMoriah Waterland 
5505c51f124SMoriah Waterland 	if (setval) {
5515c51f124SMoriah Waterland 		/*
5525c51f124SMoriah Waterland 		 * Check to make sure that a package or an installf that uses
5535c51f124SMoriah Waterland 		 * wild cards '?' to assume the ftype of an object on the
5545c51f124SMoriah Waterland 		 * system is not assuming a door ftype. Doors are not supported
5555c51f124SMoriah Waterland 		 * but should be ignored.
5565c51f124SMoriah Waterland 		 */
5575c51f124SMoriah Waterland 		if (myftype == 'D') {
5585c51f124SMoriah Waterland 			reperr(pkg_gt(ERR_FTYPED), path);
5595c51f124SMoriah Waterland 			retcode = VE_FTYPE;
5605c51f124SMoriah Waterland 			return (VE_FTYPE);
5615c51f124SMoriah Waterland 		} else {
5625c51f124SMoriah Waterland 			*ftype = myftype;
5635c51f124SMoriah Waterland 		}
5645c51f124SMoriah Waterland 	} else if (!retcode && (*ftype != myftype) &&
5655c51f124SMoriah Waterland 	    ((myftype != 'f') || !strchr("ilev", *ftype)) &&
5665c51f124SMoriah Waterland 	    ((myftype != 'd') || (*ftype != 'x'))) {
5675c51f124SMoriah Waterland 		reperr(pkg_gt(ERR_FTYPE), *ftype, myftype);
5685c51f124SMoriah Waterland 		retcode = VE_FTYPE;
5695c51f124SMoriah Waterland 	}
5705c51f124SMoriah Waterland 
5715c51f124SMoriah Waterland 	if (!retcode && (*ftype == 's')) {
5725c51f124SMoriah Waterland 		/* make sure that symbolic link is correct */
5735c51f124SMoriah Waterland 		n = readlink(path, buf, PATH_MAX);
5745c51f124SMoriah Waterland 		if (n < 0) {
5755c51f124SMoriah Waterland 			reperr(pkg_gt(ERR_SLINK), ainfo->local);
5765c51f124SMoriah Waterland 			retcode = VE_CONT;
5775c51f124SMoriah Waterland 		} else if (ainfo->local != NULL) {
5785c51f124SMoriah Waterland 			buf[n] = '\0';
5795c51f124SMoriah Waterland 			if (strcmp(buf, ainfo->local)) {
5805c51f124SMoriah Waterland 				reperr(pkg_gt(ERR_SLINK), ainfo->local);
5815c51f124SMoriah Waterland 				retcode = VE_CONT;
5825c51f124SMoriah Waterland 			}
5835c51f124SMoriah Waterland 		} else if (ainfo->local == NULL) {
5845c51f124SMoriah Waterland 			/*
5855c51f124SMoriah Waterland 			 * Since a sym link target exists, insert it
5865c51f124SMoriah Waterland 			 * into the ainfo structure
5875c51f124SMoriah Waterland 			 */
5885c51f124SMoriah Waterland 			buf[n] = '\0';
5895c51f124SMoriah Waterland 			ainfo->local = strdup(buf);
5905c51f124SMoriah Waterland 		}
5915c51f124SMoriah Waterland 	}
5925c51f124SMoriah Waterland 
5935c51f124SMoriah Waterland 	if (retcode) {
5945c51f124SMoriah Waterland 		/* The path doesn't exist or is different than it should be. */
5955c51f124SMoriah Waterland 		if (fix) {
5965c51f124SMoriah Waterland 			/*
5975c51f124SMoriah Waterland 			 * Clear the way for the write. If it won't clear,
5985c51f124SMoriah Waterland 			 * there's nothing we can do.
5995c51f124SMoriah Waterland 			 */
6005c51f124SMoriah Waterland 			if (!clear_target(path, ftype, targ_is_dir))
6015c51f124SMoriah Waterland 				return (VE_FAIL);
6025c51f124SMoriah Waterland 
6035c51f124SMoriah Waterland 			if ((*ftype == 'd') || (*ftype == 'x')) {
6045c51f124SMoriah Waterland 				char	*pt, *p;
6055c51f124SMoriah Waterland 
6065c51f124SMoriah Waterland 				/* Try to make it the easy way */
6075c51f124SMoriah Waterland 				if (mkdir(path, ainfo->mode)) {
6085c51f124SMoriah Waterland 					/*
6095c51f124SMoriah Waterland 					 * Failing that, walk through the
6105c51f124SMoriah Waterland 					 * parent directories creating
6115c51f124SMoriah Waterland 					 * whatever is needed.
6125c51f124SMoriah Waterland 					 */
6135c51f124SMoriah Waterland 					p = strdup(path);
6145c51f124SMoriah Waterland 					pt = (*p == '/') ? p+1 : p;
6155c51f124SMoriah Waterland 					do {
6165c51f124SMoriah Waterland 						if (pt = strchr(pt, '/'))
6175c51f124SMoriah Waterland 							*pt = '\0';
6185c51f124SMoriah Waterland 						if (access(p, 0) &&
6195c51f124SMoriah Waterland 						    mkdir(p, ainfo->mode))
6205c51f124SMoriah Waterland 							break;
6215c51f124SMoriah Waterland 						if (pt)
6225c51f124SMoriah Waterland 							*pt++ = '/';
6235c51f124SMoriah Waterland 					} while (pt);
6245c51f124SMoriah Waterland 					free(p);
6255c51f124SMoriah Waterland 				}
6265c51f124SMoriah Waterland 				if (stat(path, &status) < 0) {
6275c51f124SMoriah Waterland 					reperr(pkg_gt(ERR_DIRFAIL));
6285c51f124SMoriah Waterland 					return (VE_FAIL);
6295c51f124SMoriah Waterland 				}
6305c51f124SMoriah Waterland 			} else if (*ftype == 's') {
6315c51f124SMoriah Waterland 				if (symlink(ainfo->local, path)) {
6325c51f124SMoriah Waterland 					reperr(pkg_gt(ERR_SLINKFAIL),
6335c51f124SMoriah Waterland 					    ainfo->local);
6345c51f124SMoriah Waterland 					return (VE_FAIL);
6355c51f124SMoriah Waterland 				}
6365c51f124SMoriah Waterland 
6375c51f124SMoriah Waterland 			} else if (*ftype == 'c') {
6385c51f124SMoriah Waterland 				int wilddevno = 0;
6395c51f124SMoriah Waterland 				/*
6405c51f124SMoriah Waterland 				 * The next three if's support 2.4 and older
6415c51f124SMoriah Waterland 				 * packages that use "?" as device numbers.
6425c51f124SMoriah Waterland 				 * This should be considered for removal by
6435c51f124SMoriah Waterland 				 * release 2.7 or so.
6445c51f124SMoriah Waterland 				 */
6455c51f124SMoriah Waterland 				if (ainfo->major == BADMAJOR) {
6465c51f124SMoriah Waterland 					ainfo->major = 0;
6475c51f124SMoriah Waterland 					wilddevno = 1;
6485c51f124SMoriah Waterland 				}
6495c51f124SMoriah Waterland 
6505c51f124SMoriah Waterland 				if (ainfo->minor == BADMINOR) {
6515c51f124SMoriah Waterland 					ainfo->minor = 0;
6525c51f124SMoriah Waterland 					wilddevno = 1;
6535c51f124SMoriah Waterland 				}
6545c51f124SMoriah Waterland 
6555c51f124SMoriah Waterland 				if (wilddevno) {
6565c51f124SMoriah Waterland 					wilddevno = 0;
6575c51f124SMoriah Waterland 					logerr(MSG_WLDDEVNO, path,
6585c51f124SMoriah Waterland 					    ainfo->major, ainfo->minor);
6595c51f124SMoriah Waterland 				}
6605c51f124SMoriah Waterland 
6615c51f124SMoriah Waterland 				if (mknod(path, ainfo->mode | S_IFCHR,
6625c51f124SMoriah Waterland 				    makedev(ainfo->major, ainfo->minor)) ||
6635c51f124SMoriah Waterland 				    (stat(path, &status) < 0)) {
6645c51f124SMoriah Waterland 					reperr(pkg_gt(ERR_CDEVFAIL));
6655c51f124SMoriah Waterland 					return (VE_FAIL);
6665c51f124SMoriah Waterland 				}
6675c51f124SMoriah Waterland 			} else if (*ftype == 'b') {
6685c51f124SMoriah Waterland 				int wilddevno = 0;
6695c51f124SMoriah Waterland 				/*
6705c51f124SMoriah Waterland 				 * The next three if's support 2.4 and older
6715c51f124SMoriah Waterland 				 * packages that use "?" as device numbers.
6725c51f124SMoriah Waterland 				 * This should be considered for removal by
6735c51f124SMoriah Waterland 				 * release 2.7 or so.
6745c51f124SMoriah Waterland 				 */
6755c51f124SMoriah Waterland 				if (ainfo->major == BADMAJOR) {
6765c51f124SMoriah Waterland 					ainfo->major = 0;
6775c51f124SMoriah Waterland 					wilddevno = 1;
6785c51f124SMoriah Waterland 				}
6795c51f124SMoriah Waterland 
6805c51f124SMoriah Waterland 				if (ainfo->minor == BADMINOR) {
6815c51f124SMoriah Waterland 					ainfo->minor = 0;
6825c51f124SMoriah Waterland 					wilddevno = 1;
6835c51f124SMoriah Waterland 				}
6845c51f124SMoriah Waterland 
6855c51f124SMoriah Waterland 				if (wilddevno) {
6865c51f124SMoriah Waterland 					wilddevno = 0;
6875c51f124SMoriah Waterland 					logerr(MSG_WLDDEVNO, path,
6885c51f124SMoriah Waterland 					    ainfo->major, ainfo->minor);
6895c51f124SMoriah Waterland 				}
6905c51f124SMoriah Waterland 
6915c51f124SMoriah Waterland 				if (mknod(path, ainfo->mode | S_IFBLK,
6925c51f124SMoriah Waterland 				    makedev(ainfo->major, ainfo->minor)) ||
6935c51f124SMoriah Waterland 				    (stat(path, &status) < 0)) {
6945c51f124SMoriah Waterland 					reperr(pkg_gt(ERR_BDEVFAIL));
6955c51f124SMoriah Waterland 					return (VE_FAIL);
6965c51f124SMoriah Waterland 				}
6975c51f124SMoriah Waterland 			} else if (*ftype == 'p') {
698*3970c098SToomas Soome 				if (mknod(path, ainfo->mode | S_IFIFO, 0) ||
6995c51f124SMoriah Waterland 				    (stat(path, &status) < 0)) {
7005c51f124SMoriah Waterland 					reperr(pkg_gt(ERR_PIPEFAIL));
7015c51f124SMoriah Waterland 					return (VE_FAIL);
7025c51f124SMoriah Waterland 				}
7035c51f124SMoriah Waterland 			} else
7045c51f124SMoriah Waterland 				return (retcode);
7055c51f124SMoriah Waterland 
7065c51f124SMoriah Waterland 		} else
7075c51f124SMoriah Waterland 			return (retcode);
7085c51f124SMoriah Waterland 	}
7095c51f124SMoriah Waterland 
7105c51f124SMoriah Waterland 	if (*ftype == 's')
7115c51f124SMoriah Waterland 		return (0); /* don't check anything else */
7125c51f124SMoriah Waterland 	if (*ftype == 'i')
7135c51f124SMoriah Waterland 		return (0); /* don't check anything else */
7145c51f124SMoriah Waterland 
7155c51f124SMoriah Waterland 	retcode = 0;
7165c51f124SMoriah Waterland 	if ((myftype == 'c') || (myftype == 'b')) {
7175c51f124SMoriah Waterland 		if (setval || (ainfo->major == BADMAJOR))
7185c51f124SMoriah Waterland 			ainfo->major = major(status.st_rdev);
7195c51f124SMoriah Waterland 		if (setval || (ainfo->minor == BADMINOR))
7205c51f124SMoriah Waterland 			ainfo->minor = minor(status.st_rdev);
7215c51f124SMoriah Waterland 		/* check major & minor */
7225c51f124SMoriah Waterland 		if (status.st_rdev != makedev(ainfo->major, ainfo->minor)) {
7235c51f124SMoriah Waterland 			reperr(pkg_gt(ERR_MAJMIN), ainfo->major, ainfo->minor,
7245c51f124SMoriah Waterland 			    major(status.st_rdev), minor(status.st_rdev));
7255c51f124SMoriah Waterland 			retcode = VE_CONT;
7265c51f124SMoriah Waterland 		}
7275c51f124SMoriah Waterland 	}
7285c51f124SMoriah Waterland 
7295c51f124SMoriah Waterland 	/* compare specified mode w/ actual mode excluding sticky bit */
7305c51f124SMoriah Waterland 	if (setval || (ainfo->mode == BADMODE) || (ainfo->mode == WILDCARD))
7315c51f124SMoriah Waterland 		ainfo->mode = status.st_mode & 07777;
7325c51f124SMoriah Waterland 	else if ((ainfo->mode & 06777) != (status.st_mode & 06777)) {
7335c51f124SMoriah Waterland 		if (fix) {
7345c51f124SMoriah Waterland 			if ((ainfo->mode == BADMODE) ||
7355c51f124SMoriah Waterland 			    (chmod(path, ainfo->mode) < 0))
7365c51f124SMoriah Waterland 				retcode = VE_FAIL;
7375c51f124SMoriah Waterland 		} else {
7385c51f124SMoriah Waterland 			reperr(pkg_gt(ERR_PERM), ainfo->mode,
739*3970c098SToomas Soome 			    status.st_mode & 07777);
7405c51f124SMoriah Waterland 			if (!retcode)
7415c51f124SMoriah Waterland 				retcode = VE_ATTR;
7425c51f124SMoriah Waterland 		}
7435c51f124SMoriah Waterland 	}
7445c51f124SMoriah Waterland 
7455c51f124SMoriah Waterland 	dochown = 0;
7465c51f124SMoriah Waterland 
7475c51f124SMoriah Waterland 	/* get group entry for specified group */
7485c51f124SMoriah Waterland 	if (setval || strcmp(ainfo->group, BADGROUP) == 0) {
7495c51f124SMoriah Waterland 		grp = cgrgid(status.st_gid);
7505c51f124SMoriah Waterland 		if (grp)
7515c51f124SMoriah Waterland 			(void) strcpy(ainfo->group, grp->gr_name);
7525c51f124SMoriah Waterland 		else {
7535c51f124SMoriah Waterland 			if (!retcode)
7545c51f124SMoriah Waterland 				retcode = VE_ATTR;
7555c51f124SMoriah Waterland 			reperr(pkg_gt(ERR_BADGRPID), status.st_gid);
7565c51f124SMoriah Waterland 		}
7575c51f124SMoriah Waterland 		gid = status.st_gid;
7585c51f124SMoriah Waterland 	} else if ((grp = cgrnam(ainfo->group)) == NULL) {
7595c51f124SMoriah Waterland 		reperr(pkg_gt(ERR_BADGRPNM), ainfo->group);
7605c51f124SMoriah Waterland 		if (!retcode)
7615c51f124SMoriah Waterland 			retcode = VE_ATTR;
7625c51f124SMoriah Waterland 	} else if ((gid = grp->gr_gid) != status.st_gid) {
7635c51f124SMoriah Waterland 		if (fix) {
7645c51f124SMoriah Waterland 			/* save specified GID */
7655c51f124SMoriah Waterland 			gid = grp->gr_gid;
7665c51f124SMoriah Waterland 			dochown++;
7675c51f124SMoriah Waterland 		} else {
7685c51f124SMoriah Waterland 			if ((grp = cgrgid((int)status.st_gid)) ==
7695c51f124SMoriah Waterland 			    (struct group *)NULL) {
7705c51f124SMoriah Waterland 				reperr(pkg_gt(ERR_GROUP), ainfo->group,
7715c51f124SMoriah Waterland 				    "(null)");
7725c51f124SMoriah Waterland 			} else {
7735c51f124SMoriah Waterland 				reperr(pkg_gt(ERR_GROUP), ainfo->group,
7745c51f124SMoriah Waterland 				    grp->gr_name);
7755c51f124SMoriah Waterland 			}
7765c51f124SMoriah Waterland 			if (!retcode)
7775c51f124SMoriah Waterland 				retcode = VE_ATTR;
7785c51f124SMoriah Waterland 		}
7795c51f124SMoriah Waterland 	}
7805c51f124SMoriah Waterland 
7815c51f124SMoriah Waterland 	/* get password entry for specified owner */
7825c51f124SMoriah Waterland 	if (setval || strcmp(ainfo->owner, BADOWNER) == 0) {
7835c51f124SMoriah Waterland 		pwd = cpwuid((int)status.st_uid);
7845c51f124SMoriah Waterland 		if (pwd)
7855c51f124SMoriah Waterland 			(void) strcpy(ainfo->owner, pwd->pw_name);
7865c51f124SMoriah Waterland 		else {
7875c51f124SMoriah Waterland 			if (!retcode)
7885c51f124SMoriah Waterland 				retcode = VE_ATTR;
7895c51f124SMoriah Waterland 			reperr(pkg_gt(ERR_BADUSRID), status.st_uid);
7905c51f124SMoriah Waterland 		}
7915c51f124SMoriah Waterland 		uid = status.st_uid;
7925c51f124SMoriah Waterland 	} else if ((pwd = cpwnam(ainfo->owner)) == NULL) {
7935c51f124SMoriah Waterland 		/* UID does not exist in password file */
7945c51f124SMoriah Waterland 		reperr(pkg_gt(ERR_BADUSRNM), ainfo->owner);
7955c51f124SMoriah Waterland 		if (!retcode)
7965c51f124SMoriah Waterland 			retcode = VE_ATTR;
7975c51f124SMoriah Waterland 	} else if ((uid = pwd->pw_uid) != status.st_uid) {
7985c51f124SMoriah Waterland 		/* get owner name for actual UID */
7995c51f124SMoriah Waterland 		if (fix) {
8005c51f124SMoriah Waterland 			uid = pwd->pw_uid;
8015c51f124SMoriah Waterland 			dochown++;
8025c51f124SMoriah Waterland 		} else {
8035c51f124SMoriah Waterland 			pwd = cpwuid((int)status.st_uid);
8045c51f124SMoriah Waterland 			if (pwd == NULL)
8055c51f124SMoriah Waterland 				reperr(pkg_gt(ERR_BADUSRID),
8065c51f124SMoriah Waterland 				    (int)status.st_uid);
8075c51f124SMoriah Waterland 			else
8085c51f124SMoriah Waterland 				reperr(pkg_gt(ERR_OWNER), ainfo->owner,
8095c51f124SMoriah Waterland 				    pwd->pw_name);
8105c51f124SMoriah Waterland 
8115c51f124SMoriah Waterland 			if (!retcode)
8125c51f124SMoriah Waterland 				retcode = VE_ATTR;
8135c51f124SMoriah Waterland 		}
8145c51f124SMoriah Waterland 	}
8155c51f124SMoriah Waterland 
8165c51f124SMoriah Waterland 	if (statvfs(path, &vfsstatus) < 0) {
8175c51f124SMoriah Waterland 		reperr(pkg_gt(ERR_EXIST));
8185c51f124SMoriah Waterland 		retcode = VE_FAIL;
8195c51f124SMoriah Waterland 	} else {
8205c51f124SMoriah Waterland 		if (dochown) {
8215c51f124SMoriah Waterland 			/* pcfs doesn't support file ownership */
8225c51f124SMoriah Waterland 			if (strcmp(vfsstatus.f_basetype, "pcfs") != 0 &&
8235c51f124SMoriah Waterland 			    chown(path, uid, gid) < 0) {
8245c51f124SMoriah Waterland 				retcode = VE_FAIL; /* chown failed */
8255c51f124SMoriah Waterland 			}
8265c51f124SMoriah Waterland 		}
8275c51f124SMoriah Waterland 	}
8285c51f124SMoriah Waterland 
8295c51f124SMoriah Waterland 	if (retcode == VE_FAIL)
8305c51f124SMoriah Waterland 		reperr(pkg_gt(ERR_ATTRFAIL));
8315c51f124SMoriah Waterland 	return (retcode);
8325c51f124SMoriah Waterland }
8335c51f124SMoriah Waterland 
8345c51f124SMoriah Waterland /*
8355c51f124SMoriah Waterland  * This is a special fast verify which basically checks the attributes
8365c51f124SMoriah Waterland  * and then, if all is OK, checks the size and mod time using the same
8375c51f124SMoriah Waterland  * stat and statvfs structures.
8385c51f124SMoriah Waterland  */
8395c51f124SMoriah Waterland int
fverify(int fix,char * ftype,char * path,struct ainfo * ainfo,struct cinfo * cinfo)8405c51f124SMoriah Waterland fverify(int fix, char *ftype, char *path, struct ainfo *ainfo,
8415c51f124SMoriah Waterland     struct cinfo *cinfo)
8425c51f124SMoriah Waterland {
8435c51f124SMoriah Waterland 	int retval;
8445c51f124SMoriah Waterland 
8455c51f124SMoriah Waterland 	/* return success if attribute checks are disabled */
8465c51f124SMoriah Waterland 
8475c51f124SMoriah Waterland 	if (get_disable_attribute_check()) {
8485c51f124SMoriah Waterland 		return (0);
8495c51f124SMoriah Waterland 	}
8505c51f124SMoriah Waterland 
8515c51f124SMoriah Waterland 	if ((retval = averify(fix, ftype, path, ainfo)) == 0) {
8525c51f124SMoriah Waterland 		if (*ftype == 'f' || *ftype == 'i') {
8535c51f124SMoriah Waterland 			if (cinfo->size != status.st_size) {
8545c51f124SMoriah Waterland 				reperr(pkg_gt(WRN_QV_SIZE), path);
8555c51f124SMoriah Waterland 				retval = VE_CONT;
8565c51f124SMoriah Waterland 			}
8575c51f124SMoriah Waterland 			/* pcfs doesn't support modification times */
8585c51f124SMoriah Waterland 			if (strcmp(vfsstatus.f_basetype, "pcfs") != 0) {
8595c51f124SMoriah Waterland 				if (cinfo->modtime != status.st_mtime) {
8605c51f124SMoriah Waterland 					reperr(pkg_gt(WRN_QV_MTIME), path);
8615c51f124SMoriah Waterland 					retval = VE_CONT;
8625c51f124SMoriah Waterland 				}
8635c51f124SMoriah Waterland 			}
8645c51f124SMoriah Waterland 		}
8655c51f124SMoriah Waterland 	}
8665c51f124SMoriah Waterland 
8675c51f124SMoriah Waterland 	return (retval);
8685c51f124SMoriah Waterland }
8695c51f124SMoriah Waterland 
8705c51f124SMoriah Waterland /*
8715c51f124SMoriah Waterland  * This function determines whether or not non-ABI symlinks are supported.
8725c51f124SMoriah Waterland  */
8735c51f124SMoriah Waterland 
8745c51f124SMoriah Waterland int
nonABI_symlinks(void)8755c51f124SMoriah Waterland nonABI_symlinks(void)
8765c51f124SMoriah Waterland {
8775c51f124SMoriah Waterland 	return (nonabi_symlinks);
8785c51f124SMoriah Waterland }
8795c51f124SMoriah Waterland 
8805c51f124SMoriah Waterland void
set_nonABI_symlinks(void)8815c51f124SMoriah Waterland set_nonABI_symlinks(void)
8825c51f124SMoriah Waterland {
8835c51f124SMoriah Waterland 	nonabi_symlinks	= 1;
8845c51f124SMoriah Waterland }
8855c51f124SMoriah Waterland 
8865c51f124SMoriah Waterland /*
8875c51f124SMoriah Waterland  * Disable attribute checking. Only disable attribute checking if files
8885c51f124SMoriah Waterland  * are guaranteed to exist in the FS.
8895c51f124SMoriah Waterland  */
8905c51f124SMoriah Waterland void
disable_attribute_check(void)8915c51f124SMoriah Waterland disable_attribute_check(void)
8925c51f124SMoriah Waterland {
8935c51f124SMoriah Waterland 	disable_attributes = 1;
8945c51f124SMoriah Waterland }
8955c51f124SMoriah Waterland 
8965c51f124SMoriah Waterland /*
8975c51f124SMoriah Waterland  * This function determines whether or not to do attribute checking.
8985c51f124SMoriah Waterland  * Returns:  0 - Do attribute checking
8995c51f124SMoriah Waterland  *          !0 - Don't do attribute checking
9005c51f124SMoriah Waterland  */
9015c51f124SMoriah Waterland int
get_disable_attribute_check(void)9025c51f124SMoriah Waterland get_disable_attribute_check(void)
9035c51f124SMoriah Waterland {
9045c51f124SMoriah Waterland 	return (disable_attributes);
9055c51f124SMoriah Waterland }
9065c51f124SMoriah Waterland 
9075c51f124SMoriah Waterland /*
9085c51f124SMoriah Waterland  * This function returns the address of the "global" error buffer that
9095c51f124SMoriah Waterland  * is populated by the various functions in this module.
9105c51f124SMoriah Waterland  */
9115c51f124SMoriah Waterland 
9125c51f124SMoriah Waterland char *
getErrbufAddr(void)9135c51f124SMoriah Waterland getErrbufAddr(void)
9145c51f124SMoriah Waterland {
9155c51f124SMoriah Waterland 	return (theErrBuf);
9165c51f124SMoriah Waterland }
9175c51f124SMoriah Waterland 
9185c51f124SMoriah Waterland /*
9195c51f124SMoriah Waterland  * This function returns the size of the buffer returned by getErrbufAddr()
9205c51f124SMoriah Waterland  */
9215c51f124SMoriah Waterland 
9225c51f124SMoriah Waterland int
getErrbufSize(void)9235c51f124SMoriah Waterland getErrbufSize(void)
9245c51f124SMoriah Waterland {
9255c51f124SMoriah Waterland 	return (sizeof (theErrBuf));
9265c51f124SMoriah Waterland }
9275c51f124SMoriah Waterland 
9285c51f124SMoriah Waterland /*
9295c51f124SMoriah Waterland  * This function returns the current global "error string"
9305c51f124SMoriah Waterland  */
9315c51f124SMoriah Waterland 
9325c51f124SMoriah Waterland char *
getErrstr(void)9335c51f124SMoriah Waterland getErrstr(void)
9345c51f124SMoriah Waterland {
9355c51f124SMoriah Waterland 	return (theErrStr);
9365c51f124SMoriah Waterland }
9375c51f124SMoriah Waterland 
9385c51f124SMoriah Waterland /*
9395c51f124SMoriah Waterland  * This function sets the global "error string"
9405c51f124SMoriah Waterland  */
9415c51f124SMoriah Waterland 
9425c51f124SMoriah Waterland void
setErrstr(char * a_errstr)9435c51f124SMoriah Waterland setErrstr(char *a_errstr)
9445c51f124SMoriah Waterland {
9455c51f124SMoriah Waterland 	theErrStr = a_errstr;
9465c51f124SMoriah Waterland }
9475c51f124SMoriah Waterland 
9485c51f124SMoriah Waterland /*
9495c51f124SMoriah Waterland  * This function enables checksumming
9505c51f124SMoriah Waterland  */
9515c51f124SMoriah Waterland 
9525c51f124SMoriah Waterland void
checksum_on(void)9535c51f124SMoriah Waterland checksum_on(void)
9545c51f124SMoriah Waterland {
9555c51f124SMoriah Waterland 	enable_checksum = 1;
9565c51f124SMoriah Waterland }
9575c51f124SMoriah Waterland 
9585c51f124SMoriah Waterland /*
9595c51f124SMoriah Waterland  * This function disables checksumming
9605c51f124SMoriah Waterland  */
9615c51f124SMoriah Waterland 
9625c51f124SMoriah Waterland void
checksum_off(void)9635c51f124SMoriah Waterland checksum_off(void)
9645c51f124SMoriah Waterland {
9655c51f124SMoriah Waterland 	enable_checksum = 0;
9665c51f124SMoriah Waterland }
967