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