xref: /onnv-gate/usr/src/lib/libpkg/common/verify.c (revision 10176:7d4731c42dff)
19781SMoriah.Waterland@Sun.COM /*
29781SMoriah.Waterland@Sun.COM  * CDDL HEADER START
39781SMoriah.Waterland@Sun.COM  *
49781SMoriah.Waterland@Sun.COM  * The contents of this file are subject to the terms of the
59781SMoriah.Waterland@Sun.COM  * Common Development and Distribution License (the "License").
69781SMoriah.Waterland@Sun.COM  * You may not use this file except in compliance with the License.
79781SMoriah.Waterland@Sun.COM  *
89781SMoriah.Waterland@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
99781SMoriah.Waterland@Sun.COM  * or http://www.opensolaris.org/os/licensing.
109781SMoriah.Waterland@Sun.COM  * See the License for the specific language governing permissions
119781SMoriah.Waterland@Sun.COM  * and limitations under the License.
129781SMoriah.Waterland@Sun.COM  *
139781SMoriah.Waterland@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
149781SMoriah.Waterland@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
159781SMoriah.Waterland@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
169781SMoriah.Waterland@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
179781SMoriah.Waterland@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
189781SMoriah.Waterland@Sun.COM  *
199781SMoriah.Waterland@Sun.COM  * CDDL HEADER END
209781SMoriah.Waterland@Sun.COM  */
219781SMoriah.Waterland@Sun.COM 
229781SMoriah.Waterland@Sun.COM /*
239781SMoriah.Waterland@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
249781SMoriah.Waterland@Sun.COM  * Use is subject to license terms.
259781SMoriah.Waterland@Sun.COM  */
269781SMoriah.Waterland@Sun.COM 
279781SMoriah.Waterland@Sun.COM /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
289781SMoriah.Waterland@Sun.COM /* All Rights Reserved */
299781SMoriah.Waterland@Sun.COM 
309781SMoriah.Waterland@Sun.COM 
319781SMoriah.Waterland@Sun.COM 
329781SMoriah.Waterland@Sun.COM #include <stdio.h>
339781SMoriah.Waterland@Sun.COM #include <limits.h>
349781SMoriah.Waterland@Sun.COM #include <stdlib.h>
359781SMoriah.Waterland@Sun.COM #include <unistd.h>
369781SMoriah.Waterland@Sun.COM #include <utime.h>
379781SMoriah.Waterland@Sun.COM #include <sys/types.h>
389781SMoriah.Waterland@Sun.COM #include <sys/param.h>
399781SMoriah.Waterland@Sun.COM #include <sys/stat.h>
409781SMoriah.Waterland@Sun.COM #include <sys/statvfs.h>
419781SMoriah.Waterland@Sun.COM #include <grp.h>
429781SMoriah.Waterland@Sun.COM #include <pwd.h>
439781SMoriah.Waterland@Sun.COM #include <errno.h>
449781SMoriah.Waterland@Sun.COM #include <string.h>
459781SMoriah.Waterland@Sun.COM #include <stdarg.h>
469781SMoriah.Waterland@Sun.COM #include <fcntl.h>
479781SMoriah.Waterland@Sun.COM #include <sys/mkdev.h>
489781SMoriah.Waterland@Sun.COM #include "pkgstrct.h"
499781SMoriah.Waterland@Sun.COM #include "pkglib.h"
509781SMoriah.Waterland@Sun.COM #include "pkglibmsgs.h"
519781SMoriah.Waterland@Sun.COM #include "pkglocale.h"
529781SMoriah.Waterland@Sun.COM 
539781SMoriah.Waterland@Sun.COM #define	WDMSK	0xFFFF
549781SMoriah.Waterland@Sun.COM #define	DATEFMT	"%D %r"
559781SMoriah.Waterland@Sun.COM #define	LONG_BOUNDARY	((sizeof (unsigned long))-1)
569781SMoriah.Waterland@Sun.COM #define	CHUNK	1024*1024
579781SMoriah.Waterland@Sun.COM 
589781SMoriah.Waterland@Sun.COM static char	theErrBuf[PATH_MAX+512] = {'\0'};
599781SMoriah.Waterland@Sun.COM static char	*theErrStr = NULL;
609781SMoriah.Waterland@Sun.COM 
619781SMoriah.Waterland@Sun.COM /* checksum disable switch */
629781SMoriah.Waterland@Sun.COM static int	enable_checksum = 1;
639781SMoriah.Waterland@Sun.COM 
649781SMoriah.Waterland@Sun.COM /* attribute disable flag */
659781SMoriah.Waterland@Sun.COM static int	disable_attributes = 0;
669781SMoriah.Waterland@Sun.COM 
679781SMoriah.Waterland@Sun.COM /* non-ABI symlinks supported */
689781SMoriah.Waterland@Sun.COM static int	nonabi_symlinks;
699781SMoriah.Waterland@Sun.COM 
709781SMoriah.Waterland@Sun.COM /*
719781SMoriah.Waterland@Sun.COM  * forward declarations
729781SMoriah.Waterland@Sun.COM  */
739781SMoriah.Waterland@Sun.COM 
749781SMoriah.Waterland@Sun.COM static int	clear_target(char *path, char *ftype, int is_a_dir);
759781SMoriah.Waterland@Sun.COM 
769781SMoriah.Waterland@Sun.COM unsigned	long compute_checksum(int *r_err, char *path);
779781SMoriah.Waterland@Sun.COM 
789781SMoriah.Waterland@Sun.COM /* union used to generate checksum */
799781SMoriah.Waterland@Sun.COM typedef union hilo {
809781SMoriah.Waterland@Sun.COM 	struct part {
819781SMoriah.Waterland@Sun.COM 		uint16_t hi;
829781SMoriah.Waterland@Sun.COM 		uint16_t lo;
839781SMoriah.Waterland@Sun.COM 	} hl;
849781SMoriah.Waterland@Sun.COM 	uint32_t	lg;
859781SMoriah.Waterland@Sun.COM } CHECKSUM_T;
869781SMoriah.Waterland@Sun.COM 
879781SMoriah.Waterland@Sun.COM /*PRINTFLIKE1*/
88*10176Sok199659 static void
reperr(char * fmt,...)899781SMoriah.Waterland@Sun.COM reperr(char *fmt, ...)
909781SMoriah.Waterland@Sun.COM {
919781SMoriah.Waterland@Sun.COM 	char	*pt;
929781SMoriah.Waterland@Sun.COM 	ssize_t	ptln;
939781SMoriah.Waterland@Sun.COM 	va_list	ap;
949781SMoriah.Waterland@Sun.COM 	int	n;
959781SMoriah.Waterland@Sun.COM 
969781SMoriah.Waterland@Sun.COM 	if (fmt == (char *)NULL) {
979781SMoriah.Waterland@Sun.COM 		theErrBuf[0] = '\0';
989781SMoriah.Waterland@Sun.COM 	} else {
999781SMoriah.Waterland@Sun.COM 		if (n = strlen(theErrBuf)) {
1009781SMoriah.Waterland@Sun.COM 			pt = theErrBuf + n;
1019781SMoriah.Waterland@Sun.COM 			*pt++ = '\n';
1029781SMoriah.Waterland@Sun.COM 			*pt = '\0';
1039781SMoriah.Waterland@Sun.COM 			ptln = sizeof (theErrBuf)-n;
1049781SMoriah.Waterland@Sun.COM 		} else {
1059781SMoriah.Waterland@Sun.COM 			pt = theErrBuf;
1069781SMoriah.Waterland@Sun.COM 			ptln = sizeof (theErrBuf);
1079781SMoriah.Waterland@Sun.COM 		}
1089781SMoriah.Waterland@Sun.COM 		va_start(ap, fmt);
1099781SMoriah.Waterland@Sun.COM 		/* LINTED variable format specifier to vsnprintf() */
1109781SMoriah.Waterland@Sun.COM 		(void) vsnprintf(pt, ptln, fmt, ap);
1119781SMoriah.Waterland@Sun.COM 		va_end(ap);
1129781SMoriah.Waterland@Sun.COM 	}
1139781SMoriah.Waterland@Sun.COM }
1149781SMoriah.Waterland@Sun.COM 
1159781SMoriah.Waterland@Sun.COM /*
1169781SMoriah.Waterland@Sun.COM  * Name:	cverify
1179781SMoriah.Waterland@Sun.COM  * Description:	This function verifies and (if fix > 0) fixes the contents
1189781SMoriah.Waterland@Sun.COM  *		of the file at the path provided
1199781SMoriah.Waterland@Sun.COM  * Arguments:	fix - 0 - do not fix entries, 1 - fix entries
1209781SMoriah.Waterland@Sun.COM  *		ftype - single character "type" the entry is supposed to be
1219781SMoriah.Waterland@Sun.COM  *		path - path to file
1229781SMoriah.Waterland@Sun.COM  *		cinfo - content info structure representing the contents
1239781SMoriah.Waterland@Sun.COM  *			the entry is supposed to contain
1249781SMoriah.Waterland@Sun.COM  *		allow_checksum - determine if checksumming should be disabled:
1259781SMoriah.Waterland@Sun.COM  *		 == 0 - do not perform checksum ever - override enable_checksum.
1269781SMoriah.Waterland@Sun.COM  *		 != 0 - use the default checksum flag "enable_checksum" to
1279781SMoriah.Waterland@Sun.COM  *			determine if checksumming should be done.
1289781SMoriah.Waterland@Sun.COM  * NOTE:	modification and creation times can be repaired; the contents
1299781SMoriah.Waterland@Sun.COM  *		of the file cannot be corrected if the checksum indicates that
1309781SMoriah.Waterland@Sun.COM  *		the contents are not correct - VE_CONT will be returned in this
1319781SMoriah.Waterland@Sun.COM  *		case.
1329781SMoriah.Waterland@Sun.COM  * Possible return values:
1339781SMoriah.Waterland@Sun.COM  * - 0 = successful
1349781SMoriah.Waterland@Sun.COM  * - VE_EXIST = path name does not exist
1359781SMoriah.Waterland@Sun.COM  * - VE_FTYPE = path file type is not recognized, is not supported,
1369781SMoriah.Waterland@Sun.COM  *		or is not what was expected
1379781SMoriah.Waterland@Sun.COM  * - VE_ATTR = path mode/group/user is not what was expected
1389781SMoriah.Waterland@Sun.COM  * - VE_CONT = mod time/link target/major/minor/size/file system type/current
1399781SMoriah.Waterland@Sun.COM  *		directory is not what was expected
1409781SMoriah.Waterland@Sun.COM  * - VE_FAIL = utime/target directory/link/stat/symlink/mknod/chmod/statvfs/
1419781SMoriah.Waterland@Sun.COM  *		chown failed
1429781SMoriah.Waterland@Sun.COM  */
1439781SMoriah.Waterland@Sun.COM 
1449781SMoriah.Waterland@Sun.COM int
cverify(int fix,char * ftype,char * path,struct cinfo * cinfo,int allow_checksum)1459781SMoriah.Waterland@Sun.COM cverify(int fix, char *ftype, char *path, struct cinfo *cinfo,
1469781SMoriah.Waterland@Sun.COM 	int allow_checksum)
1479781SMoriah.Waterland@Sun.COM {
1489781SMoriah.Waterland@Sun.COM 	struct stat	status; 	/* file status buffer */
1499781SMoriah.Waterland@Sun.COM 	struct utimbuf	times;
1509781SMoriah.Waterland@Sun.COM 	unsigned long	mycksum;
1519781SMoriah.Waterland@Sun.COM 	int		setval, retcode;
1529781SMoriah.Waterland@Sun.COM 	char		tbuf1[512];
1539781SMoriah.Waterland@Sun.COM 	char		tbuf2[512];
1549781SMoriah.Waterland@Sun.COM 	int		cksumerr;
1559781SMoriah.Waterland@Sun.COM 
1569781SMoriah.Waterland@Sun.COM 	setval = (*ftype == '?');
1579781SMoriah.Waterland@Sun.COM 	retcode = 0;
1589781SMoriah.Waterland@Sun.COM 	reperr(NULL);
1599781SMoriah.Waterland@Sun.COM 
1609781SMoriah.Waterland@Sun.COM 	if (stat(path, &status) < 0) {
1619781SMoriah.Waterland@Sun.COM 		reperr(pkg_gt(ERR_EXIST));
1629781SMoriah.Waterland@Sun.COM 		return (VE_EXIST);
1639781SMoriah.Waterland@Sun.COM 	}
1649781SMoriah.Waterland@Sun.COM 
1659781SMoriah.Waterland@Sun.COM 	/* -1	requires modtimes to be the same */
1669781SMoriah.Waterland@Sun.COM 	/*  0   reports modtime failure */
1679781SMoriah.Waterland@Sun.COM 	/*  1   fixes modtimes */
1689781SMoriah.Waterland@Sun.COM 
1699781SMoriah.Waterland@Sun.COM 	if (setval || (cinfo->modtime == BADCONT)) {
1709781SMoriah.Waterland@Sun.COM 		cinfo->modtime = status.st_mtime;
1719781SMoriah.Waterland@Sun.COM 	} else if (status.st_mtime != cinfo->modtime) {
1729781SMoriah.Waterland@Sun.COM 		if (fix > 0) {
1739781SMoriah.Waterland@Sun.COM 			/* reset times on the file */
1749781SMoriah.Waterland@Sun.COM 			times.actime = cinfo->modtime;
1759781SMoriah.Waterland@Sun.COM 			times.modtime = cinfo->modtime;
1769781SMoriah.Waterland@Sun.COM 			if (utime(path, &times)) {
1779781SMoriah.Waterland@Sun.COM 				reperr(pkg_gt(ERR_MODFAIL));
1789781SMoriah.Waterland@Sun.COM 				retcode = VE_FAIL;
1799781SMoriah.Waterland@Sun.COM 			}
1809781SMoriah.Waterland@Sun.COM 		} else if (fix < 0) {
1819781SMoriah.Waterland@Sun.COM 			/* modtimes must be the same */
1829781SMoriah.Waterland@Sun.COM 			if (strftime(tbuf1, sizeof (tbuf1), DATEFMT,
1839781SMoriah.Waterland@Sun.COM 				localtime(&cinfo->modtime)) == 0) {
1849781SMoriah.Waterland@Sun.COM 				reperr(pkg_gt(ERR_MEM));
1859781SMoriah.Waterland@Sun.COM 			}
1869781SMoriah.Waterland@Sun.COM 			if (strftime(tbuf2, sizeof (tbuf2), DATEFMT,
1879781SMoriah.Waterland@Sun.COM 				localtime(&status.st_mtime)) == 0) {
1889781SMoriah.Waterland@Sun.COM 				reperr(pkg_gt(ERR_MEM));
1899781SMoriah.Waterland@Sun.COM 			}
1909781SMoriah.Waterland@Sun.COM 			reperr(pkg_gt(ERR_MTIME), tbuf1, tbuf2);
1919781SMoriah.Waterland@Sun.COM 			retcode = VE_CONT;
1929781SMoriah.Waterland@Sun.COM 		}
1939781SMoriah.Waterland@Sun.COM 	}
1949781SMoriah.Waterland@Sun.COM 
1959781SMoriah.Waterland@Sun.COM 	if (setval || (cinfo->size == (fsblkcnt_t)BADCONT)) {
1969781SMoriah.Waterland@Sun.COM 		cinfo->size = status.st_size;
1979781SMoriah.Waterland@Sun.COM 	} else if (status.st_size != cinfo->size) {
1989781SMoriah.Waterland@Sun.COM 		if (!retcode) {
1999781SMoriah.Waterland@Sun.COM 			retcode = VE_CONT;
2009781SMoriah.Waterland@Sun.COM 		}
2019781SMoriah.Waterland@Sun.COM 		reperr(pkg_gt(ERR_SIZE), cinfo->size, status.st_size);
2029781SMoriah.Waterland@Sun.COM 	}
2039781SMoriah.Waterland@Sun.COM 
2049781SMoriah.Waterland@Sun.COM 	cksumerr = 0;
2059781SMoriah.Waterland@Sun.COM 
2069781SMoriah.Waterland@Sun.COM 	/*
2079781SMoriah.Waterland@Sun.COM 	 * see if checksumming should be done: if checksumming is allowed,
2089781SMoriah.Waterland@Sun.COM 	 * and checksumming is enabled, then checksum the file.
2099781SMoriah.Waterland@Sun.COM 	 */
2109781SMoriah.Waterland@Sun.COM 
2119781SMoriah.Waterland@Sun.COM 	/* return if no need to compute checksum */
2129781SMoriah.Waterland@Sun.COM 
2139781SMoriah.Waterland@Sun.COM 	if ((allow_checksum == 0) || (enable_checksum == 0)) {
2149781SMoriah.Waterland@Sun.COM 		return (retcode);
2159781SMoriah.Waterland@Sun.COM 	}
2169781SMoriah.Waterland@Sun.COM 
2179781SMoriah.Waterland@Sun.COM 	/* compute checksum */
2189781SMoriah.Waterland@Sun.COM 
2199781SMoriah.Waterland@Sun.COM 	mycksum = compute_checksum(&cksumerr, path);
2209781SMoriah.Waterland@Sun.COM 
2219781SMoriah.Waterland@Sun.COM 	/* set value if not set or if checksum cannot be computed */
2229781SMoriah.Waterland@Sun.COM 
2239781SMoriah.Waterland@Sun.COM 	if (setval || (cinfo->cksum == BADCONT)) {
2249781SMoriah.Waterland@Sun.COM 		cinfo->cksum = mycksum;
2259781SMoriah.Waterland@Sun.COM 		return (retcode);
2269781SMoriah.Waterland@Sun.COM 	}
2279781SMoriah.Waterland@Sun.COM 
2289781SMoriah.Waterland@Sun.COM 	/* report / return error if checksums mismatch or there is an error */
2299781SMoriah.Waterland@Sun.COM 
2309781SMoriah.Waterland@Sun.COM 	if ((mycksum != cinfo->cksum) || cksumerr) {
2319781SMoriah.Waterland@Sun.COM 		if (!retcode) {
2329781SMoriah.Waterland@Sun.COM 			retcode = VE_CONT;
2339781SMoriah.Waterland@Sun.COM 		}
2349781SMoriah.Waterland@Sun.COM 		if (!cksumerr) {
2359781SMoriah.Waterland@Sun.COM 			reperr(pkg_gt(ERR_CKSUM), cinfo->cksum, mycksum);
2369781SMoriah.Waterland@Sun.COM 		}
2379781SMoriah.Waterland@Sun.COM 	}
2389781SMoriah.Waterland@Sun.COM 
2399781SMoriah.Waterland@Sun.COM 	return (retcode);
2409781SMoriah.Waterland@Sun.COM }
2419781SMoriah.Waterland@Sun.COM 
2429781SMoriah.Waterland@Sun.COM /*
2439781SMoriah.Waterland@Sun.COM  * Name:	compute_checksum
2449781SMoriah.Waterland@Sun.COM  * Description:	generate checksum for specified file
2459781SMoriah.Waterland@Sun.COM  * Arguments:	r_cksumerr (int *) [RO, *RW]
2469781SMoriah.Waterland@Sun.COM  *			- pointer to integer that is set on return to:
2479781SMoriah.Waterland@Sun.COM  *				== 0 - no error occurred
2489781SMoriah.Waterland@Sun.COM  *				!= 0 - error occurred
2499781SMoriah.Waterland@Sun.COM  *		a_path (char *) [RO, *RO]
2509781SMoriah.Waterland@Sun.COM  *			- pointer to string representing path to file to
2519781SMoriah.Waterland@Sun.COM  *			  generate checksum of
2529781SMoriah.Waterland@Sun.COM  * Returns:	unsigned long - results:
2539781SMoriah.Waterland@Sun.COM  *			- If *r_cksumerr == 0, checksum of specified file
2549781SMoriah.Waterland@Sun.COM  *			- If *r_cksumerr != 0, undefined
2559781SMoriah.Waterland@Sun.COM  */
2569781SMoriah.Waterland@Sun.COM unsigned long
compute_checksum(int * r_cksumerr,char * a_path)2579781SMoriah.Waterland@Sun.COM compute_checksum(int *r_cksumerr, char *a_path)
2589781SMoriah.Waterland@Sun.COM {
2599781SMoriah.Waterland@Sun.COM 	CHECKSUM_T	suma;	/* to split four-bytes into 2 two-byte values */
2609781SMoriah.Waterland@Sun.COM 	CHECKSUM_T	tempa;
2619781SMoriah.Waterland@Sun.COM 	int		fd;
2629781SMoriah.Waterland@Sun.COM 	uint32_t	lg;	/* running checksum value */
2639781SMoriah.Waterland@Sun.COM 	uint32_t	buf[CHUNK/4]; /* to read CHUNK bytes */
2649781SMoriah.Waterland@Sun.COM 	uint32_t	lsavhi;	/* high order two-bytes of four-byte checksum */
2659781SMoriah.Waterland@Sun.COM 	uint32_t	lsavlo;	/* low order two-bytes of four-byte checksum */
2669781SMoriah.Waterland@Sun.COM 	int		leap = sizeof (uint32_t);
2679781SMoriah.Waterland@Sun.COM 	int		notyet = 0;
2689781SMoriah.Waterland@Sun.COM 	int		nread;
2699781SMoriah.Waterland@Sun.COM 	struct stat64	sbuf;
2709781SMoriah.Waterland@Sun.COM 
2719781SMoriah.Waterland@Sun.COM 	/* reset error flag */
2729781SMoriah.Waterland@Sun.COM 	*r_cksumerr = 0;
2739781SMoriah.Waterland@Sun.COM 
2749781SMoriah.Waterland@Sun.COM 	/* open file and obtain -> where file is mapped/read */
2759781SMoriah.Waterland@Sun.COM 	if ((fd = open(a_path, O_RDONLY)) < 0) {
2769781SMoriah.Waterland@Sun.COM 		*r_cksumerr = 1;
2779781SMoriah.Waterland@Sun.COM 		reperr(pkg_gt(ERR_NO_CKSUM));
2789781SMoriah.Waterland@Sun.COM 		perror(ERR_NO_CKSUM);
2799781SMoriah.Waterland@Sun.COM 		return (0);
2809781SMoriah.Waterland@Sun.COM 	}
2819781SMoriah.Waterland@Sun.COM 
2829781SMoriah.Waterland@Sun.COM 	if (fstat64(fd, &sbuf) != 0) {
2839781SMoriah.Waterland@Sun.COM 		*r_cksumerr = 1;
2849781SMoriah.Waterland@Sun.COM 		reperr(pkg_gt(ERR_NO_CKSUM));
2859781SMoriah.Waterland@Sun.COM 		perror(ERR_NO_CKSUM);
2869781SMoriah.Waterland@Sun.COM 		return (0);
2879781SMoriah.Waterland@Sun.COM 	}
2889781SMoriah.Waterland@Sun.COM 
2899781SMoriah.Waterland@Sun.COM 	/* initialize checksum value */
2909781SMoriah.Waterland@Sun.COM 	lg = 0;
2919781SMoriah.Waterland@Sun.COM 
2929781SMoriah.Waterland@Sun.COM 	/*
2939781SMoriah.Waterland@Sun.COM 	 * Read CHUNK bytes off the file at a time; Read size of long bytes
2949781SMoriah.Waterland@Sun.COM 	 * from memory at a time and process them.
2959781SMoriah.Waterland@Sun.COM 	 * If last read, then read remnant bytes and process individually.
2969781SMoriah.Waterland@Sun.COM 	 */
2979781SMoriah.Waterland@Sun.COM 	errno = 0;
2989781SMoriah.Waterland@Sun.COM 	while ((nread = read(fd, (void*)buf,
2999781SMoriah.Waterland@Sun.COM 		    (sbuf.st_size < CHUNK) ? sbuf.st_size : CHUNK)) > 0) {
3009781SMoriah.Waterland@Sun.COM 		uchar_t *s;
3019781SMoriah.Waterland@Sun.COM 		uint32_t *p = buf;
3029781SMoriah.Waterland@Sun.COM 
3039781SMoriah.Waterland@Sun.COM 		notyet = nread % leap;
3049781SMoriah.Waterland@Sun.COM 		nread -= notyet;
3059781SMoriah.Waterland@Sun.COM 
3069781SMoriah.Waterland@Sun.COM 		for (; nread > 0; nread -= leap) {
3079781SMoriah.Waterland@Sun.COM 			lg += ((((*p)>>24)&0xFF) & WDMSK);
3089781SMoriah.Waterland@Sun.COM 			lg += ((((*p)>>16)&0xFF) & WDMSK);
3099781SMoriah.Waterland@Sun.COM 			lg += ((((*p)>>8)&0xFF) & WDMSK);
3109781SMoriah.Waterland@Sun.COM 			lg += (((*p)&0xFF) & WDMSK);
3119781SMoriah.Waterland@Sun.COM 			p++;
3129781SMoriah.Waterland@Sun.COM 		}
3139781SMoriah.Waterland@Sun.COM 		s = (uchar_t *)p;
3149781SMoriah.Waterland@Sun.COM 		/* leftover bytes less than four in number */
3159781SMoriah.Waterland@Sun.COM 		while (notyet--)
3169781SMoriah.Waterland@Sun.COM 			lg += (((uint32_t)(*s++)) & WDMSK);
3179781SMoriah.Waterland@Sun.COM 	}
3189781SMoriah.Waterland@Sun.COM 
3199781SMoriah.Waterland@Sun.COM 	/* wind up */
3209781SMoriah.Waterland@Sun.COM 	(void) close(fd);
3219781SMoriah.Waterland@Sun.COM 
3229781SMoriah.Waterland@Sun.COM 	/* compute checksum components */
3239781SMoriah.Waterland@Sun.COM 	suma.lg = lg;
3249781SMoriah.Waterland@Sun.COM 	tempa.lg = (suma.hl.lo & WDMSK) + (suma.hl.hi & WDMSK);
3259781SMoriah.Waterland@Sun.COM 	lsavhi = (uint32_t)tempa.hl.hi;
3269781SMoriah.Waterland@Sun.COM 	lsavlo = (uint32_t)tempa.hl.lo;
3279781SMoriah.Waterland@Sun.COM 
3289781SMoriah.Waterland@Sun.COM 	/* return final checksum value */
3299781SMoriah.Waterland@Sun.COM 	return (lsavhi+lsavlo);
3309781SMoriah.Waterland@Sun.COM }
3319781SMoriah.Waterland@Sun.COM 
3329781SMoriah.Waterland@Sun.COM static 	struct stat	status; 	/* file status buffer */
3339781SMoriah.Waterland@Sun.COM static  struct statvfs	vfsstatus;	/* filesystem status buffer */
3349781SMoriah.Waterland@Sun.COM 
3359781SMoriah.Waterland@Sun.COM /*
3369781SMoriah.Waterland@Sun.COM  * Remove the thing that's currently in place so we can put down the package
3379781SMoriah.Waterland@Sun.COM  * object. If we're replacing a directory with a directory, leave it alone.
3389781SMoriah.Waterland@Sun.COM  * Returns 1 if all OK and 0 if failed.
3399781SMoriah.Waterland@Sun.COM  */
3409781SMoriah.Waterland@Sun.COM static int
clear_target(char * path,char * ftype,int is_a_dir)3419781SMoriah.Waterland@Sun.COM clear_target(char *path, char *ftype, int is_a_dir)
3429781SMoriah.Waterland@Sun.COM {
3439781SMoriah.Waterland@Sun.COM 	int retcode = 1;
3449781SMoriah.Waterland@Sun.COM 
3459781SMoriah.Waterland@Sun.COM 	if (is_a_dir) {	/* if there's a directory there already ... */
3469781SMoriah.Waterland@Sun.COM 		/* ... and this isn't, ... */
3479781SMoriah.Waterland@Sun.COM 		if ((*ftype != 'd') && (*ftype != 'x')) {
3489781SMoriah.Waterland@Sun.COM 			if (rmdir(path)) {	/* try to remove it. */
3499781SMoriah.Waterland@Sun.COM 				reperr(pkg_gt(ERR_RMDIR), path);
3509781SMoriah.Waterland@Sun.COM 				retcode = 0;
3519781SMoriah.Waterland@Sun.COM 			}
3529781SMoriah.Waterland@Sun.COM 		}
3539781SMoriah.Waterland@Sun.COM 	} else {
3549781SMoriah.Waterland@Sun.COM 		if (remove(path)) {
3559781SMoriah.Waterland@Sun.COM 			if (errno != ENOENT) {
3569781SMoriah.Waterland@Sun.COM 				retcode = 0;	/* It didn't work. */
3579781SMoriah.Waterland@Sun.COM 			}
3589781SMoriah.Waterland@Sun.COM 		}
3599781SMoriah.Waterland@Sun.COM 	}
3609781SMoriah.Waterland@Sun.COM 
3619781SMoriah.Waterland@Sun.COM 	return (retcode);
3629781SMoriah.Waterland@Sun.COM }
3639781SMoriah.Waterland@Sun.COM 
3649781SMoriah.Waterland@Sun.COM /*
3659781SMoriah.Waterland@Sun.COM  * Name:	averify
3669781SMoriah.Waterland@Sun.COM  * Description:	This function verifies and (if fix > 0) fixes the attributes
3679781SMoriah.Waterland@Sun.COM  *		of the file at the path provided.
3689781SMoriah.Waterland@Sun.COM  * Arguments:	fix - 0 - do not fix entries, 1 - fix entries
3699781SMoriah.Waterland@Sun.COM  *		ftype - single character "type" the entry is supposed to be
3709781SMoriah.Waterland@Sun.COM  *		path - path to file
3719781SMoriah.Waterland@Sun.COM  *		ainfo - attribute info structure representing the attributes
3729781SMoriah.Waterland@Sun.COM  *			the entry is supposed to be
3739781SMoriah.Waterland@Sun.COM  * NOTE:	attributes are links and permissions
3749781SMoriah.Waterland@Sun.COM  * Possible return values:
3759781SMoriah.Waterland@Sun.COM  * - 0 = successful
3769781SMoriah.Waterland@Sun.COM  * - VE_EXIST = path name does not exist
3779781SMoriah.Waterland@Sun.COM  * - VE_FTYPE = path file type is not recognized, is not supported,
3789781SMoriah.Waterland@Sun.COM  *		or is not what was expected
3799781SMoriah.Waterland@Sun.COM  * - VE_ATTR = path mode/group/user is not what was expected
3809781SMoriah.Waterland@Sun.COM  * - VE_CONT = mod time/link target/major/minor/size/file system type/current
3819781SMoriah.Waterland@Sun.COM  *		directory is not what was expected
3829781SMoriah.Waterland@Sun.COM  * - VE_FAIL = utime/target directory/link/stat/symlink/mknod/chmod/statvfs/
3839781SMoriah.Waterland@Sun.COM  *		chown failed
3849781SMoriah.Waterland@Sun.COM  */
3859781SMoriah.Waterland@Sun.COM int
averify(int fix,char * ftype,char * path,struct ainfo * ainfo)3869781SMoriah.Waterland@Sun.COM averify(int fix, char *ftype, char *path, struct ainfo *ainfo)
3879781SMoriah.Waterland@Sun.COM {
3889781SMoriah.Waterland@Sun.COM 	struct group	*grp; 	/* group entry buffer */
3899781SMoriah.Waterland@Sun.COM 	struct passwd	*pwd;
3909781SMoriah.Waterland@Sun.COM 	int		n;
3919781SMoriah.Waterland@Sun.COM 	int		setval;
3929781SMoriah.Waterland@Sun.COM 	int		uid, gid;
3939781SMoriah.Waterland@Sun.COM 	int		dochown;
3949781SMoriah.Waterland@Sun.COM 	int		retcode;
395*10176Sok199659 	int		statError = 0;
3969781SMoriah.Waterland@Sun.COM 	int		targ_is_dir = 0;	/* replacing a directory */
3979781SMoriah.Waterland@Sun.COM 	char		myftype;
3989781SMoriah.Waterland@Sun.COM 	char		buf[PATH_MAX];
3999781SMoriah.Waterland@Sun.COM 	ino_t		my_ino;
4009781SMoriah.Waterland@Sun.COM 	dev_t		my_dev;
4019781SMoriah.Waterland@Sun.COM 	char 		cwd[MAXPATHLEN];
4029781SMoriah.Waterland@Sun.COM 	char 		*cd;
4039781SMoriah.Waterland@Sun.COM 	char 		*c;
4049781SMoriah.Waterland@Sun.COM 
4059781SMoriah.Waterland@Sun.COM 	setval = (*ftype == '?');
4069781SMoriah.Waterland@Sun.COM 	retcode = 0;
4079781SMoriah.Waterland@Sun.COM 	reperr(NULL);
4089781SMoriah.Waterland@Sun.COM 
4099781SMoriah.Waterland@Sun.COM 	if (get_disable_attribute_check()) {
4109781SMoriah.Waterland@Sun.COM 		return (0);
4119781SMoriah.Waterland@Sun.COM 	}
4129781SMoriah.Waterland@Sun.COM 
4139781SMoriah.Waterland@Sun.COM 	if (*ftype == 'l') {
4149781SMoriah.Waterland@Sun.COM 		if (stat(path, &status) < 0) {
4159781SMoriah.Waterland@Sun.COM 			retcode = VE_EXIST;
4169781SMoriah.Waterland@Sun.COM 			reperr(pkg_gt(ERR_EXIST));
4179781SMoriah.Waterland@Sun.COM 		}
4189781SMoriah.Waterland@Sun.COM 
4199781SMoriah.Waterland@Sun.COM 		my_ino = status.st_ino;
4209781SMoriah.Waterland@Sun.COM 		my_dev = status.st_dev;
4219781SMoriah.Waterland@Sun.COM 
4229781SMoriah.Waterland@Sun.COM 		/* Get copy of the current working directory */
4239781SMoriah.Waterland@Sun.COM 		if (getcwd(cwd, MAXPATHLEN) == NULL) {
4249781SMoriah.Waterland@Sun.COM 			reperr(pkg_gt(ERR_GETWD), ainfo->local);
4259781SMoriah.Waterland@Sun.COM 			return (VE_FAIL);
4269781SMoriah.Waterland@Sun.COM 		}
4279781SMoriah.Waterland@Sun.COM 
4289781SMoriah.Waterland@Sun.COM 		/*
4299781SMoriah.Waterland@Sun.COM 		 * Change to the directory in which the hard
4309781SMoriah.Waterland@Sun.COM 		 * link is to be created.
4319781SMoriah.Waterland@Sun.COM 		 */
4329781SMoriah.Waterland@Sun.COM 		cd = strdup(path);
4339781SMoriah.Waterland@Sun.COM 		c = strrchr(cd, '/');
4349781SMoriah.Waterland@Sun.COM 		if (c) {
4359781SMoriah.Waterland@Sun.COM 			/* bugid 4247895 */
4369781SMoriah.Waterland@Sun.COM 			if (strcmp(cd, c) == 0)
4379781SMoriah.Waterland@Sun.COM 				strcpy(cd, "/");
4389781SMoriah.Waterland@Sun.COM 			else
4399781SMoriah.Waterland@Sun.COM 				*c = NULL;
4409781SMoriah.Waterland@Sun.COM 
4419781SMoriah.Waterland@Sun.COM 			if (chdir(cd) != 0) {
4429781SMoriah.Waterland@Sun.COM 				reperr(pkg_gt(ERR_CHDIR), cd);
4439781SMoriah.Waterland@Sun.COM 				return (VE_FAIL);
4449781SMoriah.Waterland@Sun.COM 			}
4459781SMoriah.Waterland@Sun.COM 		}
4469781SMoriah.Waterland@Sun.COM 		free(cd);
4479781SMoriah.Waterland@Sun.COM 
4489781SMoriah.Waterland@Sun.COM 		if (retcode || (status.st_nlink < 2) ||
4499781SMoriah.Waterland@Sun.COM 		    (stat(ainfo->local, &status) < 0) ||
4509781SMoriah.Waterland@Sun.COM 		    (my_dev != status.st_dev) || (my_ino != status.st_ino)) {
4519781SMoriah.Waterland@Sun.COM 			if (fix) {
4529781SMoriah.Waterland@Sun.COM 				/*
4539781SMoriah.Waterland@Sun.COM 				 * Don't want to do a hard link to a
4549781SMoriah.Waterland@Sun.COM 				 * directory.
4559781SMoriah.Waterland@Sun.COM 				 */
4569781SMoriah.Waterland@Sun.COM 				if (!isdir(ainfo->local)) {
4579781SMoriah.Waterland@Sun.COM 					chdir(cwd);
4589781SMoriah.Waterland@Sun.COM 					reperr(pkg_gt(ERR_LINKISDIR),
4599781SMoriah.Waterland@Sun.COM 					    ainfo->local);
4609781SMoriah.Waterland@Sun.COM 					return (VE_FAIL);
4619781SMoriah.Waterland@Sun.COM 				}
4629781SMoriah.Waterland@Sun.COM 				/* Now do the link. */
4639781SMoriah.Waterland@Sun.COM 				if (!clear_target(path, ftype, targ_is_dir))
4649781SMoriah.Waterland@Sun.COM 					return (VE_FAIL);
4659781SMoriah.Waterland@Sun.COM 
4669781SMoriah.Waterland@Sun.COM 				if (link(ainfo->local, path)) {
4679781SMoriah.Waterland@Sun.COM 					chdir(cwd);
4689781SMoriah.Waterland@Sun.COM 					reperr(pkg_gt(ERR_LINKFAIL),
4699781SMoriah.Waterland@Sun.COM 					    ainfo->local);
4709781SMoriah.Waterland@Sun.COM 					return (VE_FAIL);
4719781SMoriah.Waterland@Sun.COM 				}
4729781SMoriah.Waterland@Sun.COM 				retcode = 0;
4739781SMoriah.Waterland@Sun.COM 			} else {
4749781SMoriah.Waterland@Sun.COM 				/* Go back to previous working directory */
4759781SMoriah.Waterland@Sun.COM 				if (chdir(cwd) != 0)
4769781SMoriah.Waterland@Sun.COM 					reperr(pkg_gt(ERR_CHDIR), cwd);
4779781SMoriah.Waterland@Sun.COM 
4789781SMoriah.Waterland@Sun.COM 				reperr(pkg_gt(ERR_LINK), ainfo->local);
4799781SMoriah.Waterland@Sun.COM 				return (VE_CONT);
4809781SMoriah.Waterland@Sun.COM 			}
4819781SMoriah.Waterland@Sun.COM 		}
4829781SMoriah.Waterland@Sun.COM 
4839781SMoriah.Waterland@Sun.COM 		/* Go back to previous working directory */
4849781SMoriah.Waterland@Sun.COM 		if (chdir(cwd) != 0) {
4859781SMoriah.Waterland@Sun.COM 			reperr(pkg_gt(ERR_CHDIR), cwd);
4869781SMoriah.Waterland@Sun.COM 			return (VE_CONT);
4879781SMoriah.Waterland@Sun.COM 		}
4889781SMoriah.Waterland@Sun.COM 
4899781SMoriah.Waterland@Sun.COM 		return (retcode);
4909781SMoriah.Waterland@Sun.COM 	}
4919781SMoriah.Waterland@Sun.COM 
4929781SMoriah.Waterland@Sun.COM 	retcode = 0;
4939781SMoriah.Waterland@Sun.COM 
494*10176Sok199659 	/* If we are to process symlinks the old way then we follow the link */
495*10176Sok199659 	if (nonABI_symlinks()) {
496*10176Sok199659 		if ((*ftype == 's') ? lstat(path, &status) :
497*10176Sok199659 			stat(path, &status)) {
498*10176Sok199659 			reperr(pkg_gt(ERR_EXIST));
499*10176Sok199659 			retcode = VE_EXIST;
500*10176Sok199659 			myftype = '?';
501*10176Sok199659 			statError++;
502*10176Sok199659 		}
503*10176Sok199659 	/* If not then we inspect the target of the link */
504*10176Sok199659 	} else {
505*10176Sok199659 		if ((n = lstat(path, &status)) == -1) {
506*10176Sok199659 			reperr(pkg_gt(ERR_EXIST));
507*10176Sok199659 			retcode = VE_EXIST;
508*10176Sok199659 			myftype = '?';
509*10176Sok199659 			statError++;
510*10176Sok199659 		}
511*10176Sok199659 	}
512*10176Sok199659 	if (!statError) {
513*10176Sok199659 		/* determining actual type of existing object */
514*10176Sok199659 		switch (status.st_mode & S_IFMT) {
515*10176Sok199659 		    case S_IFLNK:
516*10176Sok199659 			myftype = 's';
517*10176Sok199659 			break;
5189781SMoriah.Waterland@Sun.COM 
519*10176Sok199659 		    case S_IFIFO:
520*10176Sok199659 			myftype = 'p';
521*10176Sok199659 			break;
522*10176Sok199659 
523*10176Sok199659 		    case S_IFCHR:
524*10176Sok199659 			myftype = 'c';
525*10176Sok199659 			break;
526*10176Sok199659 
527*10176Sok199659 		    case S_IFDIR:
528*10176Sok199659 			myftype = 'd';
529*10176Sok199659 			targ_is_dir = 1;
530*10176Sok199659 			break;
5319781SMoriah.Waterland@Sun.COM 
532*10176Sok199659 		    case S_IFBLK:
533*10176Sok199659 			myftype = 'b';
534*10176Sok199659 			break;
535*10176Sok199659 
536*10176Sok199659 		    case S_IFREG:
537*10176Sok199659 		    case 0:
538*10176Sok199659 			myftype = 'f';
539*10176Sok199659 			break;
540*10176Sok199659 
541*10176Sok199659 		    case S_IFDOOR:
542*10176Sok199659 			myftype = 'D';
543*10176Sok199659 			break;
544*10176Sok199659 
545*10176Sok199659 		    default:
546*10176Sok199659 			reperr(pkg_gt(ERR_UNKNOWN));
547*10176Sok199659 			return (VE_FTYPE);
548*10176Sok199659 		}
549*10176Sok199659 	}
5509781SMoriah.Waterland@Sun.COM 
5519781SMoriah.Waterland@Sun.COM 	if (setval) {
5529781SMoriah.Waterland@Sun.COM 		/*
5539781SMoriah.Waterland@Sun.COM 		 * Check to make sure that a package or an installf that uses
5549781SMoriah.Waterland@Sun.COM 		 * wild cards '?' to assume the ftype of an object on the
5559781SMoriah.Waterland@Sun.COM 		 * system is not assuming a door ftype. Doors are not supported
5569781SMoriah.Waterland@Sun.COM 		 * but should be ignored.
5579781SMoriah.Waterland@Sun.COM 		 */
5589781SMoriah.Waterland@Sun.COM 		if (myftype == 'D') {
5599781SMoriah.Waterland@Sun.COM 			reperr(pkg_gt(ERR_FTYPED), path);
5609781SMoriah.Waterland@Sun.COM 			retcode = VE_FTYPE;
5619781SMoriah.Waterland@Sun.COM 			return (VE_FTYPE);
5629781SMoriah.Waterland@Sun.COM 		} else {
5639781SMoriah.Waterland@Sun.COM 			*ftype = myftype;
5649781SMoriah.Waterland@Sun.COM 		}
5659781SMoriah.Waterland@Sun.COM 	} else if (!retcode && (*ftype != myftype) &&
5669781SMoriah.Waterland@Sun.COM 	    ((myftype != 'f') || !strchr("ilev", *ftype)) &&
5679781SMoriah.Waterland@Sun.COM 	    ((myftype != 'd') || (*ftype != 'x'))) {
5689781SMoriah.Waterland@Sun.COM 		reperr(pkg_gt(ERR_FTYPE), *ftype, myftype);
5699781SMoriah.Waterland@Sun.COM 		retcode = VE_FTYPE;
5709781SMoriah.Waterland@Sun.COM 	}
5719781SMoriah.Waterland@Sun.COM 
5729781SMoriah.Waterland@Sun.COM 	if (!retcode && (*ftype == 's')) {
5739781SMoriah.Waterland@Sun.COM 		/* make sure that symbolic link is correct */
5749781SMoriah.Waterland@Sun.COM 		n = readlink(path, buf, PATH_MAX);
5759781SMoriah.Waterland@Sun.COM 		if (n < 0) {
5769781SMoriah.Waterland@Sun.COM 			reperr(pkg_gt(ERR_SLINK), ainfo->local);
5779781SMoriah.Waterland@Sun.COM 			retcode = VE_CONT;
5789781SMoriah.Waterland@Sun.COM 		} else if (ainfo->local != NULL) {
5799781SMoriah.Waterland@Sun.COM 			buf[n] = '\0';
5809781SMoriah.Waterland@Sun.COM 			if (strcmp(buf, ainfo->local)) {
5819781SMoriah.Waterland@Sun.COM 				reperr(pkg_gt(ERR_SLINK), ainfo->local);
5829781SMoriah.Waterland@Sun.COM 				retcode = VE_CONT;
5839781SMoriah.Waterland@Sun.COM 			}
5849781SMoriah.Waterland@Sun.COM 		} else if (ainfo->local == NULL) {
5859781SMoriah.Waterland@Sun.COM 			/*
5869781SMoriah.Waterland@Sun.COM 			 * Since a sym link target exists, insert it
5879781SMoriah.Waterland@Sun.COM 			 * into the ainfo structure
5889781SMoriah.Waterland@Sun.COM 			 */
5899781SMoriah.Waterland@Sun.COM 			buf[n] = '\0';
5909781SMoriah.Waterland@Sun.COM 			ainfo->local = strdup(buf);
5919781SMoriah.Waterland@Sun.COM 		}
5929781SMoriah.Waterland@Sun.COM 	}
5939781SMoriah.Waterland@Sun.COM 
5949781SMoriah.Waterland@Sun.COM 	if (retcode) {
5959781SMoriah.Waterland@Sun.COM 		/* The path doesn't exist or is different than it should be. */
5969781SMoriah.Waterland@Sun.COM 		if (fix) {
5979781SMoriah.Waterland@Sun.COM 			/*
5989781SMoriah.Waterland@Sun.COM 			 * Clear the way for the write. If it won't clear,
5999781SMoriah.Waterland@Sun.COM 			 * there's nothing we can do.
6009781SMoriah.Waterland@Sun.COM 			 */
6019781SMoriah.Waterland@Sun.COM 			if (!clear_target(path, ftype, targ_is_dir))
6029781SMoriah.Waterland@Sun.COM 				return (VE_FAIL);
6039781SMoriah.Waterland@Sun.COM 
6049781SMoriah.Waterland@Sun.COM 			if ((*ftype == 'd') || (*ftype == 'x')) {
6059781SMoriah.Waterland@Sun.COM 				char	*pt, *p;
6069781SMoriah.Waterland@Sun.COM 
6079781SMoriah.Waterland@Sun.COM 				/* Try to make it the easy way */
6089781SMoriah.Waterland@Sun.COM 				if (mkdir(path, ainfo->mode)) {
6099781SMoriah.Waterland@Sun.COM 					/*
6109781SMoriah.Waterland@Sun.COM 					 * Failing that, walk through the
6119781SMoriah.Waterland@Sun.COM 					 * parent directories creating
6129781SMoriah.Waterland@Sun.COM 					 * whatever is needed.
6139781SMoriah.Waterland@Sun.COM 					 */
6149781SMoriah.Waterland@Sun.COM 					p = strdup(path);
6159781SMoriah.Waterland@Sun.COM 					pt = (*p == '/') ? p+1 : p;
6169781SMoriah.Waterland@Sun.COM 					do {
6179781SMoriah.Waterland@Sun.COM 						if (pt = strchr(pt, '/'))
6189781SMoriah.Waterland@Sun.COM 							*pt = '\0';
6199781SMoriah.Waterland@Sun.COM 						if (access(p, 0) &&
6209781SMoriah.Waterland@Sun.COM 						    mkdir(p, ainfo->mode))
6219781SMoriah.Waterland@Sun.COM 							break;
6229781SMoriah.Waterland@Sun.COM 						if (pt)
6239781SMoriah.Waterland@Sun.COM 							*pt++ = '/';
6249781SMoriah.Waterland@Sun.COM 					} while (pt);
6259781SMoriah.Waterland@Sun.COM 					free(p);
6269781SMoriah.Waterland@Sun.COM 				}
6279781SMoriah.Waterland@Sun.COM 				if (stat(path, &status) < 0) {
6289781SMoriah.Waterland@Sun.COM 					reperr(pkg_gt(ERR_DIRFAIL));
6299781SMoriah.Waterland@Sun.COM 					return (VE_FAIL);
6309781SMoriah.Waterland@Sun.COM 				}
6319781SMoriah.Waterland@Sun.COM 			} else if (*ftype == 's') {
6329781SMoriah.Waterland@Sun.COM 				if (symlink(ainfo->local, path)) {
6339781SMoriah.Waterland@Sun.COM 					reperr(pkg_gt(ERR_SLINKFAIL),
6349781SMoriah.Waterland@Sun.COM 					    ainfo->local);
6359781SMoriah.Waterland@Sun.COM 					return (VE_FAIL);
6369781SMoriah.Waterland@Sun.COM 				}
6379781SMoriah.Waterland@Sun.COM 
6389781SMoriah.Waterland@Sun.COM 			} else if (*ftype == 'c') {
6399781SMoriah.Waterland@Sun.COM 				int wilddevno = 0;
6409781SMoriah.Waterland@Sun.COM 				/*
6419781SMoriah.Waterland@Sun.COM 				 * The next three if's support 2.4 and older
6429781SMoriah.Waterland@Sun.COM 				 * packages that use "?" as device numbers.
6439781SMoriah.Waterland@Sun.COM 				 * This should be considered for removal by
6449781SMoriah.Waterland@Sun.COM 				 * release 2.7 or so.
6459781SMoriah.Waterland@Sun.COM 				 */
6469781SMoriah.Waterland@Sun.COM 				if (ainfo->major == BADMAJOR) {
6479781SMoriah.Waterland@Sun.COM 					ainfo->major = 0;
6489781SMoriah.Waterland@Sun.COM 					wilddevno = 1;
6499781SMoriah.Waterland@Sun.COM 				}
6509781SMoriah.Waterland@Sun.COM 
6519781SMoriah.Waterland@Sun.COM 				if (ainfo->minor == BADMINOR) {
6529781SMoriah.Waterland@Sun.COM 					ainfo->minor = 0;
6539781SMoriah.Waterland@Sun.COM 					wilddevno = 1;
6549781SMoriah.Waterland@Sun.COM 				}
6559781SMoriah.Waterland@Sun.COM 
6569781SMoriah.Waterland@Sun.COM 				if (wilddevno) {
6579781SMoriah.Waterland@Sun.COM 					wilddevno = 0;
6589781SMoriah.Waterland@Sun.COM 					logerr(MSG_WLDDEVNO, path,
6599781SMoriah.Waterland@Sun.COM 					    ainfo->major, ainfo->minor);
6609781SMoriah.Waterland@Sun.COM 				}
6619781SMoriah.Waterland@Sun.COM 
6629781SMoriah.Waterland@Sun.COM 				if (mknod(path, ainfo->mode | S_IFCHR,
6639781SMoriah.Waterland@Sun.COM #ifdef SUNOS41
6649781SMoriah.Waterland@Sun.COM 				    makedev(ainfo->xmajor, ainfo->xminor)) ||
6659781SMoriah.Waterland@Sun.COM #else
6669781SMoriah.Waterland@Sun.COM 				    makedev(ainfo->major, ainfo->minor)) ||
6679781SMoriah.Waterland@Sun.COM #endif
6689781SMoriah.Waterland@Sun.COM 				    (stat(path, &status) < 0)) {
6699781SMoriah.Waterland@Sun.COM 					reperr(pkg_gt(ERR_CDEVFAIL));
6709781SMoriah.Waterland@Sun.COM 					return (VE_FAIL);
6719781SMoriah.Waterland@Sun.COM 				}
6729781SMoriah.Waterland@Sun.COM 			} else if (*ftype == 'b') {
6739781SMoriah.Waterland@Sun.COM 				int wilddevno = 0;
6749781SMoriah.Waterland@Sun.COM 				/*
6759781SMoriah.Waterland@Sun.COM 				 * The next three if's support 2.4 and older
6769781SMoriah.Waterland@Sun.COM 				 * packages that use "?" as device numbers.
6779781SMoriah.Waterland@Sun.COM 				 * This should be considered for removal by
6789781SMoriah.Waterland@Sun.COM 				 * release 2.7 or so.
6799781SMoriah.Waterland@Sun.COM 				 */
6809781SMoriah.Waterland@Sun.COM 				if (ainfo->major == BADMAJOR) {
6819781SMoriah.Waterland@Sun.COM 					ainfo->major = 0;
6829781SMoriah.Waterland@Sun.COM 					wilddevno = 1;
6839781SMoriah.Waterland@Sun.COM 				}
6849781SMoriah.Waterland@Sun.COM 
6859781SMoriah.Waterland@Sun.COM 				if (ainfo->minor == BADMINOR) {
6869781SMoriah.Waterland@Sun.COM 					ainfo->minor = 0;
6879781SMoriah.Waterland@Sun.COM 					wilddevno = 1;
6889781SMoriah.Waterland@Sun.COM 				}
6899781SMoriah.Waterland@Sun.COM 
6909781SMoriah.Waterland@Sun.COM 				if (wilddevno) {
6919781SMoriah.Waterland@Sun.COM 					wilddevno = 0;
6929781SMoriah.Waterland@Sun.COM 					logerr(MSG_WLDDEVNO, path,
6939781SMoriah.Waterland@Sun.COM 					    ainfo->major, ainfo->minor);
6949781SMoriah.Waterland@Sun.COM 				}
6959781SMoriah.Waterland@Sun.COM 
6969781SMoriah.Waterland@Sun.COM 				if (mknod(path, ainfo->mode | S_IFBLK,
6979781SMoriah.Waterland@Sun.COM #ifdef SUNOS41
6989781SMoriah.Waterland@Sun.COM 				    makedev(ainfo->xmajor, ainfo->xminor)) ||
6999781SMoriah.Waterland@Sun.COM #else
7009781SMoriah.Waterland@Sun.COM 				    makedev(ainfo->major, ainfo->minor)) ||
7019781SMoriah.Waterland@Sun.COM #endif
7029781SMoriah.Waterland@Sun.COM 				    (stat(path, &status) < 0)) {
7039781SMoriah.Waterland@Sun.COM 					reperr(pkg_gt(ERR_BDEVFAIL));
7049781SMoriah.Waterland@Sun.COM 					return (VE_FAIL);
7059781SMoriah.Waterland@Sun.COM 				}
7069781SMoriah.Waterland@Sun.COM 			} else if (*ftype == 'p') {
7079781SMoriah.Waterland@Sun.COM 				if (mknod(path, ainfo->mode | S_IFIFO, NULL) ||
7089781SMoriah.Waterland@Sun.COM 				    (stat(path, &status) < 0)) {
7099781SMoriah.Waterland@Sun.COM 					reperr(pkg_gt(ERR_PIPEFAIL));
7109781SMoriah.Waterland@Sun.COM 					return (VE_FAIL);
7119781SMoriah.Waterland@Sun.COM 				}
7129781SMoriah.Waterland@Sun.COM 			} else
7139781SMoriah.Waterland@Sun.COM 				return (retcode);
7149781SMoriah.Waterland@Sun.COM 
7159781SMoriah.Waterland@Sun.COM 		} else
7169781SMoriah.Waterland@Sun.COM 			return (retcode);
7179781SMoriah.Waterland@Sun.COM 	}
7189781SMoriah.Waterland@Sun.COM 
7199781SMoriah.Waterland@Sun.COM 	if (*ftype == 's')
7209781SMoriah.Waterland@Sun.COM 		return (0); /* don't check anything else */
7219781SMoriah.Waterland@Sun.COM 	if (*ftype == 'i')
7229781SMoriah.Waterland@Sun.COM 		return (0); /* don't check anything else */
7239781SMoriah.Waterland@Sun.COM 
7249781SMoriah.Waterland@Sun.COM 	retcode = 0;
7259781SMoriah.Waterland@Sun.COM 	if ((myftype == 'c') || (myftype == 'b')) {
7269781SMoriah.Waterland@Sun.COM #ifdef SUNOS41
7279781SMoriah.Waterland@Sun.COM 		if (setval || (ainfo->xmajor < 0))
7289781SMoriah.Waterland@Sun.COM 			ainfo->xmajor = ((status.st_rdev>>8)&0377);
7299781SMoriah.Waterland@Sun.COM 		if (setval || (ainfo->xminor < 0))
7309781SMoriah.Waterland@Sun.COM 			ainfo->xminor = (status.st_rdev&0377);
7319781SMoriah.Waterland@Sun.COM 		/* check major & minor */
7329781SMoriah.Waterland@Sun.COM 		if (status.st_rdev != makedev(ainfo->xmajor, ainfo->xminor)) {
7339781SMoriah.Waterland@Sun.COM 			reperr(pkg_gt(ERR_MAJMIN), ainfo->xmajor,
7349781SMoriah.Waterland@Sun.COM 			    ainfo->xminor,
7359781SMoriah.Waterland@Sun.COM 				(status.st_rdev>>8)&0377, status.st_rdev&0377);
7369781SMoriah.Waterland@Sun.COM 			retcode = VE_CONT;
7379781SMoriah.Waterland@Sun.COM 		}
7389781SMoriah.Waterland@Sun.COM #else
7399781SMoriah.Waterland@Sun.COM 		if (setval || (ainfo->major == BADMAJOR))
7409781SMoriah.Waterland@Sun.COM 			ainfo->major = major(status.st_rdev);
7419781SMoriah.Waterland@Sun.COM 		if (setval || (ainfo->minor == BADMINOR))
7429781SMoriah.Waterland@Sun.COM 			ainfo->minor = minor(status.st_rdev);
7439781SMoriah.Waterland@Sun.COM 		/* check major & minor */
7449781SMoriah.Waterland@Sun.COM 		if (status.st_rdev != makedev(ainfo->major, ainfo->minor)) {
7459781SMoriah.Waterland@Sun.COM 			reperr(pkg_gt(ERR_MAJMIN), ainfo->major, ainfo->minor,
7469781SMoriah.Waterland@Sun.COM 			    major(status.st_rdev), minor(status.st_rdev));
7479781SMoriah.Waterland@Sun.COM 			retcode = VE_CONT;
7489781SMoriah.Waterland@Sun.COM 		}
7499781SMoriah.Waterland@Sun.COM #endif
7509781SMoriah.Waterland@Sun.COM 	}
7519781SMoriah.Waterland@Sun.COM 
7529781SMoriah.Waterland@Sun.COM 	/* compare specified mode w/ actual mode excluding sticky bit */
7539781SMoriah.Waterland@Sun.COM 	if (setval || (ainfo->mode == BADMODE) || (ainfo->mode == WILDCARD))
7549781SMoriah.Waterland@Sun.COM 		ainfo->mode = status.st_mode & 07777;
7559781SMoriah.Waterland@Sun.COM 	else if ((ainfo->mode & 06777) != (status.st_mode & 06777)) {
7569781SMoriah.Waterland@Sun.COM 		if (fix) {
7579781SMoriah.Waterland@Sun.COM 			if ((ainfo->mode == BADMODE) ||
7589781SMoriah.Waterland@Sun.COM 			    (chmod(path, ainfo->mode) < 0))
7599781SMoriah.Waterland@Sun.COM 				retcode = VE_FAIL;
7609781SMoriah.Waterland@Sun.COM 		} else {
7619781SMoriah.Waterland@Sun.COM 			reperr(pkg_gt(ERR_PERM), ainfo->mode,
7629781SMoriah.Waterland@Sun.COM 				status.st_mode & 07777);
7639781SMoriah.Waterland@Sun.COM 			if (!retcode)
7649781SMoriah.Waterland@Sun.COM 				retcode = VE_ATTR;
7659781SMoriah.Waterland@Sun.COM 		}
7669781SMoriah.Waterland@Sun.COM 	}
7679781SMoriah.Waterland@Sun.COM 
7689781SMoriah.Waterland@Sun.COM 	dochown = 0;
7699781SMoriah.Waterland@Sun.COM 
7709781SMoriah.Waterland@Sun.COM 	/* get group entry for specified group */
7719781SMoriah.Waterland@Sun.COM 	if (setval || strcmp(ainfo->group, BADGROUP) == 0) {
7729781SMoriah.Waterland@Sun.COM 		grp = cgrgid(status.st_gid);
7739781SMoriah.Waterland@Sun.COM 		if (grp)
7749781SMoriah.Waterland@Sun.COM 			(void) strcpy(ainfo->group, grp->gr_name);
7759781SMoriah.Waterland@Sun.COM 		else {
7769781SMoriah.Waterland@Sun.COM 			if (!retcode)
7779781SMoriah.Waterland@Sun.COM 				retcode = VE_ATTR;
7789781SMoriah.Waterland@Sun.COM 			reperr(pkg_gt(ERR_BADGRPID), status.st_gid);
7799781SMoriah.Waterland@Sun.COM 		}
7809781SMoriah.Waterland@Sun.COM 		gid = status.st_gid;
7819781SMoriah.Waterland@Sun.COM 	} else if ((grp = cgrnam(ainfo->group)) == NULL) {
7829781SMoriah.Waterland@Sun.COM 		reperr(pkg_gt(ERR_BADGRPNM), ainfo->group);
7839781SMoriah.Waterland@Sun.COM 		if (!retcode)
7849781SMoriah.Waterland@Sun.COM 			retcode = VE_ATTR;
7859781SMoriah.Waterland@Sun.COM 	} else if ((gid = grp->gr_gid) != status.st_gid) {
7869781SMoriah.Waterland@Sun.COM 		if (fix) {
7879781SMoriah.Waterland@Sun.COM 			/* save specified GID */
7889781SMoriah.Waterland@Sun.COM 			gid = grp->gr_gid;
7899781SMoriah.Waterland@Sun.COM 			dochown++;
7909781SMoriah.Waterland@Sun.COM 		} else {
7919781SMoriah.Waterland@Sun.COM 			if ((grp = cgrgid((int)status.st_gid)) ==
7929781SMoriah.Waterland@Sun.COM 			    (struct group *)NULL) {
7939781SMoriah.Waterland@Sun.COM 				reperr(pkg_gt(ERR_GROUP), ainfo->group,
7949781SMoriah.Waterland@Sun.COM 				    "(null)");
7959781SMoriah.Waterland@Sun.COM 			} else {
7969781SMoriah.Waterland@Sun.COM 				reperr(pkg_gt(ERR_GROUP), ainfo->group,
7979781SMoriah.Waterland@Sun.COM 				    grp->gr_name);
7989781SMoriah.Waterland@Sun.COM 			}
7999781SMoriah.Waterland@Sun.COM 			if (!retcode)
8009781SMoriah.Waterland@Sun.COM 				retcode = VE_ATTR;
8019781SMoriah.Waterland@Sun.COM 		}
8029781SMoriah.Waterland@Sun.COM 	}
8039781SMoriah.Waterland@Sun.COM 
8049781SMoriah.Waterland@Sun.COM 	/* get password entry for specified owner */
8059781SMoriah.Waterland@Sun.COM 	if (setval || strcmp(ainfo->owner, BADOWNER) == 0) {
8069781SMoriah.Waterland@Sun.COM 		pwd = cpwuid((int)status.st_uid);
8079781SMoriah.Waterland@Sun.COM 		if (pwd)
8089781SMoriah.Waterland@Sun.COM 			(void) strcpy(ainfo->owner, pwd->pw_name);
8099781SMoriah.Waterland@Sun.COM 		else {
8109781SMoriah.Waterland@Sun.COM 			if (!retcode)
8119781SMoriah.Waterland@Sun.COM 				retcode = VE_ATTR;
8129781SMoriah.Waterland@Sun.COM 			reperr(pkg_gt(ERR_BADUSRID), status.st_uid);
8139781SMoriah.Waterland@Sun.COM 		}
8149781SMoriah.Waterland@Sun.COM 		uid = status.st_uid;
8159781SMoriah.Waterland@Sun.COM 	} else if ((pwd = cpwnam(ainfo->owner)) == NULL) {
8169781SMoriah.Waterland@Sun.COM 		/* UID does not exist in password file */
8179781SMoriah.Waterland@Sun.COM 		reperr(pkg_gt(ERR_BADUSRNM), ainfo->owner);
8189781SMoriah.Waterland@Sun.COM 		if (!retcode)
8199781SMoriah.Waterland@Sun.COM 			retcode = VE_ATTR;
8209781SMoriah.Waterland@Sun.COM 	} else if ((uid = pwd->pw_uid) != status.st_uid) {
8219781SMoriah.Waterland@Sun.COM 		/* get owner name for actual UID */
8229781SMoriah.Waterland@Sun.COM 		if (fix) {
8239781SMoriah.Waterland@Sun.COM 			uid = pwd->pw_uid;
8249781SMoriah.Waterland@Sun.COM 			dochown++;
8259781SMoriah.Waterland@Sun.COM 		} else {
8269781SMoriah.Waterland@Sun.COM 			pwd = cpwuid((int)status.st_uid);
8279781SMoriah.Waterland@Sun.COM 			if (pwd == NULL)
8289781SMoriah.Waterland@Sun.COM 				reperr(pkg_gt(ERR_BADUSRID),
8299781SMoriah.Waterland@Sun.COM 				    (int)status.st_uid);
8309781SMoriah.Waterland@Sun.COM 			else
8319781SMoriah.Waterland@Sun.COM 				reperr(pkg_gt(ERR_OWNER), ainfo->owner,
8329781SMoriah.Waterland@Sun.COM 				    pwd->pw_name);
8339781SMoriah.Waterland@Sun.COM 
8349781SMoriah.Waterland@Sun.COM 			if (!retcode)
8359781SMoriah.Waterland@Sun.COM 				retcode = VE_ATTR;
8369781SMoriah.Waterland@Sun.COM 		}
8379781SMoriah.Waterland@Sun.COM 	}
8389781SMoriah.Waterland@Sun.COM 
8399781SMoriah.Waterland@Sun.COM 	if (statvfs(path, &vfsstatus) < 0) {
8409781SMoriah.Waterland@Sun.COM 		reperr(pkg_gt(ERR_EXIST));
8419781SMoriah.Waterland@Sun.COM 		retcode = VE_FAIL;
8429781SMoriah.Waterland@Sun.COM 	} else {
8439781SMoriah.Waterland@Sun.COM 		if (dochown) {
8449781SMoriah.Waterland@Sun.COM 			/* pcfs doesn't support file ownership */
8459781SMoriah.Waterland@Sun.COM 			if (strcmp(vfsstatus.f_basetype, "pcfs") != 0 &&
8469781SMoriah.Waterland@Sun.COM 			    chown(path, uid, gid) < 0) {
8479781SMoriah.Waterland@Sun.COM 				retcode = VE_FAIL; /* chown failed */
8489781SMoriah.Waterland@Sun.COM 			}
8499781SMoriah.Waterland@Sun.COM 		}
8509781SMoriah.Waterland@Sun.COM 	}
8519781SMoriah.Waterland@Sun.COM 
8529781SMoriah.Waterland@Sun.COM 	if (retcode == VE_FAIL)
8539781SMoriah.Waterland@Sun.COM 		reperr(pkg_gt(ERR_ATTRFAIL));
8549781SMoriah.Waterland@Sun.COM 	return (retcode);
8559781SMoriah.Waterland@Sun.COM }
8569781SMoriah.Waterland@Sun.COM 
8579781SMoriah.Waterland@Sun.COM /*
8589781SMoriah.Waterland@Sun.COM  * This is a special fast verify which basically checks the attributes
8599781SMoriah.Waterland@Sun.COM  * and then, if all is OK, checks the size and mod time using the same
8609781SMoriah.Waterland@Sun.COM  * stat and statvfs structures.
8619781SMoriah.Waterland@Sun.COM  */
8629781SMoriah.Waterland@Sun.COM int
fverify(int fix,char * ftype,char * path,struct ainfo * ainfo,struct cinfo * cinfo)8639781SMoriah.Waterland@Sun.COM fverify(int fix, char *ftype, char *path, struct ainfo *ainfo,
8649781SMoriah.Waterland@Sun.COM     struct cinfo *cinfo)
8659781SMoriah.Waterland@Sun.COM {
8669781SMoriah.Waterland@Sun.COM 	int retval;
8679781SMoriah.Waterland@Sun.COM 
8689781SMoriah.Waterland@Sun.COM 	/* return success if attribute checks are disabled */
8699781SMoriah.Waterland@Sun.COM 
8709781SMoriah.Waterland@Sun.COM 	if (get_disable_attribute_check()) {
8719781SMoriah.Waterland@Sun.COM 		return (0);
8729781SMoriah.Waterland@Sun.COM 	}
8739781SMoriah.Waterland@Sun.COM 
8749781SMoriah.Waterland@Sun.COM 	if ((retval = averify(fix, ftype, path, ainfo)) == 0) {
8759781SMoriah.Waterland@Sun.COM 		if (*ftype == 'f' || *ftype == 'i') {
8769781SMoriah.Waterland@Sun.COM 			if (cinfo->size != status.st_size) {
8779781SMoriah.Waterland@Sun.COM 				reperr(pkg_gt(WRN_QV_SIZE), path);
8789781SMoriah.Waterland@Sun.COM 				retval = VE_CONT;
8799781SMoriah.Waterland@Sun.COM 			}
8809781SMoriah.Waterland@Sun.COM 			/* pcfs doesn't support modification times */
8819781SMoriah.Waterland@Sun.COM 			if (strcmp(vfsstatus.f_basetype, "pcfs") != 0) {
8829781SMoriah.Waterland@Sun.COM 				if (cinfo->modtime != status.st_mtime) {
8839781SMoriah.Waterland@Sun.COM 					reperr(pkg_gt(WRN_QV_MTIME), path);
8849781SMoriah.Waterland@Sun.COM 					retval = VE_CONT;
8859781SMoriah.Waterland@Sun.COM 				}
8869781SMoriah.Waterland@Sun.COM 			}
8879781SMoriah.Waterland@Sun.COM 		}
8889781SMoriah.Waterland@Sun.COM 	}
8899781SMoriah.Waterland@Sun.COM 
8909781SMoriah.Waterland@Sun.COM 	return (retval);
8919781SMoriah.Waterland@Sun.COM }
8929781SMoriah.Waterland@Sun.COM 
8939781SMoriah.Waterland@Sun.COM /*
8949781SMoriah.Waterland@Sun.COM  * This function determines whether or not non-ABI symlinks are supported.
8959781SMoriah.Waterland@Sun.COM  */
8969781SMoriah.Waterland@Sun.COM 
8979781SMoriah.Waterland@Sun.COM int
nonABI_symlinks(void)8989781SMoriah.Waterland@Sun.COM nonABI_symlinks(void)
8999781SMoriah.Waterland@Sun.COM {
9009781SMoriah.Waterland@Sun.COM 	return (nonabi_symlinks);
9019781SMoriah.Waterland@Sun.COM }
9029781SMoriah.Waterland@Sun.COM 
9039781SMoriah.Waterland@Sun.COM void
set_nonABI_symlinks(void)9049781SMoriah.Waterland@Sun.COM set_nonABI_symlinks(void)
9059781SMoriah.Waterland@Sun.COM {
9069781SMoriah.Waterland@Sun.COM 	nonabi_symlinks	= 1;
9079781SMoriah.Waterland@Sun.COM }
9089781SMoriah.Waterland@Sun.COM 
9099781SMoriah.Waterland@Sun.COM /*
9109781SMoriah.Waterland@Sun.COM  * Disable attribute checking. Only disable attribute checking if files
9119781SMoriah.Waterland@Sun.COM  * are guaranteed to exist in the FS.
9129781SMoriah.Waterland@Sun.COM  */
9139781SMoriah.Waterland@Sun.COM void
disable_attribute_check(void)9149781SMoriah.Waterland@Sun.COM disable_attribute_check(void)
9159781SMoriah.Waterland@Sun.COM {
9169781SMoriah.Waterland@Sun.COM 	disable_attributes = 1;
9179781SMoriah.Waterland@Sun.COM }
9189781SMoriah.Waterland@Sun.COM 
9199781SMoriah.Waterland@Sun.COM /*
9209781SMoriah.Waterland@Sun.COM  * This function determines whether or not to do attribute checking.
9219781SMoriah.Waterland@Sun.COM  * Returns:  0 - Do attribute checking
9229781SMoriah.Waterland@Sun.COM  *          !0 - Don't do attribute checking
9239781SMoriah.Waterland@Sun.COM  */
9249781SMoriah.Waterland@Sun.COM int
get_disable_attribute_check(void)9259781SMoriah.Waterland@Sun.COM get_disable_attribute_check(void)
9269781SMoriah.Waterland@Sun.COM {
9279781SMoriah.Waterland@Sun.COM 	return (disable_attributes);
9289781SMoriah.Waterland@Sun.COM }
9299781SMoriah.Waterland@Sun.COM 
9309781SMoriah.Waterland@Sun.COM /*
9319781SMoriah.Waterland@Sun.COM  * This function returns the address of the "global" error buffer that
9329781SMoriah.Waterland@Sun.COM  * is populated by the various functions in this module.
9339781SMoriah.Waterland@Sun.COM  */
9349781SMoriah.Waterland@Sun.COM 
9359781SMoriah.Waterland@Sun.COM char *
getErrbufAddr(void)9369781SMoriah.Waterland@Sun.COM getErrbufAddr(void)
9379781SMoriah.Waterland@Sun.COM {
9389781SMoriah.Waterland@Sun.COM 	return (theErrBuf);
9399781SMoriah.Waterland@Sun.COM }
9409781SMoriah.Waterland@Sun.COM 
9419781SMoriah.Waterland@Sun.COM /*
9429781SMoriah.Waterland@Sun.COM  * This function returns the size of the buffer returned by getErrbufAddr()
9439781SMoriah.Waterland@Sun.COM  */
9449781SMoriah.Waterland@Sun.COM 
9459781SMoriah.Waterland@Sun.COM int
getErrbufSize(void)9469781SMoriah.Waterland@Sun.COM getErrbufSize(void)
9479781SMoriah.Waterland@Sun.COM {
9489781SMoriah.Waterland@Sun.COM 	return (sizeof (theErrBuf));
9499781SMoriah.Waterland@Sun.COM }
9509781SMoriah.Waterland@Sun.COM 
9519781SMoriah.Waterland@Sun.COM /*
9529781SMoriah.Waterland@Sun.COM  * This function returns the current global "error string"
9539781SMoriah.Waterland@Sun.COM  */
9549781SMoriah.Waterland@Sun.COM 
9559781SMoriah.Waterland@Sun.COM char *
getErrstr(void)9569781SMoriah.Waterland@Sun.COM getErrstr(void)
9579781SMoriah.Waterland@Sun.COM {
9589781SMoriah.Waterland@Sun.COM 	return (theErrStr);
9599781SMoriah.Waterland@Sun.COM }
9609781SMoriah.Waterland@Sun.COM 
9619781SMoriah.Waterland@Sun.COM /*
9629781SMoriah.Waterland@Sun.COM  * This function sets the global "error string"
9639781SMoriah.Waterland@Sun.COM  */
9649781SMoriah.Waterland@Sun.COM 
9659781SMoriah.Waterland@Sun.COM void
setErrstr(char * a_errstr)9669781SMoriah.Waterland@Sun.COM setErrstr(char *a_errstr)
9679781SMoriah.Waterland@Sun.COM {
9689781SMoriah.Waterland@Sun.COM 	theErrStr = a_errstr;
9699781SMoriah.Waterland@Sun.COM }
9709781SMoriah.Waterland@Sun.COM 
9719781SMoriah.Waterland@Sun.COM /*
9729781SMoriah.Waterland@Sun.COM  * This function enables checksumming
9739781SMoriah.Waterland@Sun.COM  */
9749781SMoriah.Waterland@Sun.COM 
9759781SMoriah.Waterland@Sun.COM void
checksum_on(void)9769781SMoriah.Waterland@Sun.COM checksum_on(void)
9779781SMoriah.Waterland@Sun.COM {
9789781SMoriah.Waterland@Sun.COM 	enable_checksum = 1;
9799781SMoriah.Waterland@Sun.COM }
9809781SMoriah.Waterland@Sun.COM 
9819781SMoriah.Waterland@Sun.COM /*
9829781SMoriah.Waterland@Sun.COM  * This function disables checksumming
9839781SMoriah.Waterland@Sun.COM  */
9849781SMoriah.Waterland@Sun.COM 
9859781SMoriah.Waterland@Sun.COM void
checksum_off(void)9869781SMoriah.Waterland@Sun.COM checksum_off(void)
9879781SMoriah.Waterland@Sun.COM {
9889781SMoriah.Waterland@Sun.COM 	enable_checksum = 0;
9899781SMoriah.Waterland@Sun.COM }
990