xref: /titanic_54/usr/src/cmd/svr4pkg/pkgmk/main.c (revision 5c51f1241dbbdf2656d0e10011981411ed0c9673)
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 #include <stdio.h>
32*5c51f124SMoriah Waterland #include <string.h>
33*5c51f124SMoriah Waterland #include <signal.h>
34*5c51f124SMoriah Waterland #include <errno.h>
35*5c51f124SMoriah Waterland #include <malloc.h>
36*5c51f124SMoriah Waterland #include <stdlib.h>
37*5c51f124SMoriah Waterland #include <unistd.h>
38*5c51f124SMoriah Waterland #include <time.h>
39*5c51f124SMoriah Waterland #include <fcntl.h>
40*5c51f124SMoriah Waterland #include <sys/types.h>
41*5c51f124SMoriah Waterland #include <sys/stat.h>
42*5c51f124SMoriah Waterland #include <sys/param.h>
43*5c51f124SMoriah Waterland #include <ctype.h>
44*5c51f124SMoriah Waterland #include <sys/mman.h>
45*5c51f124SMoriah Waterland #include <sys/sysmacros.h>
46*5c51f124SMoriah Waterland #include <strings.h>
47*5c51f124SMoriah Waterland #include <pkgstrct.h>
48*5c51f124SMoriah Waterland #include <pkgdev.h>
49*5c51f124SMoriah Waterland #include <pkginfo.h>
50*5c51f124SMoriah Waterland #include <pkglocs.h>
51*5c51f124SMoriah Waterland #include <locale.h>
52*5c51f124SMoriah Waterland #include <libintl.h>
53*5c51f124SMoriah Waterland #include <sys/statvfs.h>
54*5c51f124SMoriah Waterland #include <sys/utsname.h>
55*5c51f124SMoriah Waterland #include <instzones_api.h>
56*5c51f124SMoriah Waterland #include <pkglib.h>
57*5c51f124SMoriah Waterland #include <libadm.h>
58*5c51f124SMoriah Waterland #include <libinst.h>
59*5c51f124SMoriah Waterland 
60*5c51f124SMoriah Waterland extern char	**environ, *pkgdir;
61*5c51f124SMoriah Waterland 
62*5c51f124SMoriah Waterland /* mkpkgmap.c */
63*5c51f124SMoriah Waterland extern int	mkpkgmap(char *outfile, char *protofile, char **cmdparam);
64*5c51f124SMoriah Waterland /* splpkgmap.c */
65*5c51f124SMoriah Waterland extern int	splpkgmap(struct cfent **eptlist, unsigned int eptnum,
66*5c51f124SMoriah Waterland     char *order[], ulong_t bsize, ulong_t frsize, fsblkcnt_t *plimit,
67*5c51f124SMoriah Waterland     fsfilcnt_t *pilimit, fsblkcnt_t *pllimit);
68*5c51f124SMoriah Waterland /* scriptvfy.c */
69*5c51f124SMoriah Waterland extern int	checkscripts(char *inst_dir, int silent);
70*5c51f124SMoriah Waterland 
71*5c51f124SMoriah Waterland /* libpkg/gpkgmap.c */
72*5c51f124SMoriah Waterland extern void	setmapmode(int mode_no);
73*5c51f124SMoriah Waterland 
74*5c51f124SMoriah Waterland static boolean_t valid_zone_attr(struct cfent **eptlist);
75*5c51f124SMoriah Waterland 
76*5c51f124SMoriah Waterland #define	MALSIZ	16
77*5c51f124SMoriah Waterland #define	NROOT	8
78*5c51f124SMoriah Waterland #define	SPOOLDEV	"spool"
79*5c51f124SMoriah Waterland 
80*5c51f124SMoriah Waterland #define	MSG_PROTOTYPE	"## Building pkgmap from package prototype file.\n"
81*5c51f124SMoriah Waterland #define	MSG_PKGINFO	"## Processing pkginfo file.\n"
82*5c51f124SMoriah Waterland #define	MSG_VOLUMIZE	"## Attempting to volumize %d entries in pkgmap.\n"
83*5c51f124SMoriah Waterland #define	MSG_PACKAGE1	"## Packaging one part.\n"
84*5c51f124SMoriah Waterland #define	MSG_PACKAGEM	"## Packaging %d parts.\n"
85*5c51f124SMoriah Waterland #define	MSG_VALSCRIPTS	"## Validating control scripts.\n"
86*5c51f124SMoriah Waterland 
87*5c51f124SMoriah Waterland /* Other problems */
88*5c51f124SMoriah Waterland #define	ERR_MEMORY	"memory allocation failure, errno=%d"
89*5c51f124SMoriah Waterland #define	ERR_NROOT	"too many paths listed with -r option, limit is %d"
90*5c51f124SMoriah Waterland #define	ERR_PKGINST	"invalid package instance identifier <%s>"
91*5c51f124SMoriah Waterland #define	ERR_PKGABRV	"invalid package abbreviation <%s>"
92*5c51f124SMoriah Waterland #define	ERR_BADDEV	"unknown or invalid device specified <%s>"
93*5c51f124SMoriah Waterland #define	ERR_TEMP	"unable to obtain temporary file resources, errno=%d"
94*5c51f124SMoriah Waterland #define	ERR_DSTREAM	"invalid device specified (datastream) <%s>"
95*5c51f124SMoriah Waterland #define	ERR_SPLIT	"unable to volumize package"
96*5c51f124SMoriah Waterland #define	ERR_MKDIR	"unable to make directory <%s>"
97*5c51f124SMoriah Waterland #define	ERR_SYMLINK	"unable to create symbolic link for <%s>"
98*5c51f124SMoriah Waterland #define	ERR_OVERWRITE	"must use -o option to overwrite <%s>"
99*5c51f124SMoriah Waterland #define	ERR_UMOUNT	"unable to unmount device <%s>"
100*5c51f124SMoriah Waterland #define	ERR_NOPKGINFO	"required pkginfo file is not specified in prototype " \
101*5c51f124SMoriah Waterland 			"file"
102*5c51f124SMoriah Waterland #define	ERR_RDPKGINFO	"unable to process pkginfo file <%s>"
103*5c51f124SMoriah Waterland #define	ERR_PROTOTYPE	"unable to locate prototype file"
104*5c51f124SMoriah Waterland #define	ERR_STATVFS	"unable to stat filesystem <%s>"
105*5c51f124SMoriah Waterland #define	ERR_WHATVFS	"unable to determine or access output filesystem for " \
106*5c51f124SMoriah Waterland 			"device <%s>"
107*5c51f124SMoriah Waterland #define	ERR_DEVICE	"unable to find info for device <%s>"
108*5c51f124SMoriah Waterland #define	ERR_BUILD	"unable to build pkgmap from prototype file"
109*5c51f124SMoriah Waterland #define	ERR_ONEVOL	"other packages found - package must fit on a single " \
110*5c51f124SMoriah Waterland 			"volume"
111*5c51f124SMoriah Waterland #define	ERR_NOPARAM	"parameter <%s> is not defined in <%s>"
112*5c51f124SMoriah Waterland #define	ERR_PKGMTCH	"PKG parameter <%s> does not match instance <%s>"
113*5c51f124SMoriah Waterland #define	ERR_NO_PKG_INFOFILE	"unable to open pkginfo file <%s>: %s"
114*5c51f124SMoriah Waterland #define	ERR_ALLZONES_AND_THISZONE	"The package <%s> has <%s> = true " \
115*5c51f124SMoriah Waterland 					"and <%s> = true: the package may " \
116*5c51f124SMoriah Waterland 					"set either parameter to true, but " \
117*5c51f124SMoriah Waterland 					"may not set both parameters to " \
118*5c51f124SMoriah Waterland 					"true. NOTE: if the package " \
119*5c51f124SMoriah Waterland 					"contains a request script, it is " \
120*5c51f124SMoriah Waterland 					"treated as though it has " \
121*5c51f124SMoriah Waterland 					"<SUNW_PKG_THISZONE> = true"
122*5c51f124SMoriah Waterland #define	ERR_NO_ALLZONES_AND_HOLLOW	"The package <%s> has <%s> = false " \
123*5c51f124SMoriah Waterland 					"and <%s> = true: a hollow package " \
124*5c51f124SMoriah Waterland 					"must also be set to install in all " \
125*5c51f124SMoriah Waterland 					"zones"
126*5c51f124SMoriah Waterland #define	ERR_PKGINFO_INVALID_OPTION_COMB	"Invalid combinations of zone " \
127*5c51f124SMoriah Waterland 					"parameters in pkginfo file"
128*5c51f124SMoriah Waterland 
129*5c51f124SMoriah Waterland #define	ERR_USAGE	"usage: %s [options] [VAR=value [VAR=value]] " \
130*5c51f124SMoriah Waterland 			"[pkginst]\n" \
131*5c51f124SMoriah Waterland 			"   where options may include:\n" \
132*5c51f124SMoriah Waterland 			"\t-o\n" \
133*5c51f124SMoriah Waterland 			"\t-a arch\n" \
134*5c51f124SMoriah Waterland 			"\t-v version\n" \
135*5c51f124SMoriah Waterland 			"\t-p pstamp\n" \
136*5c51f124SMoriah Waterland 			"\t-l limit\n" \
137*5c51f124SMoriah Waterland 			"\t-r rootpath\n" \
138*5c51f124SMoriah Waterland 			"\t-b basedir\n" \
139*5c51f124SMoriah Waterland 			"\t-d device\n" \
140*5c51f124SMoriah Waterland 			"\t-f protofile\n"
141*5c51f124SMoriah Waterland #define	WRN_MISSINGDIR	"WARNING: missing directory entry for <%s>"
142*5c51f124SMoriah Waterland #define	WRN_SETPARAM	"WARNING: parameter <%s> set to \"%s\""
143*5c51f124SMoriah Waterland #define	WRN_CLASSES	"WARNING: unreferenced class <%s> in prototype file"
144*5c51f124SMoriah Waterland 
145*5c51f124SMoriah Waterland #define	LINK    1
146*5c51f124SMoriah Waterland 
147*5c51f124SMoriah Waterland struct pkgdev pkgdev; 	/* holds info about the installation device */
148*5c51f124SMoriah Waterland int	started;
149*5c51f124SMoriah Waterland char	pkgloc[PATH_MAX];
150*5c51f124SMoriah Waterland char	*basedir;
151*5c51f124SMoriah Waterland char	*root;
152*5c51f124SMoriah Waterland char	*rootlist[NROOT];
153*5c51f124SMoriah Waterland char	*t_pkgmap;
154*5c51f124SMoriah Waterland char	*t_pkginfo;
155*5c51f124SMoriah Waterland 
156*5c51f124SMoriah Waterland static struct cfent *svept;
157*5c51f124SMoriah Waterland static char	*protofile,
158*5c51f124SMoriah Waterland 		*device;
159*5c51f124SMoriah Waterland static fsblkcnt_t limit = 0;
160*5c51f124SMoriah Waterland static fsblkcnt_t llimit = 0;
161*5c51f124SMoriah Waterland static fsfilcnt_t ilimit = 0;
162*5c51f124SMoriah Waterland static int	overwrite,
163*5c51f124SMoriah Waterland 		nflag,
164*5c51f124SMoriah Waterland 		sflag;
165*5c51f124SMoriah Waterland static void	ckmissing(char *path, char type);
166*5c51f124SMoriah Waterland static void	outvol(struct cfent **eptlist, unsigned int eptnum, int part,
167*5c51f124SMoriah Waterland 			int nparts);
168*5c51f124SMoriah Waterland static void	trap(int n);
169*5c51f124SMoriah Waterland static void	usage(void);
170*5c51f124SMoriah Waterland 
171*5c51f124SMoriah Waterland static int	slinkf(char *from, char *to);
172*5c51f124SMoriah Waterland 
173*5c51f124SMoriah Waterland int
174*5c51f124SMoriah Waterland main(int argc, char *argv[])
175*5c51f124SMoriah Waterland {
176*5c51f124SMoriah Waterland 	struct utsname utsbuf;
177*5c51f124SMoriah Waterland 	struct statvfs64 svfsb;
178*5c51f124SMoriah Waterland 	struct cfent	**eptlist;
179*5c51f124SMoriah Waterland 	FILE	*fp;
180*5c51f124SMoriah Waterland 	VFP_T	*vfp;
181*5c51f124SMoriah Waterland 	int	c, n, found;
182*5c51f124SMoriah Waterland 	int	part, nparts, npkgs, objects;
183*5c51f124SMoriah Waterland 	char	buf[MAX_PKG_PARAM_LENGTH];
184*5c51f124SMoriah Waterland 	char	temp[MAX_PKG_PARAM_LENGTH];
185*5c51f124SMoriah Waterland 	char	param[MAX_PKG_PARAM_LENGTH];
186*5c51f124SMoriah Waterland 	char	*pt, *value, *pkginst, *tmpdir, *abi_sym_ptr,
187*5c51f124SMoriah Waterland 		**cmdparam;
188*5c51f124SMoriah Waterland 	char	*pkgname;
189*5c51f124SMoriah Waterland 	char	*pkgvers;
190*5c51f124SMoriah Waterland 	char	*pkgarch;
191*5c51f124SMoriah Waterland 	char	*pkgcat;
192*5c51f124SMoriah Waterland 	void	(*func)();
193*5c51f124SMoriah Waterland 	time_t	clock;
194*5c51f124SMoriah Waterland 	ulong_t	bsize = 0;
195*5c51f124SMoriah Waterland 	ulong_t	frsize = 0;
196*5c51f124SMoriah Waterland 	struct cl_attr	**allclass = NULL;
197*5c51f124SMoriah Waterland 	struct cl_attr	**order;
198*5c51f124SMoriah Waterland 	unsigned int eptnum, i;
199*5c51f124SMoriah Waterland 
200*5c51f124SMoriah Waterland 	/* initialize locale environment */
201*5c51f124SMoriah Waterland 
202*5c51f124SMoriah Waterland 	(void) setlocale(LC_ALL, "");
203*5c51f124SMoriah Waterland 
204*5c51f124SMoriah Waterland #if !defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
205*5c51f124SMoriah Waterland #define	TEXT_DOMAIN "SYS_TEST"
206*5c51f124SMoriah Waterland #endif
207*5c51f124SMoriah Waterland 	(void) textdomain(TEXT_DOMAIN);
208*5c51f124SMoriah Waterland 
209*5c51f124SMoriah Waterland 	/* initialize program name */
210*5c51f124SMoriah Waterland 
211*5c51f124SMoriah Waterland 	(void) set_prog_name(argv[0]);
212*5c51f124SMoriah Waterland 
213*5c51f124SMoriah Waterland 	/* tell spmi zones interface how to access package output functions */
214*5c51f124SMoriah Waterland 
215*5c51f124SMoriah Waterland 	z_set_output_functions(echo, echoDebug, progerr);
216*5c51f124SMoriah Waterland 
217*5c51f124SMoriah Waterland 	func = sigset(SIGINT, trap);
218*5c51f124SMoriah Waterland 	if (func != SIG_DFL)
219*5c51f124SMoriah Waterland 		func = sigset(SIGINT, func);
220*5c51f124SMoriah Waterland 	func = sigset(SIGHUP, trap);
221*5c51f124SMoriah Waterland 	setmapmode(MAPBUILD);	/* variable binding */
222*5c51f124SMoriah Waterland 	if (func != SIG_DFL)
223*5c51f124SMoriah Waterland 		func = sigset(SIGHUP, func);
224*5c51f124SMoriah Waterland 
225*5c51f124SMoriah Waterland 	environ = NULL;
226*5c51f124SMoriah Waterland 	while ((c = getopt(argc, argv, "osnp:l:r:b:d:f:a:v:?")) != EOF) {
227*5c51f124SMoriah Waterland 		switch (c) {
228*5c51f124SMoriah Waterland 		    case 'n':
229*5c51f124SMoriah Waterland 			nflag++;
230*5c51f124SMoriah Waterland 			break;
231*5c51f124SMoriah Waterland 
232*5c51f124SMoriah Waterland 		    case 's':
233*5c51f124SMoriah Waterland 			sflag++;
234*5c51f124SMoriah Waterland 			break;
235*5c51f124SMoriah Waterland 
236*5c51f124SMoriah Waterland 		    case 'o':
237*5c51f124SMoriah Waterland 			overwrite++;
238*5c51f124SMoriah Waterland 			break;
239*5c51f124SMoriah Waterland 
240*5c51f124SMoriah Waterland 		    case 'p':
241*5c51f124SMoriah Waterland 			putparam("PSTAMP", optarg);
242*5c51f124SMoriah Waterland 			break;
243*5c51f124SMoriah Waterland 
244*5c51f124SMoriah Waterland 		    case 'l':
245*5c51f124SMoriah Waterland 			llimit = strtoull(optarg, NULL, 10);
246*5c51f124SMoriah Waterland 			break;
247*5c51f124SMoriah Waterland 
248*5c51f124SMoriah Waterland 		    case 'r':
249*5c51f124SMoriah Waterland 			pt = strtok(optarg, " \t\n, ");
250*5c51f124SMoriah Waterland 			n = 0;
251*5c51f124SMoriah Waterland 			do {
252*5c51f124SMoriah Waterland 				rootlist[n++] = flex_device(pt, 0);
253*5c51f124SMoriah Waterland 				if (n >= NROOT) {
254*5c51f124SMoriah Waterland 					progerr(gettext(ERR_NROOT), NROOT);
255*5c51f124SMoriah Waterland 					quit(1);
256*5c51f124SMoriah Waterland 				}
257*5c51f124SMoriah Waterland 			} while (pt = strtok(NULL, " \t\n, "));
258*5c51f124SMoriah Waterland 			rootlist[n] = NULL;
259*5c51f124SMoriah Waterland 			break;
260*5c51f124SMoriah Waterland 
261*5c51f124SMoriah Waterland 		    case 'b':
262*5c51f124SMoriah Waterland 			basedir = optarg;
263*5c51f124SMoriah Waterland 			break;
264*5c51f124SMoriah Waterland 
265*5c51f124SMoriah Waterland 		    case 'f':
266*5c51f124SMoriah Waterland 			protofile = optarg;
267*5c51f124SMoriah Waterland 			break;
268*5c51f124SMoriah Waterland 
269*5c51f124SMoriah Waterland 		    case 'd':
270*5c51f124SMoriah Waterland 			device = flex_device(optarg, 1);
271*5c51f124SMoriah Waterland 			break;
272*5c51f124SMoriah Waterland 
273*5c51f124SMoriah Waterland 		    case 'a':
274*5c51f124SMoriah Waterland 			putparam("ARCH", optarg);
275*5c51f124SMoriah Waterland 			break;
276*5c51f124SMoriah Waterland 
277*5c51f124SMoriah Waterland 		    case 'v':
278*5c51f124SMoriah Waterland 			putparam("VERSION", optarg);
279*5c51f124SMoriah Waterland 			break;
280*5c51f124SMoriah Waterland 
281*5c51f124SMoriah Waterland 		    default:
282*5c51f124SMoriah Waterland 			usage();
283*5c51f124SMoriah Waterland 			/*NOTREACHED*/
284*5c51f124SMoriah Waterland 			/*
285*5c51f124SMoriah Waterland 			 * Although usage() calls a noreturn function,
286*5c51f124SMoriah Waterland 			 * needed to add return (1);  so that main() would
287*5c51f124SMoriah Waterland 			 * pass compilation checks. The statement below
288*5c51f124SMoriah Waterland 			 * should never be executed.
289*5c51f124SMoriah Waterland 			 */
290*5c51f124SMoriah Waterland 			return (1);
291*5c51f124SMoriah Waterland 		}
292*5c51f124SMoriah Waterland 	}
293*5c51f124SMoriah Waterland 
294*5c51f124SMoriah Waterland 	/*
295*5c51f124SMoriah Waterland 	 * Store command line variable assignments for later
296*5c51f124SMoriah Waterland 	 * incorporation into the environment.
297*5c51f124SMoriah Waterland 	 */
298*5c51f124SMoriah Waterland 	cmdparam = &argv[optind];
299*5c51f124SMoriah Waterland 
300*5c51f124SMoriah Waterland 	/* Skip past equates. */
301*5c51f124SMoriah Waterland 	while (argv[optind] && strchr(argv[optind], '='))
302*5c51f124SMoriah Waterland 		optind++;
303*5c51f124SMoriah Waterland 
304*5c51f124SMoriah Waterland 	/* Confirm that the instance name is valid */
305*5c51f124SMoriah Waterland 	if ((pkginst = argv[optind]) != NULL) {
306*5c51f124SMoriah Waterland 		if (pkgnmchk(pkginst, "all", 0)) {
307*5c51f124SMoriah Waterland 			progerr(gettext(ERR_PKGINST), pkginst);
308*5c51f124SMoriah Waterland 			quit(1);
309*5c51f124SMoriah Waterland 		}
310*5c51f124SMoriah Waterland 		argv[optind++] = NULL;
311*5c51f124SMoriah Waterland 	}
312*5c51f124SMoriah Waterland 	if (optind != argc)
313*5c51f124SMoriah Waterland 		usage();
314*5c51f124SMoriah Waterland 
315*5c51f124SMoriah Waterland 	tmpdir = getenv("TMPDIR");
316*5c51f124SMoriah Waterland 	if (tmpdir == NULL)
317*5c51f124SMoriah Waterland 		tmpdir = P_tmpdir;
318*5c51f124SMoriah Waterland 
319*5c51f124SMoriah Waterland 	/* bug id 4244631, not ABI compliant */
320*5c51f124SMoriah Waterland 	abi_sym_ptr = getenv("PKG_NONABI_SYMLINKS");
321*5c51f124SMoriah Waterland 	if (abi_sym_ptr && (strncasecmp(abi_sym_ptr, "TRUE", 4) == 0)) {
322*5c51f124SMoriah Waterland 		set_nonABI_symlinks();
323*5c51f124SMoriah Waterland 	}
324*5c51f124SMoriah Waterland 
325*5c51f124SMoriah Waterland 	if (device == NULL) {
326*5c51f124SMoriah Waterland 		device = devattr(SPOOLDEV, "pathname");
327*5c51f124SMoriah Waterland 		if (device == NULL) {
328*5c51f124SMoriah Waterland 			progerr(gettext(ERR_DEVICE), SPOOLDEV);
329*5c51f124SMoriah Waterland 			exit(99);
330*5c51f124SMoriah Waterland 		}
331*5c51f124SMoriah Waterland 	}
332*5c51f124SMoriah Waterland 
333*5c51f124SMoriah Waterland 	if (protofile == NULL) {
334*5c51f124SMoriah Waterland 		if (access("prototype", 0) == 0)
335*5c51f124SMoriah Waterland 			protofile = "prototype";
336*5c51f124SMoriah Waterland 		else if (access("Prototype", 0) == 0)
337*5c51f124SMoriah Waterland 			protofile = "Prototype";
338*5c51f124SMoriah Waterland 		else {
339*5c51f124SMoriah Waterland 			progerr(gettext(ERR_PROTOTYPE));
340*5c51f124SMoriah Waterland 			quit(1);
341*5c51f124SMoriah Waterland 		}
342*5c51f124SMoriah Waterland 	}
343*5c51f124SMoriah Waterland 
344*5c51f124SMoriah Waterland 	if (devtype(device, &pkgdev)) {
345*5c51f124SMoriah Waterland 		progerr(gettext(ERR_BADDEV), device);
346*5c51f124SMoriah Waterland 		quit(1);
347*5c51f124SMoriah Waterland 	}
348*5c51f124SMoriah Waterland 	if (pkgdev.norewind) {
349*5c51f124SMoriah Waterland 		/* initialize datastream */
350*5c51f124SMoriah Waterland 		progerr(gettext(ERR_DSTREAM), device);
351*5c51f124SMoriah Waterland 		quit(1);
352*5c51f124SMoriah Waterland 	}
353*5c51f124SMoriah Waterland 	if (pkgdev.mount) {
354*5c51f124SMoriah Waterland 		if (n = pkgmount(&pkgdev, NULL, 0, 0, 1))
355*5c51f124SMoriah Waterland 			quit(n);
356*5c51f124SMoriah Waterland 	}
357*5c51f124SMoriah Waterland 
358*5c51f124SMoriah Waterland 	/*
359*5c51f124SMoriah Waterland 	 * convert prototype file to a pkgmap, while locating
360*5c51f124SMoriah Waterland 	 * package objects in the current environment
361*5c51f124SMoriah Waterland 	 */
362*5c51f124SMoriah Waterland 	t_pkgmap = tempnam(tmpdir, "tmpmap");
363*5c51f124SMoriah Waterland 	if (t_pkgmap == NULL) {
364*5c51f124SMoriah Waterland 		progerr(gettext(ERR_TEMP), errno);
365*5c51f124SMoriah Waterland 		exit(99);
366*5c51f124SMoriah Waterland 	}
367*5c51f124SMoriah Waterland 
368*5c51f124SMoriah Waterland 	(void) fprintf(stderr, gettext(MSG_PROTOTYPE));
369*5c51f124SMoriah Waterland 	if (n = mkpkgmap(t_pkgmap, protofile, cmdparam)) {
370*5c51f124SMoriah Waterland 		progerr(gettext(ERR_BUILD));
371*5c51f124SMoriah Waterland 		quit(1);
372*5c51f124SMoriah Waterland 	}
373*5c51f124SMoriah Waterland 
374*5c51f124SMoriah Waterland 	setmapmode(MAPNONE);	/* All appropriate variables are now bound */
375*5c51f124SMoriah Waterland 
376*5c51f124SMoriah Waterland 	if (vfpOpen(&vfp, t_pkgmap, "r", VFP_NEEDNOW) != 0) {
377*5c51f124SMoriah Waterland 		progerr(gettext(ERR_TEMP), errno);
378*5c51f124SMoriah Waterland 		quit(99);
379*5c51f124SMoriah Waterland 	}
380*5c51f124SMoriah Waterland 
381*5c51f124SMoriah Waterland 	eptlist = procmap(vfp, 0, NULL);
382*5c51f124SMoriah Waterland 
383*5c51f124SMoriah Waterland 	if (eptlist == NULL) {
384*5c51f124SMoriah Waterland 		quit(1);
385*5c51f124SMoriah Waterland 	}
386*5c51f124SMoriah Waterland 
387*5c51f124SMoriah Waterland 	(void) vfpClose(&vfp);
388*5c51f124SMoriah Waterland 
389*5c51f124SMoriah Waterland 	/* Validate the zone attributes in pkginfo, before creation */
390*5c51f124SMoriah Waterland 	if (!valid_zone_attr(eptlist)) {
391*5c51f124SMoriah Waterland 		progerr(ERR_PKGINFO_INVALID_OPTION_COMB);
392*5c51f124SMoriah Waterland 		quit(1);
393*5c51f124SMoriah Waterland 	}
394*5c51f124SMoriah Waterland 
395*5c51f124SMoriah Waterland 	(void) fprintf(stderr, gettext(MSG_PKGINFO));
396*5c51f124SMoriah Waterland 	pt = NULL;
397*5c51f124SMoriah Waterland 	for (i = 0; eptlist[i]; i++) {
398*5c51f124SMoriah Waterland 		ckmissing(eptlist[i]->path, eptlist[i]->ftype);
399*5c51f124SMoriah Waterland 		if (eptlist[i]->ftype != 'i')
400*5c51f124SMoriah Waterland 			continue;
401*5c51f124SMoriah Waterland 		if (strcmp(eptlist[i]->path, "pkginfo") == 0)
402*5c51f124SMoriah Waterland 			svept = eptlist[i];
403*5c51f124SMoriah Waterland 	}
404*5c51f124SMoriah Waterland 	if (svept == NULL) {
405*5c51f124SMoriah Waterland 		progerr(gettext(ERR_NOPKGINFO));
406*5c51f124SMoriah Waterland 		quit(99);
407*5c51f124SMoriah Waterland 	}
408*5c51f124SMoriah Waterland 	eptnum = i;
409*5c51f124SMoriah Waterland 
410*5c51f124SMoriah Waterland 	/*
411*5c51f124SMoriah Waterland 	 * process all parameters from the pkginfo file
412*5c51f124SMoriah Waterland 	 * and place them in the execution environment
413*5c51f124SMoriah Waterland 	 */
414*5c51f124SMoriah Waterland 
415*5c51f124SMoriah Waterland 	if ((fp = fopen(svept->ainfo.local, "r")) == NULL) {
416*5c51f124SMoriah Waterland 		progerr(gettext(ERR_RDPKGINFO), svept->ainfo.local);
417*5c51f124SMoriah Waterland 		quit(99);
418*5c51f124SMoriah Waterland 	}
419*5c51f124SMoriah Waterland 	param[0] = '\0';
420*5c51f124SMoriah Waterland 	while (value = fpkgparam(fp, param)) {
421*5c51f124SMoriah Waterland 		if (getenv(param) == NULL)
422*5c51f124SMoriah Waterland 			putparam(param, value);
423*5c51f124SMoriah Waterland 		free((void *)value);
424*5c51f124SMoriah Waterland 		param[0] = '\0';
425*5c51f124SMoriah Waterland 	}
426*5c51f124SMoriah Waterland 	(void) fclose(fp);
427*5c51f124SMoriah Waterland 
428*5c51f124SMoriah Waterland 	/* add command line variables */
429*5c51f124SMoriah Waterland 	while (*cmdparam && (value = strchr(*cmdparam, '=')) != NULL) {
430*5c51f124SMoriah Waterland 		*value = NULL;	/* terminate the parameter */
431*5c51f124SMoriah Waterland 		value++;	/* value is now the value (not '=') */
432*5c51f124SMoriah Waterland 		putparam(*cmdparam++, value);  /* store it in environ */
433*5c51f124SMoriah Waterland 	}
434*5c51f124SMoriah Waterland 
435*5c51f124SMoriah Waterland 	/* make sure parameters are valid */
436*5c51f124SMoriah Waterland 	(void) time(&clock);
437*5c51f124SMoriah Waterland 	if (pt = getenv("PKG")) {
438*5c51f124SMoriah Waterland 		if (pkgnmchk(pt, NULL, 0) || strchr(pt, '.')) {
439*5c51f124SMoriah Waterland 			progerr(gettext(ERR_PKGABRV), pt);
440*5c51f124SMoriah Waterland 			quit(1);
441*5c51f124SMoriah Waterland 		}
442*5c51f124SMoriah Waterland 		if (pkginst == NULL)
443*5c51f124SMoriah Waterland 			pkginst = pt;
444*5c51f124SMoriah Waterland 	} else {
445*5c51f124SMoriah Waterland 		progerr(gettext(ERR_NOPARAM), "PKG", svept->path);
446*5c51f124SMoriah Waterland 		quit(1);
447*5c51f124SMoriah Waterland 	}
448*5c51f124SMoriah Waterland 	/*
449*5c51f124SMoriah Waterland 	 * verify consistency between PKG parameter and pkginst
450*5c51f124SMoriah Waterland 	 */
451*5c51f124SMoriah Waterland 	(void) snprintf(param, sizeof (param), "%s.*", pt);
452*5c51f124SMoriah Waterland 	if (pkgnmchk(pkginst, param, 0)) {
453*5c51f124SMoriah Waterland 		progerr(gettext(ERR_PKGMTCH), pt, pkginst);
454*5c51f124SMoriah Waterland 		quit(1);
455*5c51f124SMoriah Waterland 	}
456*5c51f124SMoriah Waterland 
457*5c51f124SMoriah Waterland 	/*
458*5c51f124SMoriah Waterland 	 * *********************************************************************
459*5c51f124SMoriah Waterland 	 * this feature is removed starting with Solaris 10 - there is no built
460*5c51f124SMoriah Waterland 	 * in list of packages that should be run "the old way"
461*5c51f124SMoriah Waterland 	 * *********************************************************************
462*5c51f124SMoriah Waterland 	 */
463*5c51f124SMoriah Waterland 
464*5c51f124SMoriah Waterland #ifdef	ALLOW_EXCEPTION_PKG_LIST
465*5c51f124SMoriah Waterland 	/* Until 2.9, set it from the execption list */
466*5c51f124SMoriah Waterland 	if (exception_pkg(pkginst, LINK))
467*5c51f124SMoriah Waterland 		set_nonABI_symlinks();
468*5c51f124SMoriah Waterland #endif
469*5c51f124SMoriah Waterland 
470*5c51f124SMoriah Waterland 	if ((pkgname = getenv("NAME")) == NULL) {
471*5c51f124SMoriah Waterland 		progerr(gettext(ERR_NOPARAM), "NAME", svept->path);
472*5c51f124SMoriah Waterland 		quit(1);
473*5c51f124SMoriah Waterland 	}
474*5c51f124SMoriah Waterland 	if (ckparam("NAME", pkgname))
475*5c51f124SMoriah Waterland 		quit(1);
476*5c51f124SMoriah Waterland 	if ((pkgvers = getenv("VERSION")) == NULL) {
477*5c51f124SMoriah Waterland 		/* XXX - I18n */
478*5c51f124SMoriah Waterland 		/* LINTED do not use cftime(); use strftime instead */
479*5c51f124SMoriah Waterland 		(void) cftime(buf, "\045m/\045d/\045Y", &clock);
480*5c51f124SMoriah Waterland 		(void) snprintf(temp, sizeof (temp),
481*5c51f124SMoriah Waterland 			gettext("Dev Release %s"), buf);
482*5c51f124SMoriah Waterland 		putparam("VERSION", temp);
483*5c51f124SMoriah Waterland 		pkgvers = getenv("VERSION");
484*5c51f124SMoriah Waterland 		logerr(gettext(WRN_SETPARAM), "VERSION", temp);
485*5c51f124SMoriah Waterland 	}
486*5c51f124SMoriah Waterland 	if (ckparam("VERSION", pkgvers))
487*5c51f124SMoriah Waterland 		quit(1);
488*5c51f124SMoriah Waterland 	if ((pkgarch = getenv("ARCH")) == NULL) {
489*5c51f124SMoriah Waterland 		(void) uname(&utsbuf);
490*5c51f124SMoriah Waterland 		putparam("ARCH", utsbuf.machine);
491*5c51f124SMoriah Waterland 		pkgarch = getenv("ARCH");
492*5c51f124SMoriah Waterland 		logerr(gettext(WRN_SETPARAM), "ARCH", utsbuf.machine);
493*5c51f124SMoriah Waterland 	}
494*5c51f124SMoriah Waterland 	if (ckparam("ARCH", pkgarch))
495*5c51f124SMoriah Waterland 		quit(1);
496*5c51f124SMoriah Waterland 	if (getenv("PSTAMP") == NULL) {
497*5c51f124SMoriah Waterland 		/* use octal value of '%' to fight sccs expansion */
498*5c51f124SMoriah Waterland 		/* XXX - I18n */
499*5c51f124SMoriah Waterland 		/* LINTED do not use cftime(); use strftime instead */
500*5c51f124SMoriah Waterland 		(void) cftime(buf, "\045Y\045m\045d\045H\045M\045S", &clock);
501*5c51f124SMoriah Waterland 		(void) uname(&utsbuf);
502*5c51f124SMoriah Waterland 		(void) snprintf(temp, sizeof (temp), "%s%s",
503*5c51f124SMoriah Waterland 			utsbuf.nodename, buf);
504*5c51f124SMoriah Waterland 		putparam("PSTAMP", temp);
505*5c51f124SMoriah Waterland 		logerr(gettext(WRN_SETPARAM), "PSTAMP", temp);
506*5c51f124SMoriah Waterland 	}
507*5c51f124SMoriah Waterland 	if ((pkgcat = getenv("CATEGORY")) == NULL) {
508*5c51f124SMoriah Waterland 		progerr(gettext(ERR_NOPARAM), "CATEGORY", svept->path);
509*5c51f124SMoriah Waterland 		quit(1);
510*5c51f124SMoriah Waterland 	}
511*5c51f124SMoriah Waterland 	if (ckparam("CATEGORY", pkgcat))
512*5c51f124SMoriah Waterland 		quit(1);
513*5c51f124SMoriah Waterland 
514*5c51f124SMoriah Waterland 	/*
515*5c51f124SMoriah Waterland 	 * warn user of classes listed in package which do
516*5c51f124SMoriah Waterland 	 * not appear in CLASSES variable in pkginfo file
517*5c51f124SMoriah Waterland 	 */
518*5c51f124SMoriah Waterland 	objects = 0;
519*5c51f124SMoriah Waterland 	for (i = 0; eptlist[i]; i++) {
520*5c51f124SMoriah Waterland 		if (eptlist[i]->ftype != 'i') {
521*5c51f124SMoriah Waterland 			objects++;
522*5c51f124SMoriah Waterland 			addlist(&allclass, eptlist[i]->pkg_class);
523*5c51f124SMoriah Waterland 		}
524*5c51f124SMoriah Waterland 	}
525*5c51f124SMoriah Waterland 
526*5c51f124SMoriah Waterland 	if ((pt = getenv("CLASSES")) == NULL) {
527*5c51f124SMoriah Waterland 		if (allclass && *allclass) {
528*5c51f124SMoriah Waterland 			cl_setl(allclass);
529*5c51f124SMoriah Waterland 			cl_putl("CLASSES", allclass);
530*5c51f124SMoriah Waterland 			logerr(gettext(WRN_SETPARAM), "CLASSES",
531*5c51f124SMoriah Waterland 			    getenv("CLASSES"));
532*5c51f124SMoriah Waterland 		}
533*5c51f124SMoriah Waterland 	} else {
534*5c51f124SMoriah Waterland 		cl_sets(qstrdup(pt));
535*5c51f124SMoriah Waterland 		if (allclass && *allclass) {
536*5c51f124SMoriah Waterland 			for (i = 0; allclass[i]; i++) {
537*5c51f124SMoriah Waterland 				found = 0;
538*5c51f124SMoriah Waterland 				if (cl_idx(allclass[i]->name) != -1) {
539*5c51f124SMoriah Waterland 					found++;
540*5c51f124SMoriah Waterland 					break;
541*5c51f124SMoriah Waterland 				}
542*5c51f124SMoriah Waterland 				if (!found) {
543*5c51f124SMoriah Waterland 					logerr(gettext(WRN_CLASSES),
544*5c51f124SMoriah Waterland 					    (char *)allclass[i]);
545*5c51f124SMoriah Waterland 				}
546*5c51f124SMoriah Waterland 			}
547*5c51f124SMoriah Waterland 		}
548*5c51f124SMoriah Waterland 	}
549*5c51f124SMoriah Waterland 
550*5c51f124SMoriah Waterland 	(void) fprintf(stderr, gettext(MSG_VOLUMIZE), objects);
551*5c51f124SMoriah Waterland 	order = (struct cl_attr **)0;
552*5c51f124SMoriah Waterland 	if (pt = getenv("ORDER")) {
553*5c51f124SMoriah Waterland 		pt = qstrdup(pt);
554*5c51f124SMoriah Waterland 		(void) setlist(&order, pt);
555*5c51f124SMoriah Waterland 		cl_putl("ORDER", order);
556*5c51f124SMoriah Waterland 	}
557*5c51f124SMoriah Waterland 
558*5c51f124SMoriah Waterland 	/* stat the intended output filesystem to get blocking information */
559*5c51f124SMoriah Waterland 	if (pkgdev.dirname == NULL) {
560*5c51f124SMoriah Waterland 		progerr(gettext(ERR_WHATVFS), device);
561*5c51f124SMoriah Waterland 		quit(99);
562*5c51f124SMoriah Waterland 	}
563*5c51f124SMoriah Waterland 	if (statvfs64(pkgdev.dirname, &svfsb)) {
564*5c51f124SMoriah Waterland 		progerr(gettext(ERR_STATVFS), pkgdev.dirname);
565*5c51f124SMoriah Waterland 		quit(99);
566*5c51f124SMoriah Waterland 	}
567*5c51f124SMoriah Waterland 
568*5c51f124SMoriah Waterland 	if (bsize == 0) {
569*5c51f124SMoriah Waterland 		bsize = svfsb.f_bsize;
570*5c51f124SMoriah Waterland 	}
571*5c51f124SMoriah Waterland 	if (frsize == 0) {
572*5c51f124SMoriah Waterland 		frsize = svfsb.f_frsize;
573*5c51f124SMoriah Waterland 	}
574*5c51f124SMoriah Waterland 
575*5c51f124SMoriah Waterland 	if (limit == 0)
576*5c51f124SMoriah Waterland 		/*
577*5c51f124SMoriah Waterland 		 * bavail is in terms of fragment size blocks - change
578*5c51f124SMoriah Waterland 		 * to 512 byte blocks
579*5c51f124SMoriah Waterland 		 */
580*5c51f124SMoriah Waterland 		limit = (fsblkcnt_t)(((fsblkcnt_t)frsize > 0) ?
581*5c51f124SMoriah Waterland 			howmany(frsize, DEV_BSIZE) :
582*5c51f124SMoriah Waterland 			howmany(bsize, DEV_BSIZE)) * svfsb.f_bavail;
583*5c51f124SMoriah Waterland 
584*5c51f124SMoriah Waterland 	if (ilimit == 0) {
585*5c51f124SMoriah Waterland 		ilimit = (svfsb.f_favail > 0) ?
586*5c51f124SMoriah Waterland 		    svfsb.f_favail : svfsb.f_ffree;
587*5c51f124SMoriah Waterland 	}
588*5c51f124SMoriah Waterland 
589*5c51f124SMoriah Waterland 	nparts = splpkgmap(eptlist, eptnum, (char **)order, bsize, frsize,
590*5c51f124SMoriah Waterland 	    &limit, &ilimit, &llimit);
591*5c51f124SMoriah Waterland 
592*5c51f124SMoriah Waterland 	if (nparts <= 0) {
593*5c51f124SMoriah Waterland 		progerr(gettext(ERR_SPLIT));
594*5c51f124SMoriah Waterland 		quit(1);
595*5c51f124SMoriah Waterland 	}
596*5c51f124SMoriah Waterland 
597*5c51f124SMoriah Waterland 	if (nflag) {
598*5c51f124SMoriah Waterland 		for (i = 0; eptlist[i]; i++)
599*5c51f124SMoriah Waterland 			(void) ppkgmap(eptlist[i], stdout);
600*5c51f124SMoriah Waterland 		exit(0);
601*5c51f124SMoriah Waterland 		/*NOTREACHED*/
602*5c51f124SMoriah Waterland 	}
603*5c51f124SMoriah Waterland 
604*5c51f124SMoriah Waterland 	(void) snprintf(pkgloc, sizeof (pkgloc), "%s/%s",
605*5c51f124SMoriah Waterland 			pkgdev.dirname, pkginst);
606*5c51f124SMoriah Waterland 	if (!isdir(pkgloc) && !overwrite) {
607*5c51f124SMoriah Waterland 		progerr(gettext(ERR_OVERWRITE), pkgloc);
608*5c51f124SMoriah Waterland 		quit(1);
609*5c51f124SMoriah Waterland 	}
610*5c51f124SMoriah Waterland 
611*5c51f124SMoriah Waterland 	/* output all environment install parameters */
612*5c51f124SMoriah Waterland 	t_pkginfo = tempnam(tmpdir, "pkginfo");
613*5c51f124SMoriah Waterland 	if ((fp = fopen(t_pkginfo, "w")) == NULL) {
614*5c51f124SMoriah Waterland 		progerr(gettext(ERR_TEMP), errno);
615*5c51f124SMoriah Waterland 		exit(99);
616*5c51f124SMoriah Waterland 	}
617*5c51f124SMoriah Waterland 	for (i = 0; environ[i]; i++) {
618*5c51f124SMoriah Waterland 		if (isupper(*environ[i])) {
619*5c51f124SMoriah Waterland 			(void) fputs(environ[i], fp);
620*5c51f124SMoriah Waterland 			(void) fputc('\n', fp);
621*5c51f124SMoriah Waterland 		}
622*5c51f124SMoriah Waterland 	}
623*5c51f124SMoriah Waterland 	(void) fclose(fp);
624*5c51f124SMoriah Waterland 
625*5c51f124SMoriah Waterland 	started++;
626*5c51f124SMoriah Waterland 	(void) rrmdir(pkgloc);
627*5c51f124SMoriah Waterland 	if (mkdir(pkgloc, 0755)) {
628*5c51f124SMoriah Waterland 		progerr(gettext(ERR_MKDIR), pkgloc);
629*5c51f124SMoriah Waterland 		quit(1);
630*5c51f124SMoriah Waterland 	}
631*5c51f124SMoriah Waterland 
632*5c51f124SMoriah Waterland 	/* determine how many packages already reside on the medium */
633*5c51f124SMoriah Waterland 	pkgdir = pkgdev.dirname;
634*5c51f124SMoriah Waterland 	npkgs = 0;
635*5c51f124SMoriah Waterland 	while (pt = fpkginst("all", NULL, NULL))
636*5c51f124SMoriah Waterland 		npkgs++;
637*5c51f124SMoriah Waterland 	(void) fpkginst(NULL); /* free resource usage */
638*5c51f124SMoriah Waterland 
639*5c51f124SMoriah Waterland 	if (nparts > 1) {
640*5c51f124SMoriah Waterland 		if (pkgdev.mount && npkgs) {
641*5c51f124SMoriah Waterland 			progerr(gettext(ERR_ONEVOL));
642*5c51f124SMoriah Waterland 			quit(1);
643*5c51f124SMoriah Waterland 		}
644*5c51f124SMoriah Waterland 	}
645*5c51f124SMoriah Waterland 
646*5c51f124SMoriah Waterland 	/*
647*5c51f124SMoriah Waterland 	 *  update pkgmap entry for pkginfo file, since it may
648*5c51f124SMoriah Waterland 	 *  have changed due to command line or failure to
649*5c51f124SMoriah Waterland 	 *  specify all neccessary parameters
650*5c51f124SMoriah Waterland 	 */
651*5c51f124SMoriah Waterland 	for (i = 0; eptlist[i]; i++) {
652*5c51f124SMoriah Waterland 		if (eptlist[i]->ftype != 'i')
653*5c51f124SMoriah Waterland 			continue;
654*5c51f124SMoriah Waterland 		if (strcmp(eptlist[i]->path, "pkginfo") == 0) {
655*5c51f124SMoriah Waterland 			svept = eptlist[i];
656*5c51f124SMoriah Waterland 			svept->ftype = '?';
657*5c51f124SMoriah Waterland 			svept->ainfo.local = t_pkginfo;
658*5c51f124SMoriah Waterland 			(void) cverify(0, &svept->ftype, t_pkginfo,
659*5c51f124SMoriah Waterland 				&svept->cinfo, 1);
660*5c51f124SMoriah Waterland 			svept->ftype = 'i';
661*5c51f124SMoriah Waterland 			break;
662*5c51f124SMoriah Waterland 		}
663*5c51f124SMoriah Waterland 	}
664*5c51f124SMoriah Waterland 
665*5c51f124SMoriah Waterland 	if (nparts > 1)
666*5c51f124SMoriah Waterland 		(void) fprintf(stderr, gettext(MSG_PACKAGEM), nparts);
667*5c51f124SMoriah Waterland 	else
668*5c51f124SMoriah Waterland 		(void) fprintf(stderr, gettext(MSG_PACKAGE1));
669*5c51f124SMoriah Waterland 
670*5c51f124SMoriah Waterland 	for (part = 1; part <= nparts; part++) {
671*5c51f124SMoriah Waterland 		if ((part > 1) && pkgdev.mount) {
672*5c51f124SMoriah Waterland 			if (pkgumount(&pkgdev)) {
673*5c51f124SMoriah Waterland 				progerr(gettext(ERR_UMOUNT), pkgdev.mount);
674*5c51f124SMoriah Waterland 				quit(99);
675*5c51f124SMoriah Waterland 			}
676*5c51f124SMoriah Waterland 			if (n = pkgmount(&pkgdev, NULL, part, nparts, 1))
677*5c51f124SMoriah Waterland 				quit(n);
678*5c51f124SMoriah Waterland 			(void) rrmdir(pkgloc);
679*5c51f124SMoriah Waterland 			if (mkdir(pkgloc, 0555)) {
680*5c51f124SMoriah Waterland 				progerr(gettext(ERR_MKDIR), pkgloc);
681*5c51f124SMoriah Waterland 				quit(99);
682*5c51f124SMoriah Waterland 			}
683*5c51f124SMoriah Waterland 		}
684*5c51f124SMoriah Waterland 		outvol(eptlist, eptnum, part, nparts);
685*5c51f124SMoriah Waterland 
686*5c51f124SMoriah Waterland 		/* Validate (as much as possible) the control scripts. */
687*5c51f124SMoriah Waterland 		if (part == 1) {
688*5c51f124SMoriah Waterland 			char inst_path[PATH_MAX];
689*5c51f124SMoriah Waterland 
690*5c51f124SMoriah Waterland 			(void) fprintf(stderr, gettext(MSG_VALSCRIPTS));
691*5c51f124SMoriah Waterland 			(void) snprintf(inst_path, sizeof (inst_path),
692*5c51f124SMoriah Waterland 					"%s/install", pkgloc);
693*5c51f124SMoriah Waterland 			checkscripts(inst_path, 0);
694*5c51f124SMoriah Waterland 		}
695*5c51f124SMoriah Waterland 	}
696*5c51f124SMoriah Waterland 
697*5c51f124SMoriah Waterland 	quit(0);
698*5c51f124SMoriah Waterland 	/* LINTED: no return */
699*5c51f124SMoriah Waterland }
700*5c51f124SMoriah Waterland 
701*5c51f124SMoriah Waterland static void
702*5c51f124SMoriah Waterland trap(int n)
703*5c51f124SMoriah Waterland {
704*5c51f124SMoriah Waterland 	(void) signal(SIGINT, SIG_IGN);
705*5c51f124SMoriah Waterland 	(void) signal(SIGHUP, SIG_IGN);
706*5c51f124SMoriah Waterland 
707*5c51f124SMoriah Waterland 	if (n == SIGINT)
708*5c51f124SMoriah Waterland 		quit(3);
709*5c51f124SMoriah Waterland 	else {
710*5c51f124SMoriah Waterland 		(void) fprintf(stderr, gettext("%s terminated (signal %d).\n"),
711*5c51f124SMoriah Waterland 				get_prog_name(), n);
712*5c51f124SMoriah Waterland 		quit(99);
713*5c51f124SMoriah Waterland 	}
714*5c51f124SMoriah Waterland }
715*5c51f124SMoriah Waterland 
716*5c51f124SMoriah Waterland static void
717*5c51f124SMoriah Waterland outvol(struct cfent **eptlist, unsigned int eptnum, int part, int nparts)
718*5c51f124SMoriah Waterland {
719*5c51f124SMoriah Waterland 	FILE	*fp;
720*5c51f124SMoriah Waterland 	char	*svpt, *path, temp[PATH_MAX];
721*5c51f124SMoriah Waterland 	unsigned int	i;
722*5c51f124SMoriah Waterland 
723*5c51f124SMoriah Waterland 
724*5c51f124SMoriah Waterland 	if (nparts > 1)
725*5c51f124SMoriah Waterland 		(void) fprintf(stderr, gettext(" -- part %2d:\n"), part);
726*5c51f124SMoriah Waterland 	if (part == 1) {
727*5c51f124SMoriah Waterland 		/* re-write pkgmap, but exclude local pathnames */
728*5c51f124SMoriah Waterland 		(void) snprintf(temp, sizeof (temp), "%s/pkgmap", pkgloc);
729*5c51f124SMoriah Waterland 		if ((fp = fopen(temp, "w")) == NULL) {
730*5c51f124SMoriah Waterland 			progerr(gettext(ERR_TEMP), errno);
731*5c51f124SMoriah Waterland 			quit(99);
732*5c51f124SMoriah Waterland 		}
733*5c51f124SMoriah Waterland 		(void) fprintf(fp, ": %d %ld\n", nparts, limit);
734*5c51f124SMoriah Waterland 		for (i = 0; eptlist[i]; i++) {
735*5c51f124SMoriah Waterland 			svpt = eptlist[i]->ainfo.local;
736*5c51f124SMoriah Waterland 			if (!strchr("sl", eptlist[i]->ftype))
737*5c51f124SMoriah Waterland 				eptlist[i]->ainfo.local = NULL;
738*5c51f124SMoriah Waterland 			if (ppkgmap(eptlist[i], fp)) {
739*5c51f124SMoriah Waterland 				progerr(gettext(ERR_TEMP), errno);
740*5c51f124SMoriah Waterland 				quit(99);
741*5c51f124SMoriah Waterland 			}
742*5c51f124SMoriah Waterland 			eptlist[i]->ainfo.local = svpt;
743*5c51f124SMoriah Waterland 		}
744*5c51f124SMoriah Waterland 		(void) fclose(fp);
745*5c51f124SMoriah Waterland 		(void) fprintf(stderr, "%s\n", temp);
746*5c51f124SMoriah Waterland 	}
747*5c51f124SMoriah Waterland 
748*5c51f124SMoriah Waterland 	(void) snprintf(temp, sizeof (temp), "%s/pkginfo", pkgloc);
749*5c51f124SMoriah Waterland 	if (copyf(svept->ainfo.local, temp, svept->cinfo.modtime))
750*5c51f124SMoriah Waterland 		quit(1);
751*5c51f124SMoriah Waterland 	(void) fprintf(stderr, "%s\n", temp);
752*5c51f124SMoriah Waterland 
753*5c51f124SMoriah Waterland 	for (i = 0; i < eptnum; i++) {
754*5c51f124SMoriah Waterland 		if (eptlist[i]->volno != part)
755*5c51f124SMoriah Waterland 			continue;
756*5c51f124SMoriah Waterland 		if (strchr("dxslcbp", eptlist[i]->ftype))
757*5c51f124SMoriah Waterland 			continue;
758*5c51f124SMoriah Waterland 		if (eptlist[i]->ftype == 'i') {
759*5c51f124SMoriah Waterland 			if (eptlist[i] == svept)
760*5c51f124SMoriah Waterland 				continue; /* don't copy pkginfo file */
761*5c51f124SMoriah Waterland 			(void) snprintf(temp, sizeof (temp),
762*5c51f124SMoriah Waterland 				"%s/install/%s", pkgloc,
763*5c51f124SMoriah Waterland 				eptlist[i]->path);
764*5c51f124SMoriah Waterland 			path = temp;
765*5c51f124SMoriah Waterland 		} else
766*5c51f124SMoriah Waterland 			path = srcpath(pkgloc, eptlist[i]->path, part, nparts);
767*5c51f124SMoriah Waterland 		if (sflag) {
768*5c51f124SMoriah Waterland 			if (slinkf(eptlist[i]->ainfo.local, path))
769*5c51f124SMoriah Waterland 				quit(1);
770*5c51f124SMoriah Waterland 		} else if (copyf(eptlist[i]->ainfo.local, path,
771*5c51f124SMoriah Waterland 				eptlist[i]->cinfo.modtime)) {
772*5c51f124SMoriah Waterland 			quit(1);
773*5c51f124SMoriah Waterland 		}
774*5c51f124SMoriah Waterland 
775*5c51f124SMoriah Waterland 		/*
776*5c51f124SMoriah Waterland 		 * If the package file attributes can be sync'd up with
777*5c51f124SMoriah Waterland 		 * the pkgmap, we fix the attributes here.
778*5c51f124SMoriah Waterland 		 */
779*5c51f124SMoriah Waterland 		if (*(eptlist[i]->ainfo.owner) != '$' &&
780*5c51f124SMoriah Waterland 		    *(eptlist[i]->ainfo.group) != '$' && getuid() == 0) {
781*5c51f124SMoriah Waterland 			/* Clear dangerous bits. */
782*5c51f124SMoriah Waterland 			eptlist[i]->ainfo.mode=
783*5c51f124SMoriah Waterland 			    (eptlist[i]->ainfo.mode & S_IAMB);
784*5c51f124SMoriah Waterland 			/*
785*5c51f124SMoriah Waterland 			 * Make sure it can be read by the world and written
786*5c51f124SMoriah Waterland 			 * by root.
787*5c51f124SMoriah Waterland 			 */
788*5c51f124SMoriah Waterland 			eptlist[i]->ainfo.mode |= 0644;
789*5c51f124SMoriah Waterland 			if (!strchr("in", eptlist[i]->ftype)) {
790*5c51f124SMoriah Waterland 				/* Set the safe attributes. */
791*5c51f124SMoriah Waterland 				averify(1, &(eptlist[i]->ftype),
792*5c51f124SMoriah Waterland 				    path, &(eptlist[i]->ainfo));
793*5c51f124SMoriah Waterland 			}
794*5c51f124SMoriah Waterland 		}
795*5c51f124SMoriah Waterland 
796*5c51f124SMoriah Waterland 		(void) fprintf(stderr, "%s\n", path);
797*5c51f124SMoriah Waterland 	}
798*5c51f124SMoriah Waterland }
799*5c51f124SMoriah Waterland 
800*5c51f124SMoriah Waterland static void
801*5c51f124SMoriah Waterland ckmissing(char *path, char type)
802*5c51f124SMoriah Waterland {
803*5c51f124SMoriah Waterland 	static char	**dir;
804*5c51f124SMoriah Waterland 	static int	ndir;
805*5c51f124SMoriah Waterland 	char	*pt;
806*5c51f124SMoriah Waterland 	int	i, found;
807*5c51f124SMoriah Waterland 
808*5c51f124SMoriah Waterland 	if (dir == NULL) {
809*5c51f124SMoriah Waterland 		dir = (char **)calloc(MALSIZ, sizeof (char *));
810*5c51f124SMoriah Waterland 		if (dir == NULL) {
811*5c51f124SMoriah Waterland 			progerr(gettext(ERR_MEMORY), errno);
812*5c51f124SMoriah Waterland 			quit(99);
813*5c51f124SMoriah Waterland 		}
814*5c51f124SMoriah Waterland 	}
815*5c51f124SMoriah Waterland 
816*5c51f124SMoriah Waterland 	if (strchr("dx", type)) {
817*5c51f124SMoriah Waterland 		dir[ndir] = path;
818*5c51f124SMoriah Waterland 		if ((++ndir % MALSIZ) == 0) {
819*5c51f124SMoriah Waterland 			dir = (char **)realloc((void *)dir,
820*5c51f124SMoriah Waterland 				(ndir+MALSIZ)*sizeof (char *));
821*5c51f124SMoriah Waterland 			if (dir == NULL) {
822*5c51f124SMoriah Waterland 				progerr(gettext(ERR_MEMORY), errno);
823*5c51f124SMoriah Waterland 				quit(99);
824*5c51f124SMoriah Waterland 			}
825*5c51f124SMoriah Waterland 		}
826*5c51f124SMoriah Waterland 		dir[ndir] = (char *)NULL;
827*5c51f124SMoriah Waterland 	}
828*5c51f124SMoriah Waterland 
829*5c51f124SMoriah Waterland 	pt = path;
830*5c51f124SMoriah Waterland 	if (*pt == '/')
831*5c51f124SMoriah Waterland 		pt++;
832*5c51f124SMoriah Waterland 	while (pt = strchr(pt, '/')) {
833*5c51f124SMoriah Waterland 		*pt = '\0';
834*5c51f124SMoriah Waterland 		found = 0;
835*5c51f124SMoriah Waterland 		for (i = 0; i < ndir; i++) {
836*5c51f124SMoriah Waterland 			if (strcmp(path, dir[i]) == 0) {
837*5c51f124SMoriah Waterland 				found++;
838*5c51f124SMoriah Waterland 				break;
839*5c51f124SMoriah Waterland 			}
840*5c51f124SMoriah Waterland 		}
841*5c51f124SMoriah Waterland 		if (!found) {
842*5c51f124SMoriah Waterland 			logerr(gettext(WRN_MISSINGDIR), path);
843*5c51f124SMoriah Waterland 			ckmissing(qstrdup(path), 'd');
844*5c51f124SMoriah Waterland 		}
845*5c51f124SMoriah Waterland 		*pt++ = '/';
846*5c51f124SMoriah Waterland 	}
847*5c51f124SMoriah Waterland }
848*5c51f124SMoriah Waterland 
849*5c51f124SMoriah Waterland static int
850*5c51f124SMoriah Waterland slinkf(char *from, char *to)
851*5c51f124SMoriah Waterland {
852*5c51f124SMoriah Waterland 	char	*pt;
853*5c51f124SMoriah Waterland 
854*5c51f124SMoriah Waterland 	pt = to;
855*5c51f124SMoriah Waterland 	while (pt = strchr(pt+1, '/')) {
856*5c51f124SMoriah Waterland 		*pt = '\0';
857*5c51f124SMoriah Waterland 		if (isdir(to) && mkdir(to, 0755)) {
858*5c51f124SMoriah Waterland 			progerr(gettext(ERR_MKDIR), to);
859*5c51f124SMoriah Waterland 			*pt = '/';
860*5c51f124SMoriah Waterland 			return (-1);
861*5c51f124SMoriah Waterland 		}
862*5c51f124SMoriah Waterland 		*pt = '/';
863*5c51f124SMoriah Waterland 	}
864*5c51f124SMoriah Waterland 	if (symlink(from, to)) {
865*5c51f124SMoriah Waterland 		progerr(gettext(ERR_SYMLINK), to);
866*5c51f124SMoriah Waterland 		return (-1);
867*5c51f124SMoriah Waterland 	}
868*5c51f124SMoriah Waterland 	return (0);
869*5c51f124SMoriah Waterland }
870*5c51f124SMoriah Waterland 
871*5c51f124SMoriah Waterland static void
872*5c51f124SMoriah Waterland usage(void)
873*5c51f124SMoriah Waterland {
874*5c51f124SMoriah Waterland 	(void) fprintf(stderr, gettext(ERR_USAGE), get_prog_name());
875*5c51f124SMoriah Waterland 	exit(1);
876*5c51f124SMoriah Waterland 	/*NOTREACHED*/
877*5c51f124SMoriah Waterland }
878*5c51f124SMoriah Waterland 
879*5c51f124SMoriah Waterland /*
880*5c51f124SMoriah Waterland  * valid_zone_attr:	Validates the zone attributes specified in
881*5c51f124SMoriah Waterland  *			pkginfo file for this package. The package
882*5c51f124SMoriah Waterland  *			can not be created with certain combinations
883*5c51f124SMoriah Waterland  *			of the attributes.
884*5c51f124SMoriah Waterland  */
885*5c51f124SMoriah Waterland static boolean_t
886*5c51f124SMoriah Waterland valid_zone_attr(struct cfent **eptlist)
887*5c51f124SMoriah Waterland {
888*5c51f124SMoriah Waterland 	FILE		*pkginfoFP;
889*5c51f124SMoriah Waterland 	boolean_t	all_zones;	/* pkg is "all zones" only */
890*5c51f124SMoriah Waterland 	boolean_t	is_hollow;	/* pkg is "hollow" */
891*5c51f124SMoriah Waterland 	boolean_t	this_zone;	/* pkg is "this zone" only */
892*5c51f124SMoriah Waterland 	char 		pkginfoPath[PATH_MAX];	/* pkginfo file path */
893*5c51f124SMoriah Waterland 	char		*pkgInst;
894*5c51f124SMoriah Waterland 	int i;
895*5c51f124SMoriah Waterland 
896*5c51f124SMoriah Waterland 	/* Path to pkginfo file within the package to be installed */
897*5c51f124SMoriah Waterland 
898*5c51f124SMoriah Waterland 	this_zone = B_FALSE;
899*5c51f124SMoriah Waterland 	for (i = 0; eptlist[i]; i++) {
900*5c51f124SMoriah Waterland 		if (eptlist[i]->ftype != 'i')
901*5c51f124SMoriah Waterland 			continue;
902*5c51f124SMoriah Waterland 		if (strcmp(eptlist[i]->path, "pkginfo") == 0)
903*5c51f124SMoriah Waterland 			(void) strcpy(pkginfoPath, eptlist[i]->ainfo.local);
904*5c51f124SMoriah Waterland 
905*5c51f124SMoriah Waterland 		/*
906*5c51f124SMoriah Waterland 		 * Check to see if this package has a request script. If this
907*5c51f124SMoriah Waterland 		 * package does have a request script, then mark the package
908*5c51f124SMoriah Waterland 		 * for installation in this zone only. Any package with a
909*5c51f124SMoriah Waterland 		 * request script cannot be installed outside of the zone the
910*5c51f124SMoriah Waterland 		 * pkgadd command is being run in, nor can such a package be
911*5c51f124SMoriah Waterland 		 * installed as part of a new zone install. A new zone install
912*5c51f124SMoriah Waterland 		 * must be non-interactive, which is required by all packages
913*5c51f124SMoriah Waterland 		 * integrated into the Solaris WOS.
914*5c51f124SMoriah Waterland 		 * If request file is set in prototype, then this_zone is TRUE.
915*5c51f124SMoriah Waterland 		 */
916*5c51f124SMoriah Waterland 		if (strcmp(eptlist[i]->path, "request") == 0)
917*5c51f124SMoriah Waterland 			this_zone = B_TRUE;
918*5c51f124SMoriah Waterland 	}
919*5c51f124SMoriah Waterland 
920*5c51f124SMoriah Waterland 	/* Gather information from the pkginfo file */
921*5c51f124SMoriah Waterland 
922*5c51f124SMoriah Waterland 	pkginfoFP = fopen(pkginfoPath, "r");
923*5c51f124SMoriah Waterland 
924*5c51f124SMoriah Waterland 	if (pkginfoFP == NULL) {
925*5c51f124SMoriah Waterland 		progerr(ERR_NO_PKG_INFOFILE, pkginfoPath, strerror(errno));
926*5c51f124SMoriah Waterland 		return (B_FALSE);
927*5c51f124SMoriah Waterland 	}
928*5c51f124SMoriah Waterland 
929*5c51f124SMoriah Waterland 	if ((pkgInst = fpkgparam(pkginfoFP, "PKG")) == NULL) {
930*5c51f124SMoriah Waterland 		progerr(gettext(ERR_NOPARAM), "PKG", pkginfoPath);
931*5c51f124SMoriah Waterland 		return (B_FALSE);
932*5c51f124SMoriah Waterland 	}
933*5c51f124SMoriah Waterland 
934*5c51f124SMoriah Waterland 
935*5c51f124SMoriah Waterland 	/* Determine "HOLLOW" setting for this package */
936*5c51f124SMoriah Waterland 	is_hollow = pkginfoParamTruth(pkginfoFP, PKG_HOLLOW_VARIABLE,
937*5c51f124SMoriah Waterland 			"true", B_FALSE);
938*5c51f124SMoriah Waterland 
939*5c51f124SMoriah Waterland 	/* Determine "ALLZONES" setting for this package */
940*5c51f124SMoriah Waterland 	all_zones = pkginfoParamTruth(pkginfoFP, PKG_ALLZONES_VARIABLE,
941*5c51f124SMoriah Waterland 			"true", B_FALSE);
942*5c51f124SMoriah Waterland 
943*5c51f124SMoriah Waterland 	/* Determine "THISZONE" setting for this package, if no request file */
944*5c51f124SMoriah Waterland 	if (!this_zone)
945*5c51f124SMoriah Waterland 		this_zone = pkginfoParamTruth(pkginfoFP, PKG_THISZONE_VARIABLE,
946*5c51f124SMoriah Waterland 			"true", B_FALSE);
947*5c51f124SMoriah Waterland 
948*5c51f124SMoriah Waterland 	/* Close pkginfo file */
949*5c51f124SMoriah Waterland 	(void) fclose(pkginfoFP);
950*5c51f124SMoriah Waterland 
951*5c51f124SMoriah Waterland 	/*
952*5c51f124SMoriah Waterland 	 * Validate zone attributes based on information gathered,
953*5c51f124SMoriah Waterland 	 * and validate the three SUNW_PKG_ options:
954*5c51f124SMoriah Waterland 	 *
955*5c51f124SMoriah Waterland 	 * -----------------------------|---------------|
956*5c51f124SMoriah Waterland 	 * <ALLZONES><HOLLOW><THISZONE> |  If Allowed   |
957*5c51f124SMoriah Waterland 	 * ----1------------------------|---------------|
958*5c51f124SMoriah Waterland 	 *		F F F		|	OK	|
959*5c51f124SMoriah Waterland 	 *		F F T		|	OK	|
960*5c51f124SMoriah Waterland 	 *		F T *		|	NO	|
961*5c51f124SMoriah Waterland 	 * ----2------------------------|---------------|
962*5c51f124SMoriah Waterland 	 *		T F F		|	OK	|
963*5c51f124SMoriah Waterland 	 *		T T F		|	OK	|
964*5c51f124SMoriah Waterland 	 *		T * T		|	NO	|
965*5c51f124SMoriah Waterland 	 * -----------------------------|---------------|
966*5c51f124SMoriah Waterland 	 */
967*5c51f124SMoriah Waterland 
968*5c51f124SMoriah Waterland 	/* pkg "all zones" && "this zone" (#2) */
969*5c51f124SMoriah Waterland 
970*5c51f124SMoriah Waterland 	if (all_zones && this_zone) {
971*5c51f124SMoriah Waterland 		progerr(ERR_ALLZONES_AND_THISZONE, pkgInst,
972*5c51f124SMoriah Waterland 		    PKG_ALLZONES_VARIABLE, PKG_THISZONE_VARIABLE);
973*5c51f124SMoriah Waterland 		return (B_FALSE);
974*5c51f124SMoriah Waterland 	}
975*5c51f124SMoriah Waterland 
976*5c51f124SMoriah Waterland 	/* pkg "!all zones" && "hollow" (#1) */
977*5c51f124SMoriah Waterland 
978*5c51f124SMoriah Waterland 	if ((!all_zones) && is_hollow) {
979*5c51f124SMoriah Waterland 		progerr(ERR_NO_ALLZONES_AND_HOLLOW, pkgInst,
980*5c51f124SMoriah Waterland 		    PKG_ALLZONES_VARIABLE, PKG_HOLLOW_VARIABLE);
981*5c51f124SMoriah Waterland 		return (B_FALSE);
982*5c51f124SMoriah Waterland 	}
983*5c51f124SMoriah Waterland 
984*5c51f124SMoriah Waterland 	return (B_TRUE);
985*5c51f124SMoriah Waterland }
986