xref: /illumos-gate/usr/src/lib/libpkg/common/verify.c (revision 5c51f124)
1*5c51f124SMoriah Waterland /*
2*5c51f124SMoriah Waterland  * CDDL HEADER START
3*5c51f124SMoriah Waterland  *
4*5c51f124SMoriah Waterland  * The contents of this file are subject to the terms of the
5*5c51f124SMoriah Waterland  * Common Development and Distribution License (the "License").
6*5c51f124SMoriah Waterland  * You may not use this file except in compliance with the License.
7*5c51f124SMoriah Waterland  *
8*5c51f124SMoriah Waterland  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*5c51f124SMoriah Waterland  * or http://www.opensolaris.org/os/licensing.
10*5c51f124SMoriah Waterland  * See the License for the specific language governing permissions
11*5c51f124SMoriah Waterland  * and limitations under the License.
12*5c51f124SMoriah Waterland  *
13*5c51f124SMoriah Waterland  * When distributing Covered Code, include this CDDL HEADER in each
14*5c51f124SMoriah Waterland  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*5c51f124SMoriah Waterland  * If applicable, add the following below this CDDL HEADER, with the
16*5c51f124SMoriah Waterland  * fields enclosed by brackets "[]" replaced with your own identifying
17*5c51f124SMoriah Waterland  * information: Portions Copyright [yyyy] [name of copyright owner]
18*5c51f124SMoriah Waterland  *
19*5c51f124SMoriah Waterland  * CDDL HEADER END
20*5c51f124SMoriah Waterland  */
21*5c51f124SMoriah Waterland 
22*5c51f124SMoriah Waterland /*
23*5c51f124SMoriah Waterland  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24*5c51f124SMoriah Waterland  * Use is subject to license terms.
25*5c51f124SMoriah Waterland  */
26*5c51f124SMoriah Waterland 
27*5c51f124SMoriah Waterland /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28*5c51f124SMoriah Waterland /* All Rights Reserved */
29*5c51f124SMoriah Waterland 
30*5c51f124SMoriah Waterland 
31*5c51f124SMoriah Waterland 
32*5c51f124SMoriah Waterland #include <stdio.h>
33*5c51f124SMoriah Waterland #include <limits.h>
34*5c51f124SMoriah Waterland #include <stdlib.h>
35*5c51f124SMoriah Waterland #include <unistd.h>
36*5c51f124SMoriah Waterland #include <utime.h>
37*5c51f124SMoriah Waterland #include <sys/types.h>
38*5c51f124SMoriah Waterland #include <sys/param.h>
39*5c51f124SMoriah Waterland #include <sys/stat.h>
40*5c51f124SMoriah Waterland #include <sys/statvfs.h>
41*5c51f124SMoriah Waterland #include <grp.h>
42*5c51f124SMoriah Waterland #include <pwd.h>
43*5c51f124SMoriah Waterland #include <errno.h>
44*5c51f124SMoriah Waterland #include <string.h>
45*5c51f124SMoriah Waterland #include <stdarg.h>
46*5c51f124SMoriah Waterland #include <fcntl.h>
47*5c51f124SMoriah Waterland #include <sys/mkdev.h>
48*5c51f124SMoriah Waterland #include "pkgstrct.h"
49*5c51f124SMoriah Waterland #include "pkglib.h"
50*5c51f124SMoriah Waterland #include "pkglibmsgs.h"
51*5c51f124SMoriah Waterland #include "pkglocale.h"
52*5c51f124SMoriah Waterland 
53*5c51f124SMoriah Waterland #define	WDMSK	0xFFFF
54*5c51f124SMoriah Waterland #define	DATEFMT	"%D %r"
55*5c51f124SMoriah Waterland #define	LONG_BOUNDARY	((sizeof (unsigned long))-1)
56*5c51f124SMoriah Waterland #define	CHUNK	1024*1024
57*5c51f124SMoriah Waterland 
58*5c51f124SMoriah Waterland static char	theErrBuf[PATH_MAX+512] = {'\0'};
59*5c51f124SMoriah Waterland static char	*theErrStr = NULL;
60*5c51f124SMoriah Waterland 
61*5c51f124SMoriah Waterland /* checksum disable switch */
62*5c51f124SMoriah Waterland static int	enable_checksum = 1;
63*5c51f124SMoriah Waterland 
64*5c51f124SMoriah Waterland /* attribute disable flag */
65*5c51f124SMoriah Waterland static int	disable_attributes = 0;
66*5c51f124SMoriah Waterland 
67*5c51f124SMoriah Waterland /* non-ABI symlinks supported */
68*5c51f124SMoriah Waterland static int	nonabi_symlinks;
69*5c51f124SMoriah Waterland 
70*5c51f124SMoriah Waterland /*
71*5c51f124SMoriah Waterland  * forward declarations
72*5c51f124SMoriah Waterland  */
73*5c51f124SMoriah Waterland 
74*5c51f124SMoriah Waterland static int	clear_target(char *path, char *ftype, int is_a_dir);
75*5c51f124SMoriah Waterland 
76*5c51f124SMoriah Waterland unsigned	long compute_checksum(int *r_err, char *path);
77*5c51f124SMoriah Waterland 
78*5c51f124SMoriah Waterland /* union used to generate checksum */
79*5c51f124SMoriah Waterland typedef union hilo {
80*5c51f124SMoriah Waterland 	struct part {
81*5c51f124SMoriah Waterland 		uint16_t hi;
82*5c51f124SMoriah Waterland 		uint16_t lo;
83*5c51f124SMoriah Waterland 	} hl;
84*5c51f124SMoriah Waterland 	uint32_t	lg;
85*5c51f124SMoriah Waterland } CHECKSUM_T;
86*5c51f124SMoriah Waterland 
87*5c51f124SMoriah Waterland /*PRINTFLIKE1*/
88*5c51f124SMoriah Waterland static void
89*5c51f124SMoriah Waterland reperr(char *fmt, ...)
90*5c51f124SMoriah Waterland {
91*5c51f124SMoriah Waterland 	char	*pt;
92*5c51f124SMoriah Waterland 	ssize_t	ptln;
93*5c51f124SMoriah Waterland 	va_list	ap;
94*5c51f124SMoriah Waterland 	int	n;
95*5c51f124SMoriah Waterland 
96*5c51f124SMoriah Waterland 	if (fmt == (char *)NULL) {
97*5c51f124SMoriah Waterland 		theErrBuf[0] = '\0';
98*5c51f124SMoriah Waterland 	} else {
99*5c51f124SMoriah Waterland 		if (n = strlen(theErrBuf)) {
100*5c51f124SMoriah Waterland 			pt = theErrBuf + n;
101*5c51f124SMoriah Waterland 			*pt++ = '\n';
102*5c51f124SMoriah Waterland 			*pt = '\0';
103*5c51f124SMoriah Waterland 			ptln = sizeof (theErrBuf)-n;
104*5c51f124SMoriah Waterland 		} else {
105*5c51f124SMoriah Waterland 			pt = theErrBuf;
106*5c51f124SMoriah Waterland 			ptln = sizeof (theErrBuf);
107*5c51f124SMoriah Waterland 		}
108*5c51f124SMoriah Waterland 		va_start(ap, fmt);
109*5c51f124SMoriah Waterland 		/* LINTED variable format specifier to vsnprintf() */
110*5c51f124SMoriah Waterland 		(void) vsnprintf(pt, ptln, fmt, ap);
111*5c51f124SMoriah Waterland 		va_end(ap);
112*5c51f124SMoriah Waterland 	}
113*5c51f124SMoriah Waterland }
114*5c51f124SMoriah Waterland 
115*5c51f124SMoriah Waterland /*
116*5c51f124SMoriah Waterland  * Name:	cverify
117*5c51f124SMoriah Waterland  * Description:	This function verifies and (if fix > 0) fixes the contents
118*5c51f124SMoriah Waterland  *		of the file at the path provided
119*5c51f124SMoriah Waterland  * Arguments:	fix - 0 - do not fix entries, 1 - fix entries
120*5c51f124SMoriah Waterland  *		ftype - single character "type" the entry is supposed to be
121*5c51f124SMoriah Waterland  *		path - path to file
122*5c51f124SMoriah Waterland  *		cinfo - content info structure representing the contents
123*5c51f124SMoriah Waterland  *			the entry is supposed to contain
124*5c51f124SMoriah Waterland  *		allow_checksum - determine if checksumming should be disabled:
125*5c51f124SMoriah Waterland  *		 == 0 - do not perform checksum ever - override enable_checksum.
126*5c51f124SMoriah Waterland  *		 != 0 - use the default checksum flag "enable_checksum" to
127*5c51f124SMoriah Waterland  *			determine if checksumming should be done.
128*5c51f124SMoriah Waterland  * NOTE:	modification and creation times can be repaired; the contents
129*5c51f124SMoriah Waterland  *		of the file cannot be corrected if the checksum indicates that
130*5c51f124SMoriah Waterland  *		the contents are not correct - VE_CONT will be returned in this
131*5c51f124SMoriah Waterland  *		case.
132*5c51f124SMoriah Waterland  * Possible return values:
133*5c51f124SMoriah Waterland  * - 0 = successful
134*5c51f124SMoriah Waterland  * - VE_EXIST = path name does not exist
135*5c51f124SMoriah Waterland  * - VE_FTYPE = path file type is not recognized, is not supported,
136*5c51f124SMoriah Waterland  *		or is not what was expected
137*5c51f124SMoriah Waterland  * - VE_ATTR = path mode/group/user is not what was expected
138*5c51f124SMoriah Waterland  * - VE_CONT = mod time/link target/major/minor/size/file system type/current
139*5c51f124SMoriah Waterland  *		directory is not what was expected
140*5c51f124SMoriah Waterland  * - VE_FAIL = utime/target directory/link/stat/symlink/mknod/chmod/statvfs/
141*5c51f124SMoriah Waterland  *		chown failed
142*5c51f124SMoriah Waterland  */
143*5c51f124SMoriah Waterland 
144*5c51f124SMoriah Waterland int
145*5c51f124SMoriah Waterland cverify(int fix, char *ftype, char *path, struct cinfo *cinfo,
146*5c51f124SMoriah Waterland 	int allow_checksum)
147*5c51f124SMoriah Waterland {
148*5c51f124SMoriah Waterland 	struct stat	status; 	/* file status buffer */
149*5c51f124SMoriah Waterland 	struct utimbuf	times;
150*5c51f124SMoriah Waterland 	unsigned long	mycksum;
151*5c51f124SMoriah Waterland 	int		setval, retcode;
152*5c51f124SMoriah Waterland 	char		tbuf1[512];
153*5c51f124SMoriah Waterland 	char		tbuf2[512];
154*5c51f124SMoriah Waterland 	int		cksumerr;
155*5c51f124SMoriah Waterland 
156*5c51f124SMoriah Waterland 	setval = (*ftype == '?');
157*5c51f124SMoriah Waterland 	retcode = 0;
158*5c51f124SMoriah Waterland 	reperr(NULL);
159*5c51f124SMoriah Waterland 
160*5c51f124SMoriah Waterland 	if (stat(path, &status) < 0) {
161*5c51f124SMoriah Waterland 		reperr(pkg_gt(ERR_EXIST));
162*5c51f124SMoriah Waterland 		return (VE_EXIST);
163*5c51f124SMoriah Waterland 	}
164*5c51f124SMoriah Waterland 
165*5c51f124SMoriah Waterland 	/* -1	requires modtimes to be the same */
166*5c51f124SMoriah Waterland 	/*  0   reports modtime failure */
167*5c51f124SMoriah Waterland 	/*  1   fixes modtimes */
168*5c51f124SMoriah Waterland 
169*5c51f124SMoriah Waterland 	if (setval || (cinfo->modtime == BADCONT)) {
170*5c51f124SMoriah Waterland 		cinfo->modtime = status.st_mtime;
171*5c51f124SMoriah Waterland 	} else if (status.st_mtime != cinfo->modtime) {
172*5c51f124SMoriah Waterland 		if (fix > 0) {
173*5c51f124SMoriah Waterland 			/* reset times on the file */
174*5c51f124SMoriah Waterland 			times.actime = cinfo->modtime;
175*5c51f124SMoriah Waterland 			times.modtime = cinfo->modtime;
176*5c51f124SMoriah Waterland 			if (utime(path, &times)) {
177*5c51f124SMoriah Waterland 				reperr(pkg_gt(ERR_MODFAIL));
178*5c51f124SMoriah Waterland 				retcode = VE_FAIL;
179*5c51f124SMoriah Waterland 			}
180*5c51f124SMoriah Waterland 		} else if (fix < 0) {
181*5c51f124SMoriah Waterland 			/* modtimes must be the same */
182*5c51f124SMoriah Waterland 			if (strftime(tbuf1, sizeof (tbuf1), DATEFMT,
183*5c51f124SMoriah Waterland 				localtime(&cinfo->modtime)) == 0) {
184*5c51f124SMoriah Waterland 				reperr(pkg_gt(ERR_MEM));
185*5c51f124SMoriah Waterland 			}
186*5c51f124SMoriah Waterland 			if (strftime(tbuf2, sizeof (tbuf2), DATEFMT,
187*5c51f124SMoriah Waterland 				localtime(&status.st_mtime)) == 0) {
188*5c51f124SMoriah Waterland 				reperr(pkg_gt(ERR_MEM));
189*5c51f124SMoriah Waterland 			}
190*5c51f124SMoriah Waterland 			reperr(pkg_gt(ERR_MTIME), tbuf1, tbuf2);
191*5c51f124SMoriah Waterland 			retcode = VE_CONT;
192*5c51f124SMoriah Waterland 		}
193*5c51f124SMoriah Waterland 	}
194*5c51f124SMoriah Waterland 
195*5c51f124SMoriah Waterland 	if (setval || (cinfo->size == (fsblkcnt_t)BADCONT)) {
196*5c51f124SMoriah Waterland 		cinfo->size = status.st_size;
197*5c51f124SMoriah Waterland 	} else if (status.st_size != cinfo->size) {
198*5c51f124SMoriah Waterland 		if (!retcode) {
199*5c51f124SMoriah Waterland 			retcode = VE_CONT;
200*5c51f124SMoriah Waterland 		}
201*5c51f124SMoriah Waterland 		reperr(pkg_gt(ERR_SIZE), cinfo->size, status.st_size);
202*5c51f124SMoriah Waterland 	}
203*5c51f124SMoriah Waterland 
204*5c51f124SMoriah Waterland 	cksumerr = 0;
205*5c51f124SMoriah Waterland 
206*5c51f124SMoriah Waterland 	/*
207*5c51f124SMoriah Waterland 	 * see if checksumming should be done: if checksumming is allowed,
208*5c51f124SMoriah Waterland 	 * and checksumming is enabled, then checksum the file.
209*5c51f124SMoriah Waterland 	 */
210*5c51f124SMoriah Waterland 
211*5c51f124SMoriah Waterland 	/* return if no need to compute checksum */
212*5c51f124SMoriah Waterland 
213*5c51f124SMoriah Waterland 	if ((allow_checksum == 0) || (enable_checksum == 0)) {
214*5c51f124SMoriah Waterland 		return (retcode);
215*5c51f124SMoriah Waterland 	}
216*5c51f124SMoriah Waterland 
217*5c51f124SMoriah Waterland 	/* compute checksum */
218*5c51f124SMoriah Waterland 
219*5c51f124SMoriah Waterland 	mycksum = compute_checksum(&cksumerr, path);
220*5c51f124SMoriah Waterland 
221*5c51f124SMoriah Waterland 	/* set value if not set or if checksum cannot be computed */
222*5c51f124SMoriah Waterland 
223*5c51f124SMoriah Waterland 	if (setval || (cinfo->cksum == BADCONT)) {
224*5c51f124SMoriah Waterland 		cinfo->cksum = mycksum;
225*5c51f124SMoriah Waterland 		return (retcode);
226*5c51f124SMoriah Waterland 	}
227*5c51f124SMoriah Waterland 
228*5c51f124SMoriah Waterland 	/* report / return error if checksums mismatch or there is an error */
229*5c51f124SMoriah Waterland 
230*5c51f124SMoriah Waterland 	if ((mycksum != cinfo->cksum) || cksumerr) {
231*5c51f124SMoriah Waterland 		if (!retcode) {
232*5c51f124SMoriah Waterland 			retcode = VE_CONT;
233*5c51f124SMoriah Waterland 		}
234*5c51f124SMoriah Waterland 		if (!cksumerr) {
235*5c51f124SMoriah Waterland 			reperr(pkg_gt(ERR_CKSUM), cinfo->cksum, mycksum);
236*5c51f124SMoriah Waterland 		}
237*5c51f124SMoriah Waterland 	}
238*5c51f124SMoriah Waterland 
239*5c51f124SMoriah Waterland 	return (retcode);
240*5c51f124SMoriah Waterland }
241*5c51f124SMoriah Waterland 
242*5c51f124SMoriah Waterland /*
243*5c51f124SMoriah Waterland  * Name:	compute_checksum
244*5c51f124SMoriah Waterland  * Description:	generate checksum for specified file
245*5c51f124SMoriah Waterland  * Arguments:	r_cksumerr (int *) [RO, *RW]
246*5c51f124SMoriah Waterland  *			- pointer to integer that is set on return to:
247*5c51f124SMoriah Waterland  *				== 0 - no error occurred
248*5c51f124SMoriah Waterland  *				!= 0 - error occurred
249*5c51f124SMoriah Waterland  *		a_path (char *) [RO, *RO]
250*5c51f124SMoriah Waterland  *			- pointer to string representing path to file to
251*5c51f124SMoriah Waterland  *			  generate checksum of
252*5c51f124SMoriah Waterland  * Returns:	unsigned long - results:
253*5c51f124SMoriah Waterland  *			- If *r_cksumerr == 0, checksum of specified file
254*5c51f124SMoriah Waterland  *			- If *r_cksumerr != 0, undefined
255*5c51f124SMoriah Waterland  */
256*5c51f124SMoriah Waterland unsigned long
257*5c51f124SMoriah Waterland compute_checksum(int *r_cksumerr, char *a_path)
258*5c51f124SMoriah Waterland {
259*5c51f124SMoriah Waterland 	CHECKSUM_T	suma;	/* to split four-bytes into 2 two-byte values */
260*5c51f124SMoriah Waterland 	CHECKSUM_T	tempa;
261*5c51f124SMoriah Waterland 	int		fd;
262*5c51f124SMoriah Waterland 	uint32_t	lg;	/* running checksum value */
263*5c51f124SMoriah Waterland 	uint32_t	buf[CHUNK/4]; /* to read CHUNK bytes */
264*5c51f124SMoriah Waterland 	uint32_t	lsavhi;	/* high order two-bytes of four-byte checksum */
265*5c51f124SMoriah Waterland 	uint32_t	lsavlo;	/* low order two-bytes of four-byte checksum */
266*5c51f124SMoriah Waterland 	int		leap = sizeof (uint32_t);
267*5c51f124SMoriah Waterland 	int		notyet = 0;
268*5c51f124SMoriah Waterland 	int		nread;
269*5c51f124SMoriah Waterland 	struct stat64	sbuf;
270*5c51f124SMoriah Waterland 
271*5c51f124SMoriah Waterland 	/* reset error flag */
272*5c51f124SMoriah Waterland 	*r_cksumerr = 0;
273*5c51f124SMoriah Waterland 
274*5c51f124SMoriah Waterland 	/* open file and obtain -> where file is mapped/read */
275*5c51f124SMoriah Waterland 	if ((fd = open(a_path, O_RDONLY)) < 0) {
276*5c51f124SMoriah Waterland 		*r_cksumerr = 1;
277*5c51f124SMoriah Waterland 		reperr(pkg_gt(ERR_NO_CKSUM));
278*5c51f124SMoriah Waterland 		perror(ERR_NO_CKSUM);
279*5c51f124SMoriah Waterland 		return (0);
280*5c51f124SMoriah Waterland 	}
281*5c51f124SMoriah Waterland 
282*5c51f124SMoriah Waterland 	if (fstat64(fd, &sbuf) != 0) {
283*5c51f124SMoriah Waterland 		*r_cksumerr = 1;
284*5c51f124SMoriah Waterland 		reperr(pkg_gt(ERR_NO_CKSUM));
285*5c51f124SMoriah Waterland 		perror(ERR_NO_CKSUM);
286*5c51f124SMoriah Waterland 		return (0);
287*5c51f124SMoriah Waterland 	}
288*5c51f124SMoriah Waterland 
289*5c51f124SMoriah Waterland 	/* initialize checksum value */
290*5c51f124SMoriah Waterland 	lg = 0;
291*5c51f124SMoriah Waterland 
292*5c51f124SMoriah Waterland 	/*
293*5c51f124SMoriah Waterland 	 * Read CHUNK bytes off the file at a time; Read size of long bytes
294*5c51f124SMoriah Waterland 	 * from memory at a time and process them.
295*5c51f124SMoriah Waterland 	 * If last read, then read remnant bytes and process individually.
296*5c51f124SMoriah Waterland 	 */
297*5c51f124SMoriah Waterland 	errno = 0;
298*5c51f124SMoriah Waterland 	while ((nread = read(fd, (void*)buf,
299*5c51f124SMoriah Waterland 		    (sbuf.st_size < CHUNK) ? sbuf.st_size : CHUNK)) > 0) {
300*5c51f124SMoriah Waterland 		uchar_t *s;
301*5c51f124SMoriah Waterland 		uint32_t *p = buf;
302*5c51f124SMoriah Waterland 
303*5c51f124SMoriah Waterland 		notyet = nread % leap;
304*5c51f124SMoriah Waterland 		nread -= notyet;
305*5c51f124SMoriah Waterland 
306*5c51f124SMoriah Waterland 		for (; nread > 0; nread -= leap) {
307*5c51f124SMoriah Waterland 			lg += ((((*p)>>24)&0xFF) & WDMSK);
308*5c51f124SMoriah Waterland 			lg += ((((*p)>>16)&0xFF) & WDMSK);
309*5c51f124SMoriah Waterland 			lg += ((((*p)>>8)&0xFF) & WDMSK);
310*5c51f124SMoriah Waterland 			lg += (((*p)&0xFF) & WDMSK);
311*5c51f124SMoriah Waterland 			p++;
312*5c51f124SMoriah Waterland 		}
313*5c51f124SMoriah Waterland 		s = (uchar_t *)p;
314*5c51f124SMoriah Waterland 		/* leftover bytes less than four in number */
315*5c51f124SMoriah Waterland 		while (notyet--)
316*5c51f124SMoriah Waterland 			lg += (((uint32_t)(*s++)) & WDMSK);
317*5c51f124SMoriah Waterland 	}
318*5c51f124SMoriah Waterland 
319*5c51f124SMoriah Waterland 	/* wind up */
320*5c51f124SMoriah Waterland 	(void) close(fd);
321*5c51f124SMoriah Waterland 
322*5c51f124SMoriah Waterland 	/* compute checksum components */
323*5c51f124SMoriah Waterland 	suma.lg = lg;
324*5c51f124SMoriah Waterland 	tempa.lg = (suma.hl.lo & WDMSK) + (suma.hl.hi & WDMSK);
325*5c51f124SMoriah Waterland 	lsavhi = (uint32_t)tempa.hl.hi;
326*5c51f124SMoriah Waterland 	lsavlo = (uint32_t)tempa.hl.lo;
327*5c51f124SMoriah Waterland 
328*5c51f124SMoriah Waterland 	/* return final checksum value */
329*5c51f124SMoriah Waterland 	return (lsavhi+lsavlo);
330*5c51f124SMoriah Waterland }
331*5c51f124SMoriah Waterland 
332*5c51f124SMoriah Waterland static 	struct stat	status; 	/* file status buffer */
333*5c51f124SMoriah Waterland static  struct statvfs	vfsstatus;	/* filesystem status buffer */
334*5c51f124SMoriah Waterland 
335*5c51f124SMoriah Waterland /*
336*5c51f124SMoriah Waterland  * Remove the thing that's currently in place so we can put down the package
337*5c51f124SMoriah Waterland  * object. If we're replacing a directory with a directory, leave it alone.
338*5c51f124SMoriah Waterland  * Returns 1 if all OK and 0 if failed.
339*5c51f124SMoriah Waterland  */
340*5c51f124SMoriah Waterland static int
341*5c51f124SMoriah Waterland clear_target(char *path, char *ftype, int is_a_dir)
342*5c51f124SMoriah Waterland {
343*5c51f124SMoriah Waterland 	int retcode = 1;
344*5c51f124SMoriah Waterland 
345*5c51f124SMoriah Waterland 	if (is_a_dir) {	/* if there's a directory there already ... */
346*5c51f124SMoriah Waterland 		/* ... and this isn't, ... */
347*5c51f124SMoriah Waterland 		if ((*ftype != 'd') && (*ftype != 'x')) {
348*5c51f124SMoriah Waterland 			if (rmdir(path)) {	/* try to remove it. */
349*5c51f124SMoriah Waterland 				reperr(pkg_gt(ERR_RMDIR), path);
350*5c51f124SMoriah Waterland 				retcode = 0;
351*5c51f124SMoriah Waterland 			}
352*5c51f124SMoriah Waterland 		}
353*5c51f124SMoriah Waterland 	} else {
354*5c51f124SMoriah Waterland 		if (remove(path)) {
355*5c51f124SMoriah Waterland 			if (errno != ENOENT) {
356*5c51f124SMoriah Waterland 				retcode = 0;	/* It didn't work. */
357*5c51f124SMoriah Waterland 			}
358*5c51f124SMoriah Waterland 		}
359*5c51f124SMoriah Waterland 	}
360*5c51f124SMoriah Waterland 
361*5c51f124SMoriah Waterland 	return (retcode);
362*5c51f124SMoriah Waterland }
363*5c51f124SMoriah Waterland 
364*5c51f124SMoriah Waterland /*
365*5c51f124SMoriah Waterland  * Name:	averify
366*5c51f124SMoriah Waterland  * Description:	This function verifies and (if fix > 0) fixes the attributes
367*5c51f124SMoriah Waterland  *		of the file at the path provided.
368*5c51f124SMoriah Waterland  * Arguments:	fix - 0 - do not fix entries, 1 - fix entries
369*5c51f124SMoriah Waterland  *		ftype - single character "type" the entry is supposed to be
370*5c51f124SMoriah Waterland  *		path - path to file
371*5c51f124SMoriah Waterland  *		ainfo - attribute info structure representing the attributes
372*5c51f124SMoriah Waterland  *			the entry is supposed to be
373*5c51f124SMoriah Waterland  * NOTE:	attributes are links and permissions
374*5c51f124SMoriah Waterland  * Possible return values:
375*5c51f124SMoriah Waterland  * - 0 = successful
376*5c51f124SMoriah Waterland  * - VE_EXIST = path name does not exist
377*5c51f124SMoriah Waterland  * - VE_FTYPE = path file type is not recognized, is not supported,
378*5c51f124SMoriah Waterland  *		or is not what was expected
379*5c51f124SMoriah Waterland  * - VE_ATTR = path mode/group/user is not what was expected
380*5c51f124SMoriah Waterland  * - VE_CONT = mod time/link target/major/minor/size/file system type/current
381*5c51f124SMoriah Waterland  *		directory is not what was expected
382*5c51f124SMoriah Waterland  * - VE_FAIL = utime/target directory/link/stat/symlink/mknod/chmod/statvfs/
383*5c51f124SMoriah Waterland  *		chown failed
384*5c51f124SMoriah Waterland  */
385*5c51f124SMoriah Waterland int
386*5c51f124SMoriah Waterland averify(int fix, char *ftype, char *path, struct ainfo *ainfo)
387*5c51f124SMoriah Waterland {
388*5c51f124SMoriah Waterland 	struct group	*grp; 	/* group entry buffer */
389*5c51f124SMoriah Waterland 	struct passwd	*pwd;
390*5c51f124SMoriah Waterland 	int		n;
391*5c51f124SMoriah Waterland 	int		setval;
392*5c51f124SMoriah Waterland 	int		uid, gid;
393*5c51f124SMoriah Waterland 	int		dochown;
394*5c51f124SMoriah Waterland 	int		retcode;
395*5c51f124SMoriah Waterland 	int		statError = 0;
396*5c51f124SMoriah Waterland 	int		targ_is_dir = 0;	/* replacing a directory */
397*5c51f124SMoriah Waterland 	char		myftype;
398*5c51f124SMoriah Waterland 	char		buf[PATH_MAX];
399*5c51f124SMoriah Waterland 	ino_t		my_ino;
400*5c51f124SMoriah Waterland 	dev_t		my_dev;
401*5c51f124SMoriah Waterland 	char 		cwd[MAXPATHLEN];
402*5c51f124SMoriah Waterland 	char 		*cd;
403*5c51f124SMoriah Waterland 	char 		*c;
404*5c51f124SMoriah Waterland 
405*5c51f124SMoriah Waterland 	setval = (*ftype == '?');
406*5c51f124SMoriah Waterland 	retcode = 0;
407*5c51f124SMoriah Waterland 	reperr(NULL);
408*5c51f124SMoriah Waterland 
409*5c51f124SMoriah Waterland 	if (get_disable_attribute_check()) {
410*5c51f124SMoriah Waterland 		return (0);
411*5c51f124SMoriah Waterland 	}
412*5c51f124SMoriah Waterland 
413*5c51f124SMoriah Waterland 	if (*ftype == 'l') {
414*5c51f124SMoriah Waterland 		if (stat(path, &status) < 0) {
415*5c51f124SMoriah Waterland 			retcode = VE_EXIST;
416*5c51f124SMoriah Waterland 			reperr(pkg_gt(ERR_EXIST));
417*5c51f124SMoriah Waterland 		}
418*5c51f124SMoriah Waterland 
419*5c51f124SMoriah Waterland 		my_ino = status.st_ino;
420*5c51f124SMoriah Waterland 		my_dev = status.st_dev;
421*5c51f124SMoriah Waterland 
422*5c51f124SMoriah Waterland 		/* Get copy of the current working directory */
423*5c51f124SMoriah Waterland 		if (getcwd(cwd, MAXPATHLEN) == NULL) {
424*5c51f124SMoriah Waterland 			reperr(pkg_gt(ERR_GETWD), ainfo->local);
425*5c51f124SMoriah Waterland 			return (VE_FAIL);
426*5c51f124SMoriah Waterland 		}
427*5c51f124SMoriah Waterland 
428*5c51f124SMoriah Waterland 		/*
429*5c51f124SMoriah Waterland 		 * Change to the directory in which the hard
430*5c51f124SMoriah Waterland 		 * link is to be created.
431*5c51f124SMoriah Waterland 		 */
432*5c51f124SMoriah Waterland 		cd = strdup(path);
433*5c51f124SMoriah Waterland 		c = strrchr(cd, '/');
434*5c51f124SMoriah Waterland 		if (c) {
435*5c51f124SMoriah Waterland 			/* bugid 4247895 */
436*5c51f124SMoriah Waterland 			if (strcmp(cd, c) == 0)
437*5c51f124SMoriah Waterland 				strcpy(cd, "/");
438*5c51f124SMoriah Waterland 			else
439*5c51f124SMoriah Waterland 				*c = NULL;
440*5c51f124SMoriah Waterland 
441*5c51f124SMoriah Waterland 			if (chdir(cd) != 0) {
442*5c51f124SMoriah Waterland 				reperr(pkg_gt(ERR_CHDIR), cd);
443*5c51f124SMoriah Waterland 				return (VE_FAIL);
444*5c51f124SMoriah Waterland 			}
445*5c51f124SMoriah Waterland 		}
446*5c51f124SMoriah Waterland 		free(cd);
447*5c51f124SMoriah Waterland 
448*5c51f124SMoriah Waterland 		if (retcode || (status.st_nlink < 2) ||
449*5c51f124SMoriah Waterland 		    (stat(ainfo->local, &status) < 0) ||
450*5c51f124SMoriah Waterland 		    (my_dev != status.st_dev) || (my_ino != status.st_ino)) {
451*5c51f124SMoriah Waterland 			if (fix) {
452*5c51f124SMoriah Waterland 				/*
453*5c51f124SMoriah Waterland 				 * Don't want to do a hard link to a
454*5c51f124SMoriah Waterland 				 * directory.
455*5c51f124SMoriah Waterland 				 */
456*5c51f124SMoriah Waterland 				if (!isdir(ainfo->local)) {
457*5c51f124SMoriah Waterland 					chdir(cwd);
458*5c51f124SMoriah Waterland 					reperr(pkg_gt(ERR_LINKISDIR),
459*5c51f124SMoriah Waterland 					    ainfo->local);
460*5c51f124SMoriah Waterland 					return (VE_FAIL);
461*5c51f124SMoriah Waterland 				}
462*5c51f124SMoriah Waterland 				/* Now do the link. */
463*5c51f124SMoriah Waterland 				if (!clear_target(path, ftype, targ_is_dir))
464*5c51f124SMoriah Waterland 					return (VE_FAIL);
465*5c51f124SMoriah Waterland 
466*5c51f124SMoriah Waterland 				if (link(ainfo->local, path)) {
467*5c51f124SMoriah Waterland 					chdir(cwd);
468*5c51f124SMoriah Waterland 					reperr(pkg_gt(ERR_LINKFAIL),
469*5c51f124SMoriah Waterland 					    ainfo->local);
470*5c51f124SMoriah Waterland 					return (VE_FAIL);
471*5c51f124SMoriah Waterland 				}
472*5c51f124SMoriah Waterland 				retcode = 0;
473*5c51f124SMoriah Waterland 			} else {
474*5c51f124SMoriah Waterland 				/* Go back to previous working directory */
475*5c51f124SMoriah Waterland 				if (chdir(cwd) != 0)
476*5c51f124SMoriah Waterland 					reperr(pkg_gt(ERR_CHDIR), cwd);
477*5c51f124SMoriah Waterland 
478*5c51f124SMoriah Waterland 				reperr(pkg_gt(ERR_LINK), ainfo->local);
479*5c51f124SMoriah Waterland 				return (VE_CONT);
480*5c51f124SMoriah Waterland 			}
481*5c51f124SMoriah Waterland 		}
482*5c51f124SMoriah Waterland 
483*5c51f124SMoriah Waterland 		/* Go back to previous working directory */
484*5c51f124SMoriah Waterland 		if (chdir(cwd) != 0) {
485*5c51f124SMoriah Waterland 			reperr(pkg_gt(ERR_CHDIR), cwd);
486*5c51f124SMoriah Waterland 			return (VE_CONT);
487*5c51f124SMoriah Waterland 		}
488*5c51f124SMoriah Waterland 
489*5c51f124SMoriah Waterland 		return (retcode);
490*5c51f124SMoriah Waterland 	}
491*5c51f124SMoriah Waterland 
492*5c51f124SMoriah Waterland 	retcode = 0;
493*5c51f124SMoriah Waterland 
494*5c51f124SMoriah Waterland 	/* If we are to process symlinks the old way then we follow the link */
495*5c51f124SMoriah Waterland 	if (nonABI_symlinks()) {
496*5c51f124SMoriah Waterland 		if ((*ftype == 's') ? lstat(path, &status) :
497*5c51f124SMoriah Waterland 			stat(path, &status)) {
498*5c51f124SMoriah Waterland 			reperr(pkg_gt(ERR_EXIST));
499*5c51f124SMoriah Waterland 			retcode = VE_EXIST;
500*5c51f124SMoriah Waterland 			myftype = '?';
501*5c51f124SMoriah Waterland 			statError++;
502*5c51f124SMoriah Waterland 		}
503*5c51f124SMoriah Waterland 	/* If not then we inspect the target of the link */
504*5c51f124SMoriah Waterland 	} else {
505*5c51f124SMoriah Waterland 		if ((n = lstat(path, &status)) == -1) {
506*5c51f124SMoriah Waterland 			reperr(pkg_gt(ERR_EXIST));
507*5c51f124SMoriah Waterland 			retcode = VE_EXIST;
508*5c51f124SMoriah Waterland 			myftype = '?';
509*5c51f124SMoriah Waterland 			statError++;
510*5c51f124SMoriah Waterland 		}
511*5c51f124SMoriah Waterland 	}
512*5c51f124SMoriah Waterland 	if (!statError) {
513*5c51f124SMoriah Waterland 		/* determining actual type of existing object */
514*5c51f124SMoriah Waterland 		switch (status.st_mode & S_IFMT) {
515*5c51f124SMoriah Waterland 		    case S_IFLNK:
516*5c51f124SMoriah Waterland 			myftype = 's';
517*5c51f124SMoriah Waterland 			break;
518*5c51f124SMoriah Waterland 
519*5c51f124SMoriah Waterland 		    case S_IFIFO:
520*5c51f124SMoriah Waterland 			myftype = 'p';
521*5c51f124SMoriah Waterland 			break;
522*5c51f124SMoriah Waterland 
523*5c51f124SMoriah Waterland 		    case S_IFCHR:
524*5c51f124SMoriah Waterland 			myftype = 'c';
525*5c51f124SMoriah Waterland 			break;
526*5c51f124SMoriah Waterland 
527*5c51f124SMoriah Waterland 		    case S_IFDIR:
528*5c51f124SMoriah Waterland 			myftype = 'd';
529*5c51f124SMoriah Waterland 			targ_is_dir = 1;
530*5c51f124SMoriah Waterland 			break;
531*5c51f124SMoriah Waterland 
532*5c51f124SMoriah Waterland 		    case S_IFBLK:
533*5c51f124SMoriah Waterland 			myftype = 'b';
534*5c51f124SMoriah Waterland 			break;
535*5c51f124SMoriah Waterland 
536*5c51f124SMoriah Waterland 		    case S_IFREG:
537*5c51f124SMoriah Waterland 		    case 0:
538*5c51f124SMoriah Waterland 			myftype = 'f';
539*5c51f124SMoriah Waterland 			break;
540*5c51f124SMoriah Waterland 
541*5c51f124SMoriah Waterland 		    case S_IFDOOR:
542*5c51f124SMoriah Waterland 			myftype = 'D';
543*5c51f124SMoriah Waterland 			break;
544*5c51f124SMoriah Waterland 
545*5c51f124SMoriah Waterland 		    default:
546*5c51f124SMoriah Waterland 			reperr(pkg_gt(ERR_UNKNOWN));
547*5c51f124SMoriah Waterland 			return (VE_FTYPE);
548*5c51f124SMoriah Waterland 		}
549*5c51f124SMoriah Waterland 	}
550*5c51f124SMoriah Waterland 
551*5c51f124SMoriah Waterland 	if (setval) {
552*5c51f124SMoriah Waterland 		/*
553*5c51f124SMoriah Waterland 		 * Check to make sure that a package or an installf that uses
554*5c51f124SMoriah Waterland 		 * wild cards '?' to assume the ftype of an object on the
555*5c51f124SMoriah Waterland 		 * system is not assuming a door ftype. Doors are not supported
556*5c51f124SMoriah Waterland 		 * but should be ignored.
557*5c51f124SMoriah Waterland 		 */
558*5c51f124SMoriah Waterland 		if (myftype == 'D') {
559*5c51f124SMoriah Waterland 			reperr(pkg_gt(ERR_FTYPED), path);
560*5c51f124SMoriah Waterland 			retcode = VE_FTYPE;
561*5c51f124SMoriah Waterland 			return (VE_FTYPE);
562*5c51f124SMoriah Waterland 		} else {
563*5c51f124SMoriah Waterland 			*ftype = myftype;
564*5c51f124SMoriah Waterland 		}
565*5c51f124SMoriah Waterland 	} else if (!retcode && (*ftype != myftype) &&
566*5c51f124SMoriah Waterland 	    ((myftype != 'f') || !strchr("ilev", *ftype)) &&
567*5c51f124SMoriah Waterland 	    ((myftype != 'd') || (*ftype != 'x'))) {
568*5c51f124SMoriah Waterland 		reperr(pkg_gt(ERR_FTYPE), *ftype, myftype);
569*5c51f124SMoriah Waterland 		retcode = VE_FTYPE;
570*5c51f124SMoriah Waterland 	}
571*5c51f124SMoriah Waterland 
572*5c51f124SMoriah Waterland 	if (!retcode && (*ftype == 's')) {
573*5c51f124SMoriah Waterland 		/* make sure that symbolic link is correct */
574*5c51f124SMoriah Waterland 		n = readlink(path, buf, PATH_MAX);
575*5c51f124SMoriah Waterland 		if (n < 0) {
576*5c51f124SMoriah Waterland 			reperr(pkg_gt(ERR_SLINK), ainfo->local);
577*5c51f124SMoriah Waterland 			retcode = VE_CONT;
578*5c51f124SMoriah Waterland 		} else if (ainfo->local != NULL) {
579*5c51f124SMoriah Waterland 			buf[n] = '\0';
580*5c51f124SMoriah Waterland 			if (strcmp(buf, ainfo->local)) {
581*5c51f124SMoriah Waterland 				reperr(pkg_gt(ERR_SLINK), ainfo->local);
582*5c51f124SMoriah Waterland 				retcode = VE_CONT;
583*5c51f124SMoriah Waterland 			}
584*5c51f124SMoriah Waterland 		} else if (ainfo->local == NULL) {
585*5c51f124SMoriah Waterland 			/*
586*5c51f124SMoriah Waterland 			 * Since a sym link target exists, insert it
587*5c51f124SMoriah Waterland 			 * into the ainfo structure
588*5c51f124SMoriah Waterland 			 */
589*5c51f124SMoriah Waterland 			buf[n] = '\0';
590*5c51f124SMoriah Waterland 			ainfo->local = strdup(buf);
591*5c51f124SMoriah Waterland 		}
592*5c51f124SMoriah Waterland 	}
593*5c51f124SMoriah Waterland 
594*5c51f124SMoriah Waterland 	if (retcode) {
595*5c51f124SMoriah Waterland 		/* The path doesn't exist or is different than it should be. */
596*5c51f124SMoriah Waterland 		if (fix) {
597*5c51f124SMoriah Waterland 			/*
598*5c51f124SMoriah Waterland 			 * Clear the way for the write. If it won't clear,
599*5c51f124SMoriah Waterland 			 * there's nothing we can do.
600*5c51f124SMoriah Waterland 			 */
601*5c51f124SMoriah Waterland 			if (!clear_target(path, ftype, targ_is_dir))
602*5c51f124SMoriah Waterland 				return (VE_FAIL);
603*5c51f124SMoriah Waterland 
604*5c51f124SMoriah Waterland 			if ((*ftype == 'd') || (*ftype == 'x')) {
605*5c51f124SMoriah Waterland 				char	*pt, *p;
606*5c51f124SMoriah Waterland 
607*5c51f124SMoriah Waterland 				/* Try to make it the easy way */
608*5c51f124SMoriah Waterland 				if (mkdir(path, ainfo->mode)) {
609*5c51f124SMoriah Waterland 					/*
610*5c51f124SMoriah Waterland 					 * Failing that, walk through the
611*5c51f124SMoriah Waterland 					 * parent directories creating
612*5c51f124SMoriah Waterland 					 * whatever is needed.
613*5c51f124SMoriah Waterland 					 */
614*5c51f124SMoriah Waterland 					p = strdup(path);
615*5c51f124SMoriah Waterland 					pt = (*p == '/') ? p+1 : p;
616*5c51f124SMoriah Waterland 					do {
617*5c51f124SMoriah Waterland 						if (pt = strchr(pt, '/'))
618*5c51f124SMoriah Waterland 							*pt = '\0';
619*5c51f124SMoriah Waterland 						if (access(p, 0) &&
620*5c51f124SMoriah Waterland 						    mkdir(p, ainfo->mode))
621*5c51f124SMoriah Waterland 							break;
622*5c51f124SMoriah Waterland 						if (pt)
623*5c51f124SMoriah Waterland 							*pt++ = '/';
624*5c51f124SMoriah Waterland 					} while (pt);
625*5c51f124SMoriah Waterland 					free(p);
626*5c51f124SMoriah Waterland 				}
627*5c51f124SMoriah Waterland 				if (stat(path, &status) < 0) {
628*5c51f124SMoriah Waterland 					reperr(pkg_gt(ERR_DIRFAIL));
629*5c51f124SMoriah Waterland 					return (VE_FAIL);
630*5c51f124SMoriah Waterland 				}
631*5c51f124SMoriah Waterland 			} else if (*ftype == 's') {
632*5c51f124SMoriah Waterland 				if (symlink(ainfo->local, path)) {
633*5c51f124SMoriah Waterland 					reperr(pkg_gt(ERR_SLINKFAIL),
634*5c51f124SMoriah Waterland 					    ainfo->local);
635*5c51f124SMoriah Waterland 					return (VE_FAIL);
636*5c51f124SMoriah Waterland 				}
637*5c51f124SMoriah Waterland 
638*5c51f124SMoriah Waterland 			} else if (*ftype == 'c') {
639*5c51f124SMoriah Waterland 				int wilddevno = 0;
640*5c51f124SMoriah Waterland 				/*
641*5c51f124SMoriah Waterland 				 * The next three if's support 2.4 and older
642*5c51f124SMoriah Waterland 				 * packages that use "?" as device numbers.
643*5c51f124SMoriah Waterland 				 * This should be considered for removal by
644*5c51f124SMoriah Waterland 				 * release 2.7 or so.
645*5c51f124SMoriah Waterland 				 */
646*5c51f124SMoriah Waterland 				if (ainfo->major == BADMAJOR) {
647*5c51f124SMoriah Waterland 					ainfo->major = 0;
648*5c51f124SMoriah Waterland 					wilddevno = 1;
649*5c51f124SMoriah Waterland 				}
650*5c51f124SMoriah Waterland 
651*5c51f124SMoriah Waterland 				if (ainfo->minor == BADMINOR) {
652*5c51f124SMoriah Waterland 					ainfo->minor = 0;
653*5c51f124SMoriah Waterland 					wilddevno = 1;
654*5c51f124SMoriah Waterland 				}
655*5c51f124SMoriah Waterland 
656*5c51f124SMoriah Waterland 				if (wilddevno) {
657*5c51f124SMoriah Waterland 					wilddevno = 0;
658*5c51f124SMoriah Waterland 					logerr(MSG_WLDDEVNO, path,
659*5c51f124SMoriah Waterland 					    ainfo->major, ainfo->minor);
660*5c51f124SMoriah Waterland 				}
661*5c51f124SMoriah Waterland 
662*5c51f124SMoriah Waterland 				if (mknod(path, ainfo->mode | S_IFCHR,
663*5c51f124SMoriah Waterland #ifdef SUNOS41
664*5c51f124SMoriah Waterland 				    makedev(ainfo->xmajor, ainfo->xminor)) ||
665*5c51f124SMoriah Waterland #else
666*5c51f124SMoriah Waterland 				    makedev(ainfo->major, ainfo->minor)) ||
667*5c51f124SMoriah Waterland #endif
668*5c51f124SMoriah Waterland 				    (stat(path, &status) < 0)) {
669*5c51f124SMoriah Waterland 					reperr(pkg_gt(ERR_CDEVFAIL));
670*5c51f124SMoriah Waterland 					return (VE_FAIL);
671*5c51f124SMoriah Waterland 				}
672*5c51f124SMoriah Waterland 			} else if (*ftype == 'b') {
673*5c51f124SMoriah Waterland 				int wilddevno = 0;
674*5c51f124SMoriah Waterland 				/*
675*5c51f124SMoriah Waterland 				 * The next three if's support 2.4 and older
676*5c51f124SMoriah Waterland 				 * packages that use "?" as device numbers.
677*5c51f124SMoriah Waterland 				 * This should be considered for removal by
678*5c51f124SMoriah Waterland 				 * release 2.7 or so.
679*5c51f124SMoriah Waterland 				 */
680*5c51f124SMoriah Waterland 				if (ainfo->major == BADMAJOR) {
681*5c51f124SMoriah Waterland 					ainfo->major = 0;
682*5c51f124SMoriah Waterland 					wilddevno = 1;
683*5c51f124SMoriah Waterland 				}
684*5c51f124SMoriah Waterland 
685*5c51f124SMoriah Waterland 				if (ainfo->minor == BADMINOR) {
686*5c51f124SMoriah Waterland 					ainfo->minor = 0;
687*5c51f124SMoriah Waterland 					wilddevno = 1;
688*5c51f124SMoriah Waterland 				}
689*5c51f124SMoriah Waterland 
690*5c51f124SMoriah Waterland 				if (wilddevno) {
691*5c51f124SMoriah Waterland 					wilddevno = 0;
692*5c51f124SMoriah Waterland 					logerr(MSG_WLDDEVNO, path,
693*5c51f124SMoriah Waterland 					    ainfo->major, ainfo->minor);
694*5c51f124SMoriah Waterland 				}
695*5c51f124SMoriah Waterland 
696*5c51f124SMoriah Waterland 				if (mknod(path, ainfo->mode | S_IFBLK,
697*5c51f124SMoriah Waterland #ifdef SUNOS41
698*5c51f124SMoriah Waterland 				    makedev(ainfo->xmajor, ainfo->xminor)) ||
699*5c51f124SMoriah Waterland #else
700*5c51f124SMoriah Waterland 				    makedev(ainfo->major, ainfo->minor)) ||
701*5c51f124SMoriah Waterland #endif
702*5c51f124SMoriah Waterland 				    (stat(path, &status) < 0)) {
703*5c51f124SMoriah Waterland 					reperr(pkg_gt(ERR_BDEVFAIL));
704*5c51f124SMoriah Waterland 					return (VE_FAIL);
705*5c51f124SMoriah Waterland 				}
706*5c51f124SMoriah Waterland 			} else if (*ftype == 'p') {
707*5c51f124SMoriah Waterland 				if (mknod(path, ainfo->mode | S_IFIFO, NULL) ||
708*5c51f124SMoriah Waterland 				    (stat(path, &status) < 0)) {
709*5c51f124SMoriah Waterland 					reperr(pkg_gt(ERR_PIPEFAIL));
710*5c51f124SMoriah Waterland 					return (VE_FAIL);
711*5c51f124SMoriah Waterland 				}
712*5c51f124SMoriah Waterland 			} else
713*5c51f124SMoriah Waterland 				return (retcode);
714*5c51f124SMoriah Waterland 
715*5c51f124SMoriah Waterland 		} else
716*5c51f124SMoriah Waterland 			return (retcode);
717*5c51f124SMoriah Waterland 	}
718*5c51f124SMoriah Waterland 
719*5c51f124SMoriah Waterland 	if (*ftype == 's')
720*5c51f124SMoriah Waterland 		return (0); /* don't check anything else */
721*5c51f124SMoriah Waterland 	if (*ftype == 'i')
722*5c51f124SMoriah Waterland 		return (0); /* don't check anything else */
723*5c51f124SMoriah Waterland 
724*5c51f124SMoriah Waterland 	retcode = 0;
725*5c51f124SMoriah Waterland 	if ((myftype == 'c') || (myftype == 'b')) {
726*5c51f124SMoriah Waterland #ifdef SUNOS41
727*5c51f124SMoriah Waterland 		if (setval || (ainfo->xmajor < 0))
728*5c51f124SMoriah Waterland 			ainfo->xmajor = ((status.st_rdev>>8)&0377);
729*5c51f124SMoriah Waterland 		if (setval || (ainfo->xminor < 0))
730*5c51f124SMoriah Waterland 			ainfo->xminor = (status.st_rdev&0377);
731*5c51f124SMoriah Waterland 		/* check major & minor */
732*5c51f124SMoriah Waterland 		if (status.st_rdev != makedev(ainfo->xmajor, ainfo->xminor)) {
733*5c51f124SMoriah Waterland 			reperr(pkg_gt(ERR_MAJMIN), ainfo->xmajor,
734*5c51f124SMoriah Waterland 			    ainfo->xminor,
735*5c51f124SMoriah Waterland 				(status.st_rdev>>8)&0377, status.st_rdev&0377);
736*5c51f124SMoriah Waterland 			retcode = VE_CONT;
737*5c51f124SMoriah Waterland 		}
738*5c51f124SMoriah Waterland #else
739*5c51f124SMoriah Waterland 		if (setval || (ainfo->major == BADMAJOR))
740*5c51f124SMoriah Waterland 			ainfo->major = major(status.st_rdev);
741*5c51f124SMoriah Waterland 		if (setval || (ainfo->minor == BADMINOR))
742*5c51f124SMoriah Waterland 			ainfo->minor = minor(status.st_rdev);
743*5c51f124SMoriah Waterland 		/* check major & minor */
744*5c51f124SMoriah Waterland 		if (status.st_rdev != makedev(ainfo->major, ainfo->minor)) {
745*5c51f124SMoriah Waterland 			reperr(pkg_gt(ERR_MAJMIN), ainfo->major, ainfo->minor,
746*5c51f124SMoriah Waterland 			    major(status.st_rdev), minor(status.st_rdev));
747*5c51f124SMoriah Waterland 			retcode = VE_CONT;
748*5c51f124SMoriah Waterland 		}
749*5c51f124SMoriah Waterland #endif
750*5c51f124SMoriah Waterland 	}
751*5c51f124SMoriah Waterland 
752*5c51f124SMoriah Waterland 	/* compare specified mode w/ actual mode excluding sticky bit */
753*5c51f124SMoriah Waterland 	if (setval || (ainfo->mode == BADMODE) || (ainfo->mode == WILDCARD))
754*5c51f124SMoriah Waterland 		ainfo->mode = status.st_mode & 07777;
755*5c51f124SMoriah Waterland 	else if ((ainfo->mode & 06777) != (status.st_mode & 06777)) {
756*5c51f124SMoriah Waterland 		if (fix) {
757*5c51f124SMoriah Waterland 			if ((ainfo->mode == BADMODE) ||
758*5c51f124SMoriah Waterland 			    (chmod(path, ainfo->mode) < 0))
759*5c51f124SMoriah Waterland 				retcode = VE_FAIL;
760*5c51f124SMoriah Waterland 		} else {
761*5c51f124SMoriah Waterland 			reperr(pkg_gt(ERR_PERM), ainfo->mode,
762*5c51f124SMoriah Waterland 				status.st_mode & 07777);
763*5c51f124SMoriah Waterland 			if (!retcode)
764*5c51f124SMoriah Waterland 				retcode = VE_ATTR;
765*5c51f124SMoriah Waterland 		}
766*5c51f124SMoriah Waterland 	}
767*5c51f124SMoriah Waterland 
768*5c51f124SMoriah Waterland 	dochown = 0;
769*5c51f124SMoriah Waterland 
770*5c51f124SMoriah Waterland 	/* get group entry for specified group */
771*5c51f124SMoriah Waterland 	if (setval || strcmp(ainfo->group, BADGROUP) == 0) {
772*5c51f124SMoriah Waterland 		grp = cgrgid(status.st_gid);
773*5c51f124SMoriah Waterland 		if (grp)
774*5c51f124SMoriah Waterland 			(void) strcpy(ainfo->group, grp->gr_name);
775*5c51f124SMoriah Waterland 		else {
776*5c51f124SMoriah Waterland 			if (!retcode)
777*5c51f124SMoriah Waterland 				retcode = VE_ATTR;
778*5c51f124SMoriah Waterland 			reperr(pkg_gt(ERR_BADGRPID), status.st_gid);
779*5c51f124SMoriah Waterland 		}
780*5c51f124SMoriah Waterland 		gid = status.st_gid;
781*5c51f124SMoriah Waterland 	} else if ((grp = cgrnam(ainfo->group)) == NULL) {
782*5c51f124SMoriah Waterland 		reperr(pkg_gt(ERR_BADGRPNM), ainfo->group);
783*5c51f124SMoriah Waterland 		if (!retcode)
784*5c51f124SMoriah Waterland 			retcode = VE_ATTR;
785*5c51f124SMoriah Waterland 	} else if ((gid = grp->gr_gid) != status.st_gid) {
786*5c51f124SMoriah Waterland 		if (fix) {
787*5c51f124SMoriah Waterland 			/* save specified GID */
788*5c51f124SMoriah Waterland 			gid = grp->gr_gid;
789*5c51f124SMoriah Waterland 			dochown++;
790*5c51f124SMoriah Waterland 		} else {
791*5c51f124SMoriah Waterland 			if ((grp = cgrgid((int)status.st_gid)) ==
792*5c51f124SMoriah Waterland 			    (struct group *)NULL) {
793*5c51f124SMoriah Waterland 				reperr(pkg_gt(ERR_GROUP), ainfo->group,
794*5c51f124SMoriah Waterland 				    "(null)");
795*5c51f124SMoriah Waterland 			} else {
796*5c51f124SMoriah Waterland 				reperr(pkg_gt(ERR_GROUP), ainfo->group,
797*5c51f124SMoriah Waterland 				    grp->gr_name);
798*5c51f124SMoriah Waterland 			}
799*5c51f124SMoriah Waterland 			if (!retcode)
800*5c51f124SMoriah Waterland 				retcode = VE_ATTR;
801*5c51f124SMoriah Waterland 		}
802*5c51f124SMoriah Waterland 	}
803*5c51f124SMoriah Waterland 
804*5c51f124SMoriah Waterland 	/* get password entry for specified owner */
805*5c51f124SMoriah Waterland 	if (setval || strcmp(ainfo->owner, BADOWNER) == 0) {
806*5c51f124SMoriah Waterland 		pwd = cpwuid((int)status.st_uid);
807*5c51f124SMoriah Waterland 		if (pwd)
808*5c51f124SMoriah Waterland 			(void) strcpy(ainfo->owner, pwd->pw_name);
809*5c51f124SMoriah Waterland 		else {
810*5c51f124SMoriah Waterland 			if (!retcode)
811*5c51f124SMoriah Waterland 				retcode = VE_ATTR;
812*5c51f124SMoriah Waterland 			reperr(pkg_gt(ERR_BADUSRID), status.st_uid);
813*5c51f124SMoriah Waterland 		}
814*5c51f124SMoriah Waterland 		uid = status.st_uid;
815*5c51f124SMoriah Waterland 	} else if ((pwd = cpwnam(ainfo->owner)) == NULL) {
816*5c51f124SMoriah Waterland 		/* UID does not exist in password file */
817*5c51f124SMoriah Waterland 		reperr(pkg_gt(ERR_BADUSRNM), ainfo->owner);
818*5c51f124SMoriah Waterland 		if (!retcode)
819*5c51f124SMoriah Waterland 			retcode = VE_ATTR;
820*5c51f124SMoriah Waterland 	} else if ((uid = pwd->pw_uid) != status.st_uid) {
821*5c51f124SMoriah Waterland 		/* get owner name for actual UID */
822*5c51f124SMoriah Waterland 		if (fix) {
823*5c51f124SMoriah Waterland 			uid = pwd->pw_uid;
824*5c51f124SMoriah Waterland 			dochown++;
825*5c51f124SMoriah Waterland 		} else {
826*5c51f124SMoriah Waterland 			pwd = cpwuid((int)status.st_uid);
827*5c51f124SMoriah Waterland 			if (pwd == NULL)
828*5c51f124SMoriah Waterland 				reperr(pkg_gt(ERR_BADUSRID),
829*5c51f124SMoriah Waterland 				    (int)status.st_uid);
830*5c51f124SMoriah Waterland 			else
831*5c51f124SMoriah Waterland 				reperr(pkg_gt(ERR_OWNER), ainfo->owner,
832*5c51f124SMoriah Waterland 				    pwd->pw_name);
833*5c51f124SMoriah Waterland 
834*5c51f124SMoriah Waterland 			if (!retcode)
835*5c51f124SMoriah Waterland 				retcode = VE_ATTR;
836*5c51f124SMoriah Waterland 		}
837*5c51f124SMoriah Waterland 	}
838*5c51f124SMoriah Waterland 
839*5c51f124SMoriah Waterland 	if (statvfs(path, &vfsstatus) < 0) {
840*5c51f124SMoriah Waterland 		reperr(pkg_gt(ERR_EXIST));
841*5c51f124SMoriah Waterland 		retcode = VE_FAIL;
842*5c51f124SMoriah Waterland 	} else {
843*5c51f124SMoriah Waterland 		if (dochown) {
844*5c51f124SMoriah Waterland 			/* pcfs doesn't support file ownership */
845*5c51f124SMoriah Waterland 			if (strcmp(vfsstatus.f_basetype, "pcfs") != 0 &&
846*5c51f124SMoriah Waterland 			    chown(path, uid, gid) < 0) {
847*5c51f124SMoriah Waterland 				retcode = VE_FAIL; /* chown failed */
848*5c51f124SMoriah Waterland 			}
849*5c51f124SMoriah Waterland 		}
850*5c51f124SMoriah Waterland 	}
851*5c51f124SMoriah Waterland 
852*5c51f124SMoriah Waterland 	if (retcode == VE_FAIL)
853*5c51f124SMoriah Waterland 		reperr(pkg_gt(ERR_ATTRFAIL));
854*5c51f124SMoriah Waterland 	return (retcode);
855*5c51f124SMoriah Waterland }
856*5c51f124SMoriah Waterland 
857*5c51f124SMoriah Waterland /*
858*5c51f124SMoriah Waterland  * This is a special fast verify which basically checks the attributes
859*5c51f124SMoriah Waterland  * and then, if all is OK, checks the size and mod time using the same
860*5c51f124SMoriah Waterland  * stat and statvfs structures.
861*5c51f124SMoriah Waterland  */
862*5c51f124SMoriah Waterland int
863*5c51f124SMoriah Waterland fverify(int fix, char *ftype, char *path, struct ainfo *ainfo,
864*5c51f124SMoriah Waterland     struct cinfo *cinfo)
865*5c51f124SMoriah Waterland {
866*5c51f124SMoriah Waterland 	int retval;
867*5c51f124SMoriah Waterland 
868*5c51f124SMoriah Waterland 	/* return success if attribute checks are disabled */
869*5c51f124SMoriah Waterland 
870*5c51f124SMoriah Waterland 	if (get_disable_attribute_check()) {
871*5c51f124SMoriah Waterland 		return (0);
872*5c51f124SMoriah Waterland 	}
873*5c51f124SMoriah Waterland 
874*5c51f124SMoriah Waterland 	if ((retval = averify(fix, ftype, path, ainfo)) == 0) {
875*5c51f124SMoriah Waterland 		if (*ftype == 'f' || *ftype == 'i') {
876*5c51f124SMoriah Waterland 			if (cinfo->size != status.st_size) {
877*5c51f124SMoriah Waterland 				reperr(pkg_gt(WRN_QV_SIZE), path);
878*5c51f124SMoriah Waterland 				retval = VE_CONT;
879*5c51f124SMoriah Waterland 			}
880*5c51f124SMoriah Waterland 			/* pcfs doesn't support modification times */
881*5c51f124SMoriah Waterland 			if (strcmp(vfsstatus.f_basetype, "pcfs") != 0) {
882*5c51f124SMoriah Waterland 				if (cinfo->modtime != status.st_mtime) {
883*5c51f124SMoriah Waterland 					reperr(pkg_gt(WRN_QV_MTIME), path);
884*5c51f124SMoriah Waterland 					retval = VE_CONT;
885*5c51f124SMoriah Waterland 				}
886*5c51f124SMoriah Waterland 			}
887*5c51f124SMoriah Waterland 		}
888*5c51f124SMoriah Waterland 	}
889*5c51f124SMoriah Waterland 
890*5c51f124SMoriah Waterland 	return (retval);
891*5c51f124SMoriah Waterland }
892*5c51f124SMoriah Waterland 
893*5c51f124SMoriah Waterland /*
894*5c51f124SMoriah Waterland  * This function determines whether or not non-ABI symlinks are supported.
895*5c51f124SMoriah Waterland  */
896*5c51f124SMoriah Waterland 
897*5c51f124SMoriah Waterland int
898*5c51f124SMoriah Waterland nonABI_symlinks(void)
899*5c51f124SMoriah Waterland {
900*5c51f124SMoriah Waterland 	return (nonabi_symlinks);
901*5c51f124SMoriah Waterland }
902*5c51f124SMoriah Waterland 
903*5c51f124SMoriah Waterland void
904*5c51f124SMoriah Waterland set_nonABI_symlinks(void)
905*5c51f124SMoriah Waterland {
906*5c51f124SMoriah Waterland 	nonabi_symlinks	= 1;
907*5c51f124SMoriah Waterland }
908*5c51f124SMoriah Waterland 
909*5c51f124SMoriah Waterland /*
910*5c51f124SMoriah Waterland  * Disable attribute checking. Only disable attribute checking if files
911*5c51f124SMoriah Waterland  * are guaranteed to exist in the FS.
912*5c51f124SMoriah Waterland  */
913*5c51f124SMoriah Waterland void
914*5c51f124SMoriah Waterland disable_attribute_check(void)
915*5c51f124SMoriah Waterland {
916*5c51f124SMoriah Waterland 	disable_attributes = 1;
917*5c51f124SMoriah Waterland }
918*5c51f124SMoriah Waterland 
919*5c51f124SMoriah Waterland /*
920*5c51f124SMoriah Waterland  * This function determines whether or not to do attribute checking.
921*5c51f124SMoriah Waterland  * Returns:  0 - Do attribute checking
922*5c51f124SMoriah Waterland  *          !0 - Don't do attribute checking
923*5c51f124SMoriah Waterland  */
924*5c51f124SMoriah Waterland int
925*5c51f124SMoriah Waterland get_disable_attribute_check(void)
926*5c51f124SMoriah Waterland {
927*5c51f124SMoriah Waterland 	return (disable_attributes);
928*5c51f124SMoriah Waterland }
929*5c51f124SMoriah Waterland 
930*5c51f124SMoriah Waterland /*
931*5c51f124SMoriah Waterland  * This function returns the address of the "global" error buffer that
932*5c51f124SMoriah Waterland  * is populated by the various functions in this module.
933*5c51f124SMoriah Waterland  */
934*5c51f124SMoriah Waterland 
935*5c51f124SMoriah Waterland char *
936*5c51f124SMoriah Waterland getErrbufAddr(void)
937*5c51f124SMoriah Waterland {
938*5c51f124SMoriah Waterland 	return (theErrBuf);
939*5c51f124SMoriah Waterland }
940*5c51f124SMoriah Waterland 
941*5c51f124SMoriah Waterland /*
942*5c51f124SMoriah Waterland  * This function returns the size of the buffer returned by getErrbufAddr()
943*5c51f124SMoriah Waterland  */
944*5c51f124SMoriah Waterland 
945*5c51f124SMoriah Waterland int
946*5c51f124SMoriah Waterland getErrbufSize(void)
947*5c51f124SMoriah Waterland {
948*5c51f124SMoriah Waterland 	return (sizeof (theErrBuf));
949*5c51f124SMoriah Waterland }
950*5c51f124SMoriah Waterland 
951*5c51f124SMoriah Waterland /*
952*5c51f124SMoriah Waterland  * This function returns the current global "error string"
953*5c51f124SMoriah Waterland  */
954*5c51f124SMoriah Waterland 
955*5c51f124SMoriah Waterland char *
956*5c51f124SMoriah Waterland getErrstr(void)
957*5c51f124SMoriah Waterland {
958*5c51f124SMoriah Waterland 	return (theErrStr);
959*5c51f124SMoriah Waterland }
960*5c51f124SMoriah Waterland 
961*5c51f124SMoriah Waterland /*
962*5c51f124SMoriah Waterland  * This function sets the global "error string"
963*5c51f124SMoriah Waterland  */
964*5c51f124SMoriah Waterland 
965*5c51f124SMoriah Waterland void
966*5c51f124SMoriah Waterland setErrstr(char *a_errstr)
967*5c51f124SMoriah Waterland {
968*5c51f124SMoriah Waterland 	theErrStr = a_errstr;
969*5c51f124SMoriah Waterland }
970*5c51f124SMoriah Waterland 
971*5c51f124SMoriah Waterland /*
972*5c51f124SMoriah Waterland  * This function enables checksumming
973*5c51f124SMoriah Waterland  */
974*5c51f124SMoriah Waterland 
975*5c51f124SMoriah Waterland void
976*5c51f124SMoriah Waterland checksum_on(void)
977*5c51f124SMoriah Waterland {
978*5c51f124SMoriah Waterland 	enable_checksum = 1;
979*5c51f124SMoriah Waterland }
980*5c51f124SMoriah Waterland 
981*5c51f124SMoriah Waterland /*
982*5c51f124SMoriah Waterland  * This function disables checksumming
983*5c51f124SMoriah Waterland  */
984*5c51f124SMoriah Waterland 
985*5c51f124SMoriah Waterland void
986*5c51f124SMoriah Waterland checksum_off(void)
987*5c51f124SMoriah Waterland {
988*5c51f124SMoriah Waterland 	enable_checksum = 0;
989*5c51f124SMoriah Waterland }
990