xref: /titanic_52/usr/src/cmd/svr4pkg/libinst/fixpath.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 
28*5c51f124SMoriah Waterland /*
29*5c51f124SMoriah Waterland  * This module contains all the code necessary to establish the key base
30*5c51f124SMoriah Waterland  * directories to which the actual components of the package will be
31*5c51f124SMoriah Waterland  * installed or removed. -- JST
32*5c51f124SMoriah Waterland  */
33*5c51f124SMoriah Waterland 
34*5c51f124SMoriah Waterland #include <stdio.h>
35*5c51f124SMoriah Waterland #include <string.h>
36*5c51f124SMoriah Waterland #include <stdlib.h>
37*5c51f124SMoriah Waterland #include <unistd.h>
38*5c51f124SMoriah Waterland #include <sys/stat.h>	/* mkdir() declaration */
39*5c51f124SMoriah Waterland #include <libintl.h>
40*5c51f124SMoriah Waterland #include <pkglib.h>
41*5c51f124SMoriah Waterland #include <install.h>
42*5c51f124SMoriah Waterland #include <libadm.h>
43*5c51f124SMoriah Waterland #include <libinst.h>
44*5c51f124SMoriah Waterland 
45*5c51f124SMoriah Waterland static char *install_root = NULL;
46*5c51f124SMoriah Waterland static int install_root_exists = 0;	/* An install root was specified */
47*5c51f124SMoriah Waterland static int install_root_len;		/* strlen(install_root) */
48*5c51f124SMoriah Waterland static char *orig_basedir = NULL;	/* The unadjusted basedir */
49*5c51f124SMoriah Waterland static char *basedir = NULL;		/* basedir (cmb w/ inst rt if req) */
50*5c51f124SMoriah Waterland static int basedir_exists = 0;		/* There are relocatable paths */
51*5c51f124SMoriah Waterland static char *client_basedir = NULL;
52*5c51f124SMoriah Waterland static int client_basedir_exists = 0;	/* Installing from a host */
53*5c51f124SMoriah Waterland static char *env_cl_bdir = NULL;	/* CLIENT_BASEDIR from environment */
54*5c51f124SMoriah Waterland static int ir_accessed = 0;		/* install_root has been used */
55*5c51f124SMoriah Waterland static int relocatable;			/* set_basedir() assumed this */
56*5c51f124SMoriah Waterland static int partial_inst = 0; /* Installing pkg from partial spool directory */
57*5c51f124SMoriah Waterland static boolean_t depend_pkginfo_DB = B_FALSE; /* Only update depend/pkginfoDB */
58*5c51f124SMoriah Waterland static int partial_spool_create = 0; /* Create partial spool dir */
59*5c51f124SMoriah Waterland 
60*5c51f124SMoriah Waterland static int	ask_basedir(char *path, int nointeract);
61*5c51f124SMoriah Waterland static char	*expand_path(char *path);
62*5c51f124SMoriah Waterland static int	set_client_basedir(void);
63*5c51f124SMoriah Waterland static char 	*fixpath_dup(char *path);
64*5c51f124SMoriah Waterland static int	orig_offset_rel;
65*5c51f124SMoriah Waterland 
66*5c51f124SMoriah Waterland /*
67*5c51f124SMoriah Waterland  * base_sepr and rel_fmt support construction of absolute paths from
68*5c51f124SMoriah Waterland  * relative paths.
69*5c51f124SMoriah Waterland  */
70*5c51f124SMoriah Waterland static int	base_sepr = 1;	/* separator length btwn basedir & path */
71*5c51f124SMoriah Waterland static char	*rel_fmt[] = { "%s%s", "%s/%s" };
72*5c51f124SMoriah Waterland 
73*5c51f124SMoriah Waterland static int	eval_valid = 0;	/* everything set up to do an eval_path() */
74*5c51f124SMoriah Waterland 
75*5c51f124SMoriah Waterland /* libpkg/gpkgmap.c */
76*5c51f124SMoriah Waterland extern int	getmapmode();
77*5c51f124SMoriah Waterland 
78*5c51f124SMoriah Waterland #define	MSG_IR_REPL	"Replacing current install root with %s."
79*5c51f124SMoriah Waterland #define	ERR_IRSET	"Install_root has already been set to <%s> and used."
80*5c51f124SMoriah Waterland #define	ERR_IRNOTABS	"Install_root (-R option) requires an absolute " \
81*5c51f124SMoriah Waterland 			"pathname: <%s>"
82*5c51f124SMoriah Waterland #define	ERR_ALLOCFAILED	"insufficient memory in %s"
83*5c51f124SMoriah Waterland #define	ERR_ADMIN_INVAL	"Invalid basedir entry in admin file."
84*5c51f124SMoriah Waterland #define	ERR_PATHNAME 	"Path name is invalid"
85*5c51f124SMoriah Waterland #define	ERR_RELINABS	"Relative path <%s> found in absolute package."
86*5c51f124SMoriah Waterland #define	ERR_CL_MIS	"Constructed CLIENT_BASEDIR <%s> and " \
87*5c51f124SMoriah Waterland 			"environment CLIENT_BASEDIR <%s> do not match."
88*5c51f124SMoriah Waterland #define	ERR_ASKBD	"%s is already installed at %s. Cannot create a " \
89*5c51f124SMoriah Waterland 			    "duplicate installation at %s."
90*5c51f124SMoriah Waterland #define	ERR_NO_CL_BD	"Cannot resolve CLIENT_BASEDIR conflicts."
91*5c51f124SMoriah Waterland #define	ERR_AMBDIRS	"Cannot evaluate path due to ambiguous " \
92*5c51f124SMoriah Waterland 			"base directories."
93*5c51f124SMoriah Waterland #define	ERR_NODELETE	"unable to delete <%s>."
94*5c51f124SMoriah Waterland #define	ERR_MKBASE	"unable to make directory <%s>."
95*5c51f124SMoriah Waterland #define	MSG_REQBASEDIR	"Installation of this package requires a base " \
96*5c51f124SMoriah Waterland 			"directory."
97*5c51f124SMoriah Waterland 
98*5c51f124SMoriah Waterland #define	MSG_MUSTEXIST	"\\nThe selected base directory <%s> must exist " \
99*5c51f124SMoriah Waterland 			"before installation is attempted."
100*5c51f124SMoriah Waterland #define	MSG_YORNPRMPT	"Do you want this directory created now"
101*5c51f124SMoriah Waterland 
102*5c51f124SMoriah Waterland #define	MSG_ISAFILE	"\\nThe selected base directory <%s> must exist " \
103*5c51f124SMoriah Waterland 			"before installation is attempted, but a file " \
104*5c51f124SMoriah Waterland 			"already exists in it's place."
105*5c51f124SMoriah Waterland #define	MSG_YORNFILE	"Do you want the file deleted and the directory " \
106*5c51f124SMoriah Waterland 			"created now"
107*5c51f124SMoriah Waterland 
108*5c51f124SMoriah Waterland #define	MSG_PROMPT	"Enter path to package base directory"
109*5c51f124SMoriah Waterland 
110*5c51f124SMoriah Waterland #define	MSG_HELP	"Installation of this package requires that a UNIX " \
111*5c51f124SMoriah Waterland 			"directory be available for installation of " \
112*5c51f124SMoriah Waterland 			"appropriate software.  This directory may be part " \
113*5c51f124SMoriah Waterland 			"of any mounted filesystem, or may itself be a " \
114*5c51f124SMoriah Waterland 			"mount point.  In general, it is unwise to select a " \
115*5c51f124SMoriah Waterland 			"base directory which already contains other files " \
116*5c51f124SMoriah Waterland 			"and/or directories."
117*5c51f124SMoriah Waterland 
118*5c51f124SMoriah Waterland /*
119*5c51f124SMoriah Waterland  * Set the install root (-R option).
120*5c51f124SMoriah Waterland  */
121*5c51f124SMoriah Waterland 
122*5c51f124SMoriah Waterland int
123*5c51f124SMoriah Waterland set_inst_root(char *path)
124*5c51f124SMoriah Waterland {
125*5c51f124SMoriah Waterland 	static	char	tmp_path[PATH_MAX];
126*5c51f124SMoriah Waterland 
127*5c51f124SMoriah Waterland 	/*
128*5c51f124SMoriah Waterland 	 * If we've already set the install_root but no one has used it
129*5c51f124SMoriah Waterland 	 * yet, we'll complain and allow the change. If it's been used
130*5c51f124SMoriah Waterland 	 * then we'll deny the switch & return failed.
131*5c51f124SMoriah Waterland 	 */
132*5c51f124SMoriah Waterland 	if (install_root_exists)
133*5c51f124SMoriah Waterland 		/* If the two install_roots are different - problem */
134*5c51f124SMoriah Waterland 		if (strcmp(install_root, path))
135*5c51f124SMoriah Waterland 			/* We are trying to *change* the install_root */
136*5c51f124SMoriah Waterland 			if (ir_accessed) {
137*5c51f124SMoriah Waterland 				ptext(stderr, gettext(ERR_IRSET), path);
138*5c51f124SMoriah Waterland 				return (0);
139*5c51f124SMoriah Waterland 			} else { /* !ir_accessed */
140*5c51f124SMoriah Waterland 				ptext(stderr, gettext(MSG_IR_REPL), path);
141*5c51f124SMoriah Waterland 				install_root_exists = 0;	/* reset */
142*5c51f124SMoriah Waterland 				install_root = NULL;
143*5c51f124SMoriah Waterland 			}
144*5c51f124SMoriah Waterland 
145*5c51f124SMoriah Waterland 	if (path && *path) {
146*5c51f124SMoriah Waterland 		if (*path != '/') {
147*5c51f124SMoriah Waterland 			ptext(stderr, gettext(ERR_IRNOTABS), path);
148*5c51f124SMoriah Waterland 			return (0);
149*5c51f124SMoriah Waterland 		}
150*5c51f124SMoriah Waterland 
151*5c51f124SMoriah Waterland 		(void) strlcpy(tmp_path, path, sizeof (tmp_path));
152*5c51f124SMoriah Waterland 
153*5c51f124SMoriah Waterland 		canonize(tmp_path);
154*5c51f124SMoriah Waterland 
155*5c51f124SMoriah Waterland 		install_root = tmp_path;
156*5c51f124SMoriah Waterland 
157*5c51f124SMoriah Waterland 		install_root_exists = 1;
158*5c51f124SMoriah Waterland 
159*5c51f124SMoriah Waterland 		install_root_len = strlen(install_root);
160*5c51f124SMoriah Waterland 
161*5c51f124SMoriah Waterland 		/* If install_root is '/' then it's trivial. */
162*5c51f124SMoriah Waterland 		if (install_root_len == 1)
163*5c51f124SMoriah Waterland 			install_root_len = 0;
164*5c51f124SMoriah Waterland 		else
165*5c51f124SMoriah Waterland 			z_set_zone_root(install_root);
166*5c51f124SMoriah Waterland 	} else
167*5c51f124SMoriah Waterland 		install_root_exists = 0;
168*5c51f124SMoriah Waterland 
169*5c51f124SMoriah Waterland 	return (1);
170*5c51f124SMoriah Waterland }
171*5c51f124SMoriah Waterland 
172*5c51f124SMoriah Waterland /*
173*5c51f124SMoriah Waterland  * This routine returns a path with the correct install_root prepended.
174*5c51f124SMoriah Waterland  * if the install_root has been set. NOTE : this allocates memory
175*5c51f124SMoriah Waterland  * which will need to be freed at some point.
176*5c51f124SMoriah Waterland  */
177*5c51f124SMoriah Waterland char *
178*5c51f124SMoriah Waterland fixpath(char *path)
179*5c51f124SMoriah Waterland {
180*5c51f124SMoriah Waterland 	register char *npath_ptr, *ir_ptr;
181*5c51f124SMoriah Waterland 	char *npath = NULL;
182*5c51f124SMoriah Waterland 
183*5c51f124SMoriah Waterland 	if (path && *path) {
184*5c51f124SMoriah Waterland 		if (install_root_exists) {
185*5c51f124SMoriah Waterland 			if ((npath =
186*5c51f124SMoriah Waterland 			    calloc(1, strlen(path) + install_root_len +
187*5c51f124SMoriah Waterland 			    1)) == NULL) {
188*5c51f124SMoriah Waterland 				progerr(gettext(ERR_ALLOCFAILED), "fixpath()");
189*5c51f124SMoriah Waterland 				quit(99);
190*5c51f124SMoriah Waterland 			}
191*5c51f124SMoriah Waterland 
192*5c51f124SMoriah Waterland 			npath_ptr = npath;
193*5c51f124SMoriah Waterland 			ir_ptr = get_inst_root();
194*5c51f124SMoriah Waterland 
195*5c51f124SMoriah Waterland 			while (*ir_ptr)	/* for every char in install_root */
196*5c51f124SMoriah Waterland 				*npath_ptr++ = *ir_ptr++;	/* copy it */
197*5c51f124SMoriah Waterland 
198*5c51f124SMoriah Waterland 			/*
199*5c51f124SMoriah Waterland 			 * If install_root == "/", a concatenation will
200*5c51f124SMoriah Waterland 			 * result in a return value of "//...", same goes
201*5c51f124SMoriah Waterland 			 * for an install_root ending in '/'. So we back
202*5c51f124SMoriah Waterland 			 * over a trailing '/' if it's there.
203*5c51f124SMoriah Waterland 			 */
204*5c51f124SMoriah Waterland 			if (*(npath_ptr - 1) == '/')
205*5c51f124SMoriah Waterland 				npath_ptr--;
206*5c51f124SMoriah Waterland 
207*5c51f124SMoriah Waterland 			if (strcmp(path, "/"))
208*5c51f124SMoriah Waterland 				(void) strcpy(npath_ptr, path);
209*5c51f124SMoriah Waterland 		} else
210*5c51f124SMoriah Waterland 			/*
211*5c51f124SMoriah Waterland 			 * If there's no install root & no client_basedir,
212*5c51f124SMoriah Waterland 			 * then return the path
213*5c51f124SMoriah Waterland 			 */
214*5c51f124SMoriah Waterland 			npath = strdup(path);
215*5c51f124SMoriah Waterland 	} else
216*5c51f124SMoriah Waterland 		/*
217*5c51f124SMoriah Waterland 		 * If there's no path specified, return the install root
218*5c51f124SMoriah Waterland 		 * since no matter what happens, this is where the
219*5c51f124SMoriah Waterland 		 * path will have to start.
220*5c51f124SMoriah Waterland 		 */
221*5c51f124SMoriah Waterland 		if (install_root_exists)
222*5c51f124SMoriah Waterland 			npath = strdup(get_inst_root());
223*5c51f124SMoriah Waterland 
224*5c51f124SMoriah Waterland 	return (npath);
225*5c51f124SMoriah Waterland }
226*5c51f124SMoriah Waterland 
227*5c51f124SMoriah Waterland /*
228*5c51f124SMoriah Waterland  * This routine does what fixpath() does except it's for high-volume
229*5c51f124SMoriah Waterland  * stuff restricted to the instvol() function. By using
230*5c51f124SMoriah Waterland  * pathdup() and pathalloc() memory fragmentation is reduced. Also, the
231*5c51f124SMoriah Waterland  * memory allocated by pathdup() and pathalloc() gets freed at the end
232*5c51f124SMoriah Waterland  * of each volume installed.
233*5c51f124SMoriah Waterland  */
234*5c51f124SMoriah Waterland char *
235*5c51f124SMoriah Waterland fixpath_dup(char *path)
236*5c51f124SMoriah Waterland {
237*5c51f124SMoriah Waterland 	register char *npath_ptr, *ir_ptr;
238*5c51f124SMoriah Waterland 	char *npath = NULL;
239*5c51f124SMoriah Waterland 
240*5c51f124SMoriah Waterland 	if (path && *path) {
241*5c51f124SMoriah Waterland 		if (install_root_exists) {
242*5c51f124SMoriah Waterland 			npath = pathalloc(strlen(path) + install_root_len + 1);
243*5c51f124SMoriah Waterland 
244*5c51f124SMoriah Waterland 			npath_ptr = npath;
245*5c51f124SMoriah Waterland 			ir_ptr = get_inst_root();
246*5c51f124SMoriah Waterland 
247*5c51f124SMoriah Waterland 			while (*ir_ptr)	/* for every char in install_root */
248*5c51f124SMoriah Waterland 				*npath_ptr++ = *ir_ptr++;	/* copy it */
249*5c51f124SMoriah Waterland 
250*5c51f124SMoriah Waterland 			/*
251*5c51f124SMoriah Waterland 			 * If install_root == "/", a concatenation will
252*5c51f124SMoriah Waterland 			 * result in a return value of "//...", same goes
253*5c51f124SMoriah Waterland 			 * for an install_root ending in '/'. So we back
254*5c51f124SMoriah Waterland 			 * over a trailing '/' if it's there.
255*5c51f124SMoriah Waterland 			 */
256*5c51f124SMoriah Waterland 			if (*(npath_ptr - 1) == '/')
257*5c51f124SMoriah Waterland 				npath_ptr--;
258*5c51f124SMoriah Waterland 
259*5c51f124SMoriah Waterland 			if (strcmp(path, "/"))
260*5c51f124SMoriah Waterland 				(void) strcpy(npath_ptr, path);
261*5c51f124SMoriah Waterland 		} else
262*5c51f124SMoriah Waterland 			/*
263*5c51f124SMoriah Waterland 			 * If there's no install root & no client_basedir,
264*5c51f124SMoriah Waterland 			 * then return the path
265*5c51f124SMoriah Waterland 			 */
266*5c51f124SMoriah Waterland 			npath = pathdup(path);
267*5c51f124SMoriah Waterland 	} else
268*5c51f124SMoriah Waterland 		/*
269*5c51f124SMoriah Waterland 		 * If there's no path specified, return the install root
270*5c51f124SMoriah Waterland 		 * since no matter what happens, this is where the
271*5c51f124SMoriah Waterland 		 * path will have to start.
272*5c51f124SMoriah Waterland 		 */
273*5c51f124SMoriah Waterland 		if (install_root_exists)
274*5c51f124SMoriah Waterland 			npath = pathdup(get_inst_root());
275*5c51f124SMoriah Waterland 
276*5c51f124SMoriah Waterland 	return (npath);
277*5c51f124SMoriah Waterland }
278*5c51f124SMoriah Waterland 
279*5c51f124SMoriah Waterland /*
280*5c51f124SMoriah Waterland  * This returns a pointer to a static name. This could be abused.
281*5c51f124SMoriah Waterland  * -- JST (1993-07-21)
282*5c51f124SMoriah Waterland  */
283*5c51f124SMoriah Waterland char *
284*5c51f124SMoriah Waterland get_inst_root(void)
285*5c51f124SMoriah Waterland {
286*5c51f124SMoriah Waterland 	ir_accessed = 1;	/* we can't change it now */
287*5c51f124SMoriah Waterland 	return (install_root);
288*5c51f124SMoriah Waterland }
289*5c51f124SMoriah Waterland 
290*5c51f124SMoriah Waterland /*
291*5c51f124SMoriah Waterland  * This routine takes path and removes install_root from the path
292*5c51f124SMoriah Waterland  * if it has already been prepended. If install_root is not prepended to
293*5c51f124SMoriah Waterland  * path or install_root is '/' or path == NULL then path is returned
294*5c51f124SMoriah Waterland  * as is. If the resulting path is somehow relative, a corrupt
295*5c51f124SMoriah Waterland  * package name error is raised and the program quits. NOTE : This
296*5c51f124SMoriah Waterland  * function usually returns a pointer into the original path
297*5c51f124SMoriah Waterland  * argument. It doesn't allocate new memory. This is possible,
298*5c51f124SMoriah Waterland  * of course, because the path being returned is guaranteed to
299*5c51f124SMoriah Waterland  * be a subset of the original argument unless basedir = '/' in
300*5c51f124SMoriah Waterland  * which case a pointer to a static "/" is returned. See
301*5c51f124SMoriah Waterland  * orig_path() below if you want to be handed a new copy of the
302*5c51f124SMoriah Waterland  * return value.
303*5c51f124SMoriah Waterland  */
304*5c51f124SMoriah Waterland char *
305*5c51f124SMoriah Waterland orig_path_ptr(char *path)
306*5c51f124SMoriah Waterland {
307*5c51f124SMoriah Waterland 	char *retv = NULL;
308*5c51f124SMoriah Waterland 
309*5c51f124SMoriah Waterland 	if (path && *path) {	/* as long as we got an argument */
310*5c51f124SMoriah Waterland 		if (!install_root_exists)	/* if no install_root */
311*5c51f124SMoriah Waterland 			retv = path;		/*   path unchanged */
312*5c51f124SMoriah Waterland 
313*5c51f124SMoriah Waterland 		/*
314*5c51f124SMoriah Waterland 		 * Otherwise, if install_root is really prepended to the path
315*5c51f124SMoriah Waterland 		 * then remove it dealing appropriately with special cases.
316*5c51f124SMoriah Waterland 		 */
317*5c51f124SMoriah Waterland 		else if (strncmp(path, install_root, install_root_len) == 0) {
318*5c51f124SMoriah Waterland 			retv = path + install_root_len;
319*5c51f124SMoriah Waterland 			if (*retv == NULL)
320*5c51f124SMoriah Waterland 				retv = "/";
321*5c51f124SMoriah Waterland 
322*5c51f124SMoriah Waterland 			/*
323*5c51f124SMoriah Waterland 			 * The result will be relative if install_root = '/'.
324*5c51f124SMoriah Waterland 			 * If the basedir path was built legally, then moving
325*5c51f124SMoriah Waterland 			 * the pointer back one character will make it
326*5c51f124SMoriah Waterland 			 * absolute. If that fails then the path we got was
327*5c51f124SMoriah Waterland 			 * incorrectly constructed in the first place.
328*5c51f124SMoriah Waterland 			 */
329*5c51f124SMoriah Waterland 			else if (*retv != '/') {
330*5c51f124SMoriah Waterland 				retv--;
331*5c51f124SMoriah Waterland 				if (*retv != '/') {
332*5c51f124SMoriah Waterland 					progerr(gettext(ERR_PATHNAME));
333*5c51f124SMoriah Waterland 					quit(99);
334*5c51f124SMoriah Waterland 				}
335*5c51f124SMoriah Waterland 			}
336*5c51f124SMoriah Waterland 		} else
337*5c51f124SMoriah Waterland 			retv = path;	/* All else failing, return path. */
338*5c51f124SMoriah Waterland 
339*5c51f124SMoriah Waterland 		canonize(retv);
340*5c51f124SMoriah Waterland 	}
341*5c51f124SMoriah Waterland 
342*5c51f124SMoriah Waterland 	return (retv);
343*5c51f124SMoriah Waterland }
344*5c51f124SMoriah Waterland 
345*5c51f124SMoriah Waterland /*
346*5c51f124SMoriah Waterland  * This function does the same as orig_path_ptr() except that it mallocs
347*5c51f124SMoriah Waterland  * new space and provides a new copy of the original basedir path which
348*5c51f124SMoriah Waterland  * needs to be free()'d one way or another later.
349*5c51f124SMoriah Waterland  */
350*5c51f124SMoriah Waterland char *
351*5c51f124SMoriah Waterland orig_path(char *path)
352*5c51f124SMoriah Waterland {
353*5c51f124SMoriah Waterland 	char *retv;
354*5c51f124SMoriah Waterland 
355*5c51f124SMoriah Waterland 	retv = orig_path_ptr(path);
356*5c51f124SMoriah Waterland 
357*5c51f124SMoriah Waterland 	return ((retv == NULL) ? retv : strdup(retv));
358*5c51f124SMoriah Waterland }
359*5c51f124SMoriah Waterland 
360*5c51f124SMoriah Waterland /*
361*5c51f124SMoriah Waterland  * This function lets us hold onto the environment's version of
362*5c51f124SMoriah Waterland  * CLIENT_BASEDIR for later review by set_client_basedir().
363*5c51f124SMoriah Waterland  */
364*5c51f124SMoriah Waterland void
365*5c51f124SMoriah Waterland set_env_cbdir()
366*5c51f124SMoriah Waterland {
367*5c51f124SMoriah Waterland 	register char *cb_ptr;
368*5c51f124SMoriah Waterland 
369*5c51f124SMoriah Waterland 	cb_ptr = getenv("CLIENT_BASEDIR");
370*5c51f124SMoriah Waterland 
371*5c51f124SMoriah Waterland 	if (cb_ptr && *cb_ptr) {
372*5c51f124SMoriah Waterland 		env_cl_bdir = strdup(cb_ptr);
373*5c51f124SMoriah Waterland 		canonize(env_cl_bdir);
374*5c51f124SMoriah Waterland 	}
375*5c51f124SMoriah Waterland }
376*5c51f124SMoriah Waterland 
377*5c51f124SMoriah Waterland /* ask for the basedir */
378*5c51f124SMoriah Waterland static int
379*5c51f124SMoriah Waterland ask_basedir(char *path, int nointeract)
380*5c51f124SMoriah Waterland {
381*5c51f124SMoriah Waterland 	int n;
382*5c51f124SMoriah Waterland 
383*5c51f124SMoriah Waterland 	if (nointeract) {
384*5c51f124SMoriah Waterland 		progerr(gettext(MSG_REQBASEDIR));
385*5c51f124SMoriah Waterland 		return (5);
386*5c51f124SMoriah Waterland 	} else {
387*5c51f124SMoriah Waterland 		path[0] = '\0';
388*5c51f124SMoriah Waterland 		if (n = ckpath(path, P_ABSOLUTE|P_DIR|P_WRITE,
389*5c51f124SMoriah Waterland 		    basedir, NULL, gettext(MSG_HELP),
390*5c51f124SMoriah Waterland 		    gettext(MSG_PROMPT)))
391*5c51f124SMoriah Waterland 			return (n);	/* FAIL */
392*5c51f124SMoriah Waterland 		orig_basedir =
393*5c51f124SMoriah Waterland 		    expand_path(path);
394*5c51f124SMoriah Waterland 	}
395*5c51f124SMoriah Waterland 	return (0);
396*5c51f124SMoriah Waterland }
397*5c51f124SMoriah Waterland 
398*5c51f124SMoriah Waterland /*
399*5c51f124SMoriah Waterland  * Set the basedir and client_basedir based on install root and config
400*5c51f124SMoriah Waterland  * files. It returns 0 if all OK otherwise returns the error code base
401*5c51f124SMoriah Waterland  * appropriate to the problem.
402*5c51f124SMoriah Waterland  */
403*5c51f124SMoriah Waterland int
404*5c51f124SMoriah Waterland set_basedirs(int reloc, char *adm_basedir, char *pkginst, int nointeract)
405*5c51f124SMoriah Waterland {
406*5c51f124SMoriah Waterland 	char	path[PATH_MAX];
407*5c51f124SMoriah Waterland 	int	n;
408*5c51f124SMoriah Waterland 
409*5c51f124SMoriah Waterland 	relocatable = reloc;
410*5c51f124SMoriah Waterland 
411*5c51f124SMoriah Waterland 	/*
412*5c51f124SMoriah Waterland 	 * If there are no relocatable files basedir is probably meaningless
413*5c51f124SMoriah Waterland 	 * so we skip ahead to the simple tests. Otherwise we do the twisted
414*5c51f124SMoriah Waterland 	 * stuff below. The BASEDIR is set based on the following heirarchy :
415*5c51f124SMoriah Waterland 	 *	1. The entry in the admin file
416*5c51f124SMoriah Waterland 	 *	2. The entry in the pkginfo file delivered on the medium
417*5c51f124SMoriah Waterland 	 *	3. The entry in the already installed pkginfo file
418*5c51f124SMoriah Waterland 	 *	4. ask
419*5c51f124SMoriah Waterland 	 * If it's not a relocatable package, we go with whatever seems
420*5c51f124SMoriah Waterland 	 * reasonable; if it's relocatable and we've exhausted our
421*5c51f124SMoriah Waterland 	 * options, we ask.
422*5c51f124SMoriah Waterland 	 */
423*5c51f124SMoriah Waterland 	if (reloc) {
424*5c51f124SMoriah Waterland 		int is_adm_basedir = (adm_basedir && *adm_basedir);
425*5c51f124SMoriah Waterland 		int is_update = 0;
426*5c51f124SMoriah Waterland 		int is_ask = 0;
427*5c51f124SMoriah Waterland 
428*5c51f124SMoriah Waterland 		if (is_adm_basedir) {
429*5c51f124SMoriah Waterland 			if (strcmp(adm_basedir, "update") == 0) {
430*5c51f124SMoriah Waterland 				is_update = 1;
431*5c51f124SMoriah Waterland 				is_ask = 1;
432*5c51f124SMoriah Waterland 			} else if (strcmp(adm_basedir, "ask") == 0)
433*5c51f124SMoriah Waterland 				is_ask = 1;
434*5c51f124SMoriah Waterland 		}
435*5c51f124SMoriah Waterland 
436*5c51f124SMoriah Waterland 		/*
437*5c51f124SMoriah Waterland 		 * If there's a BASEDIR in the admin file & it's a valid
438*5c51f124SMoriah Waterland 		 * absolute pathname, use it.
439*5c51f124SMoriah Waterland 		 */
440*5c51f124SMoriah Waterland 		if (is_adm_basedir && strchr("/$", *adm_basedir))
441*5c51f124SMoriah Waterland 			orig_basedir = expand_path(adm_basedir);
442*5c51f124SMoriah Waterland 
443*5c51f124SMoriah Waterland 		/* If admin says 'ask regardless', ask and continue */
444*5c51f124SMoriah Waterland 		else if (is_adm_basedir && is_ask) {
445*5c51f124SMoriah Waterland 			if (n = ask_basedir(path, nointeract))
446*5c51f124SMoriah Waterland 				return (n);
447*5c51f124SMoriah Waterland 			if (is_update &&
448*5c51f124SMoriah Waterland 			    strcmp(orig_basedir,
449*5c51f124SMoriah Waterland 			    (basedir = getenv("BASEDIR"))) != 0) {
450*5c51f124SMoriah Waterland 				progerr(gettext(ERR_ASKBD),
451*5c51f124SMoriah Waterland 				    getenv("PKG"), basedir, orig_basedir);
452*5c51f124SMoriah Waterland 				quit(4);
453*5c51f124SMoriah Waterland 			}
454*5c51f124SMoriah Waterland 		}
455*5c51f124SMoriah Waterland 		/*
456*5c51f124SMoriah Waterland 		 * If it isn't the only other valid option,
457*5c51f124SMoriah Waterland 		 * namely 'default', quit FAIL.
458*5c51f124SMoriah Waterland 		 */
459*5c51f124SMoriah Waterland 		else if (is_adm_basedir &&
460*5c51f124SMoriah Waterland 		    strcmp(adm_basedir, "default") != 0) {
461*5c51f124SMoriah Waterland 			progerr(gettext(ERR_ADMIN_INVAL));
462*5c51f124SMoriah Waterland 			return (1);
463*5c51f124SMoriah Waterland 
464*5c51f124SMoriah Waterland 		/*
465*5c51f124SMoriah Waterland 		 * OK, the admin file has no preference, so we go to the
466*5c51f124SMoriah Waterland 		 * other sources.
467*5c51f124SMoriah Waterland 		 */
468*5c51f124SMoriah Waterland 		} else {
469*5c51f124SMoriah Waterland 			/*
470*5c51f124SMoriah Waterland 			 * Check to see if BASEDIR is set in the environment
471*5c51f124SMoriah Waterland 			 * (probably from the pkginfo file on the installation
472*5c51f124SMoriah Waterland 			 * medium).
473*5c51f124SMoriah Waterland 			 */
474*5c51f124SMoriah Waterland 			basedir = getenv("BASEDIR");
475*5c51f124SMoriah Waterland 			if (basedir && *basedir)
476*5c51f124SMoriah Waterland 				orig_basedir = expand_path(basedir);
477*5c51f124SMoriah Waterland 			else {
478*5c51f124SMoriah Waterland 				/*
479*5c51f124SMoriah Waterland 				 * Check to see if the package BASEDIR was
480*5c51f124SMoriah Waterland 				 * already defined during a previous
481*5c51f124SMoriah Waterland 				 * installation of this package instance. The
482*5c51f124SMoriah Waterland 				 * function below looks for an installed
483*5c51f124SMoriah Waterland 				 * pkginfo file and scans it.
484*5c51f124SMoriah Waterland 				 */
485*5c51f124SMoriah Waterland 				basedir = pkgparam(pkginst, "BASEDIR");
486*5c51f124SMoriah Waterland 				if (basedir && *basedir)
487*5c51f124SMoriah Waterland 					orig_basedir = expand_path(basedir);
488*5c51f124SMoriah Waterland 				else if (n = ask_basedir(path, nointeract))
489*5c51f124SMoriah Waterland 					return (n);
490*5c51f124SMoriah Waterland 			}
491*5c51f124SMoriah Waterland 		}
492*5c51f124SMoriah Waterland 	} else {	/* not relocatable */
493*5c51f124SMoriah Waterland 		/*
494*5c51f124SMoriah Waterland 		 * Since all paths are absolute the only reason to have a
495*5c51f124SMoriah Waterland 		 * basedir is if there's an install root meaning there's
496*5c51f124SMoriah Waterland 		 * really a basedir relative to this host or this package is
497*5c51f124SMoriah Waterland 		 * absolute only because it's sparse in which case we're
498*5c51f124SMoriah Waterland 		 * interested in the prior basedir. So we next check for a
499*5c51f124SMoriah Waterland 		 * prior basedir and then an install root.
500*5c51f124SMoriah Waterland 		 */
501*5c51f124SMoriah Waterland 		basedir = pkgparam(pkginst, "BASEDIR");
502*5c51f124SMoriah Waterland 		if (basedir && *basedir)
503*5c51f124SMoriah Waterland 			orig_basedir = expand_path(basedir);
504*5c51f124SMoriah Waterland 
505*5c51f124SMoriah Waterland 		else if (install_root_exists)
506*5c51f124SMoriah Waterland 			/*
507*5c51f124SMoriah Waterland 			 * If we have a basedir *only because*
508*5c51f124SMoriah Waterland 			 * we have an install_root, we need to
509*5c51f124SMoriah Waterland 			 * set orig_basedir to '/' to simplify
510*5c51f124SMoriah Waterland 			 * later attempts to force
511*5c51f124SMoriah Waterland 			 * client_basedir.
512*5c51f124SMoriah Waterland 			 */
513*5c51f124SMoriah Waterland 			orig_basedir = "/";
514*5c51f124SMoriah Waterland 		else {
515*5c51f124SMoriah Waterland 			eval_valid++;	/* we can run eval_path() now */
516*5c51f124SMoriah Waterland 			return (0);	/* fixpath below unnecessary */
517*5c51f124SMoriah Waterland 		}
518*5c51f124SMoriah Waterland 	}
519*5c51f124SMoriah Waterland 
520*5c51f124SMoriah Waterland 	basedir_exists = 1;
521*5c51f124SMoriah Waterland 
522*5c51f124SMoriah Waterland 	basedir = fixpath(orig_basedir);
523*5c51f124SMoriah Waterland 
524*5c51f124SMoriah Waterland 	/*
525*5c51f124SMoriah Waterland 	 * If basedir == "/" then there's no need for a "/" between
526*5c51f124SMoriah Waterland 	 * it and the rest of the path.
527*5c51f124SMoriah Waterland 	 */
528*5c51f124SMoriah Waterland 	if (strcmp(basedir, "/") == 0)
529*5c51f124SMoriah Waterland 		base_sepr = 0;
530*5c51f124SMoriah Waterland 
531*5c51f124SMoriah Waterland 	if (set_client_basedir() == 0) {
532*5c51f124SMoriah Waterland 		progerr(gettext(ERR_NO_CL_BD));
533*5c51f124SMoriah Waterland 		return (1);
534*5c51f124SMoriah Waterland 	}
535*5c51f124SMoriah Waterland 
536*5c51f124SMoriah Waterland 	eval_valid++;	/* we've confirmed the validity of everything */
537*5c51f124SMoriah Waterland 
538*5c51f124SMoriah Waterland 	return (0);
539*5c51f124SMoriah Waterland }
540*5c51f124SMoriah Waterland 
541*5c51f124SMoriah Waterland /*
542*5c51f124SMoriah Waterland  * Make a directory from a path and all necessary directories above it as
543*5c51f124SMoriah Waterland  * needed.
544*5c51f124SMoriah Waterland  */
545*5c51f124SMoriah Waterland int
546*5c51f124SMoriah Waterland mkpath(char *p)
547*5c51f124SMoriah Waterland {
548*5c51f124SMoriah Waterland 	char	*pt;
549*5c51f124SMoriah Waterland 
550*5c51f124SMoriah Waterland 	/* if entire path exists, return o.k. */
551*5c51f124SMoriah Waterland 
552*5c51f124SMoriah Waterland 	if (access(p, F_OK) == 0) {
553*5c51f124SMoriah Waterland 		return (0);
554*5c51f124SMoriah Waterland 	}
555*5c51f124SMoriah Waterland 
556*5c51f124SMoriah Waterland 	/* entire path not there - check components and create */
557*5c51f124SMoriah Waterland 
558*5c51f124SMoriah Waterland 	pt = (*p == '/') ? p+1 : p;
559*5c51f124SMoriah Waterland 	do {
560*5c51f124SMoriah Waterland 		if (pt = strchr(pt, '/')) {
561*5c51f124SMoriah Waterland 			*pt = '\0';
562*5c51f124SMoriah Waterland 		}
563*5c51f124SMoriah Waterland 		if ((access(p, F_OK) != 0) && (mkdir(p, 0755) != 0)) {
564*5c51f124SMoriah Waterland 			return (-1);
565*5c51f124SMoriah Waterland 		}
566*5c51f124SMoriah Waterland 		if (pt) {
567*5c51f124SMoriah Waterland 			*pt++ = '/';
568*5c51f124SMoriah Waterland 		}
569*5c51f124SMoriah Waterland 	} while (pt);
570*5c51f124SMoriah Waterland 
571*5c51f124SMoriah Waterland 	return (0);
572*5c51f124SMoriah Waterland }
573*5c51f124SMoriah Waterland 
574*5c51f124SMoriah Waterland /* This makes the required base directory if necessary */
575*5c51f124SMoriah Waterland void
576*5c51f124SMoriah Waterland mkbasedir(int flag, char *basedir)
577*5c51f124SMoriah Waterland {
578*5c51f124SMoriah Waterland 	char	ans[MAX_INPUT];
579*5c51f124SMoriah Waterland 	int	n;
580*5c51f124SMoriah Waterland 
581*5c51f124SMoriah Waterland 	/*
582*5c51f124SMoriah Waterland 	 * If a base directory is called for but there's no such directory on
583*5c51f124SMoriah Waterland 	 * the system, deal with that issue.
584*5c51f124SMoriah Waterland 	 */
585*5c51f124SMoriah Waterland 	if (is_a_basedir() && isdir(basedir)) {
586*5c51f124SMoriah Waterland 		if (flag) {	/* Interaction is OK. */
587*5c51f124SMoriah Waterland 			/*
588*5c51f124SMoriah Waterland 			 * If there's a non-directory object in the way, ask.
589*5c51f124SMoriah Waterland 			 */
590*5c51f124SMoriah Waterland 			if (access(basedir, F_OK) == 0) {
591*5c51f124SMoriah Waterland 				ptext(stderr, gettext(MSG_ISAFILE), basedir);
592*5c51f124SMoriah Waterland 
593*5c51f124SMoriah Waterland 				if (n = ckyorn(ans, NULL, NULL, NULL,
594*5c51f124SMoriah Waterland 				    gettext(MSG_YORNFILE)))
595*5c51f124SMoriah Waterland 					quit(n);
596*5c51f124SMoriah Waterland 				if (strchr("yY", *ans) == NULL)
597*5c51f124SMoriah Waterland 					quit(3);
598*5c51f124SMoriah Waterland 
599*5c51f124SMoriah Waterland 				/*
600*5c51f124SMoriah Waterland 				 * It isn't a directory, so we'll just unlink
601*5c51f124SMoriah Waterland 				 * it.
602*5c51f124SMoriah Waterland 				 */
603*5c51f124SMoriah Waterland 				if (unlink(basedir) == -1) {
604*5c51f124SMoriah Waterland 					progerr(gettext(ERR_NODELETE),
605*5c51f124SMoriah Waterland 					    basedir);
606*5c51f124SMoriah Waterland 					quit(99);
607*5c51f124SMoriah Waterland 				}
608*5c51f124SMoriah Waterland 
609*5c51f124SMoriah Waterland 			} else {
610*5c51f124SMoriah Waterland 				ptext(stderr, gettext(MSG_MUSTEXIST), basedir);
611*5c51f124SMoriah Waterland 
612*5c51f124SMoriah Waterland 				if (n = ckyorn(ans, NULL, NULL, NULL,
613*5c51f124SMoriah Waterland 				    gettext(MSG_YORNPRMPT)))
614*5c51f124SMoriah Waterland 					quit(n);
615*5c51f124SMoriah Waterland 				if (strchr("yY", *ans) == NULL)
616*5c51f124SMoriah Waterland 					quit(3);
617*5c51f124SMoriah Waterland 			}
618*5c51f124SMoriah Waterland 		}
619*5c51f124SMoriah Waterland 
620*5c51f124SMoriah Waterland 		if (access(basedir, F_OK) == 0 || mkpath(basedir)) {
621*5c51f124SMoriah Waterland 			progerr(gettext(ERR_MKBASE), basedir);
622*5c51f124SMoriah Waterland 			quit(99);
623*5c51f124SMoriah Waterland 		}
624*5c51f124SMoriah Waterland 	}
625*5c51f124SMoriah Waterland }
626*5c51f124SMoriah Waterland 
627*5c51f124SMoriah Waterland /*
628*5c51f124SMoriah Waterland  * Create a client_basedir if it is appropriate. If all goes well, resulting
629*5c51f124SMoriah Waterland  * in either a valid client_basedir or a valid lack thereof, it returns 1.
630*5c51f124SMoriah Waterland  * If there is an irreconcileable conflict, it returns 0.
631*5c51f124SMoriah Waterland  */
632*5c51f124SMoriah Waterland static int
633*5c51f124SMoriah Waterland set_client_basedir(void)
634*5c51f124SMoriah Waterland {
635*5c51f124SMoriah Waterland 	if (install_root_exists) {
636*5c51f124SMoriah Waterland 		if (basedir_exists)
637*5c51f124SMoriah Waterland 			client_basedir = strdup(orig_basedir);
638*5c51f124SMoriah Waterland 		else
639*5c51f124SMoriah Waterland 			client_basedir = "/";
640*5c51f124SMoriah Waterland 		client_basedir_exists = 1;
641*5c51f124SMoriah Waterland 	}
642*5c51f124SMoriah Waterland 
643*5c51f124SMoriah Waterland 	/*
644*5c51f124SMoriah Waterland 	 * In response to an agreement associated with bug report #1133956,
645*5c51f124SMoriah Waterland 	 * CLIENT_BASEDIR will be defined in all cases where BASEDIR is
646*5c51f124SMoriah Waterland 	 * defined until the on1094 release. For on1094 delete the else if
647*5c51f124SMoriah Waterland 	 * and associated expressions below. -- JST (6/25/1993)
648*5c51f124SMoriah Waterland 	 */
649*5c51f124SMoriah Waterland 	else if (basedir_exists) {
650*5c51f124SMoriah Waterland 		client_basedir = strdup(basedir);
651*5c51f124SMoriah Waterland 		client_basedir_exists = 1;
652*5c51f124SMoriah Waterland 	}
653*5c51f124SMoriah Waterland 
654*5c51f124SMoriah Waterland 	/*
655*5c51f124SMoriah Waterland 	 * At this point we may or may not have a client_basedir defined. Now
656*5c51f124SMoriah Waterland 	 * we need to check for one in the environment & make sure it syncs
657*5c51f124SMoriah Waterland 	 * up with prior findings. If there's no other client_basedir defined,
658*5c51f124SMoriah Waterland 	 * the environment defines it.
659*5c51f124SMoriah Waterland 	 */
660*5c51f124SMoriah Waterland 	if (env_cl_bdir && *env_cl_bdir) {
661*5c51f124SMoriah Waterland 		if (client_basedir_exists) {
662*5c51f124SMoriah Waterland 			/* If the two client basedirs mismatch, return fail */
663*5c51f124SMoriah Waterland 			if (strcmp(client_basedir, env_cl_bdir)) {
664*5c51f124SMoriah Waterland 				ptext(stderr, gettext(ERR_CL_MIS),
665*5c51f124SMoriah Waterland 				    client_basedir, env_cl_bdir);
666*5c51f124SMoriah Waterland 				return (0);
667*5c51f124SMoriah Waterland 			}
668*5c51f124SMoriah Waterland 		} else {
669*5c51f124SMoriah Waterland 			client_basedir = env_cl_bdir;
670*5c51f124SMoriah Waterland 			client_basedir_exists = 1;
671*5c51f124SMoriah Waterland 		}
672*5c51f124SMoriah Waterland 	}
673*5c51f124SMoriah Waterland 
674*5c51f124SMoriah Waterland 	return (1);
675*5c51f124SMoriah Waterland }
676*5c51f124SMoriah Waterland 
677*5c51f124SMoriah Waterland static char *
678*5c51f124SMoriah Waterland expand_path(char *path)
679*5c51f124SMoriah Waterland {
680*5c51f124SMoriah Waterland 	char	path_buf[PATH_MAX];
681*5c51f124SMoriah Waterland 
682*5c51f124SMoriah Waterland 	if (!path || !*path)
683*5c51f124SMoriah Waterland 		return (path);
684*5c51f124SMoriah Waterland 
685*5c51f124SMoriah Waterland 	(void) strlcpy(path_buf, path, sizeof (path_buf));
686*5c51f124SMoriah Waterland 	mappath(getmapmode(), path_buf);
687*5c51f124SMoriah Waterland 	canonize(path_buf);
688*5c51f124SMoriah Waterland 
689*5c51f124SMoriah Waterland 	return (qstrdup(path_buf));
690*5c51f124SMoriah Waterland }
691*5c51f124SMoriah Waterland 
692*5c51f124SMoriah Waterland char *
693*5c51f124SMoriah Waterland get_basedir(void)
694*5c51f124SMoriah Waterland {
695*5c51f124SMoriah Waterland 	return (basedir);
696*5c51f124SMoriah Waterland }
697*5c51f124SMoriah Waterland 
698*5c51f124SMoriah Waterland char *
699*5c51f124SMoriah Waterland get_client_basedir(void)
700*5c51f124SMoriah Waterland {
701*5c51f124SMoriah Waterland 	return (client_basedir);
702*5c51f124SMoriah Waterland }
703*5c51f124SMoriah Waterland 
704*5c51f124SMoriah Waterland /*
705*5c51f124SMoriah Waterland  * This function returns the basedir that is appropriate for this package's
706*5c51f124SMoriah Waterland  * pkginfo file.
707*5c51f124SMoriah Waterland  */
708*5c51f124SMoriah Waterland char *
709*5c51f124SMoriah Waterland get_info_basedir(void)
710*5c51f124SMoriah Waterland {
711*5c51f124SMoriah Waterland 	if (install_root_exists)
712*5c51f124SMoriah Waterland 		return (client_basedir);
713*5c51f124SMoriah Waterland 	else if (basedir_exists)
714*5c51f124SMoriah Waterland 		return (basedir);
715*5c51f124SMoriah Waterland 	else
716*5c51f124SMoriah Waterland 		return (NULL);
717*5c51f124SMoriah Waterland }
718*5c51f124SMoriah Waterland 
719*5c51f124SMoriah Waterland int
720*5c51f124SMoriah Waterland is_an_inst_root(void)
721*5c51f124SMoriah Waterland {
722*5c51f124SMoriah Waterland 	return (install_root_exists);
723*5c51f124SMoriah Waterland }
724*5c51f124SMoriah Waterland 
725*5c51f124SMoriah Waterland int
726*5c51f124SMoriah Waterland is_a_basedir(void)
727*5c51f124SMoriah Waterland {
728*5c51f124SMoriah Waterland 	return (basedir_exists);
729*5c51f124SMoriah Waterland }
730*5c51f124SMoriah Waterland 
731*5c51f124SMoriah Waterland int
732*5c51f124SMoriah Waterland is_relocatable(void)
733*5c51f124SMoriah Waterland {
734*5c51f124SMoriah Waterland 	return (relocatable);
735*5c51f124SMoriah Waterland }
736*5c51f124SMoriah Waterland 
737*5c51f124SMoriah Waterland int
738*5c51f124SMoriah Waterland is_a_cl_basedir(void)
739*5c51f124SMoriah Waterland {
740*5c51f124SMoriah Waterland 	return (client_basedir_exists);
741*5c51f124SMoriah Waterland }
742*5c51f124SMoriah Waterland 
743*5c51f124SMoriah Waterland /*
744*5c51f124SMoriah Waterland  * Since calls to putparam() become valid long after much of the above
745*5c51f124SMoriah Waterland  * code has run, this routine allows the insertion of these key
746*5c51f124SMoriah Waterland  * environment variables without passing a bunch of pointers.
747*5c51f124SMoriah Waterland  */
748*5c51f124SMoriah Waterland void
749*5c51f124SMoriah Waterland put_path_params(void)
750*5c51f124SMoriah Waterland {
751*5c51f124SMoriah Waterland 	if (install_root_exists)
752*5c51f124SMoriah Waterland 		putparam("PKG_INSTALL_ROOT", get_inst_root());
753*5c51f124SMoriah Waterland 
754*5c51f124SMoriah Waterland 	if (basedir_exists)
755*5c51f124SMoriah Waterland 		putparam("BASEDIR", basedir);
756*5c51f124SMoriah Waterland 
757*5c51f124SMoriah Waterland 	if (client_basedir_exists)
758*5c51f124SMoriah Waterland 		putparam("CLIENT_BASEDIR", client_basedir);
759*5c51f124SMoriah Waterland }
760*5c51f124SMoriah Waterland 
761*5c51f124SMoriah Waterland /*
762*5c51f124SMoriah Waterland  * This fills three pointers and a buffer which contains the longest
763*5c51f124SMoriah Waterland  * possible path (with install_root and basedir prepended. The pointers
764*5c51f124SMoriah Waterland  * are to the subpaths within the string. This was added so that the
765*5c51f124SMoriah Waterland  * eptlist could be produced with all relevant paths defined without
766*5c51f124SMoriah Waterland  * repeated calls and string scans. For example, given a path of
767*5c51f124SMoriah Waterland  * haberdasher/crute we may return
768*5c51f124SMoriah Waterland  *
769*5c51f124SMoriah Waterland  *	server_ptr -----> /export/root/client1/opt/SUNWhab/haberdasher/crute
770*5c51f124SMoriah Waterland  *                                            |            |
771*5c51f124SMoriah Waterland  *	client_ptr ---------------------------             |
772*5c51f124SMoriah Waterland  *	map_ptr -------------------------------------------
773*5c51f124SMoriah Waterland  *
774*5c51f124SMoriah Waterland  * We construct the new path based upon the established environment
775*5c51f124SMoriah Waterland  * and the type of path that was passed. Here are the possibilities:
776*5c51f124SMoriah Waterland  *
777*5c51f124SMoriah Waterland  *   |					| relative path	| absolute path	|
778*5c51f124SMoriah Waterland  *   |	--------------------------------|---------------|---------------|
779*5c51f124SMoriah Waterland  *   |	is_an_inst_root			|	1	|	2	|
780*5c51f124SMoriah Waterland  *   V	! an_inst_root && is_a_basedir	|	1	|	3	|
781*5c51f124SMoriah Waterland  *	! an_inst_root && ! a_basedir	|	X	|	3	|
782*5c51f124SMoriah Waterland  *
783*5c51f124SMoriah Waterland  * METHOD
784*5c51f124SMoriah Waterland  * 1. Prepend the basedir to the path (the basedir is guaranteed to exist
785*5c51f124SMoriah Waterland  *	whenever there's an install_root).
786*5c51f124SMoriah Waterland  *
787*5c51f124SMoriah Waterland  * 2. Prepend the install_root (not the basedir) to the path
788*5c51f124SMoriah Waterland  *
789*5c51f124SMoriah Waterland  * 3. Return the path as unchanged.
790*5c51f124SMoriah Waterland  *
791*5c51f124SMoriah Waterland  * X. THIS CAN'T HAPPEN
792*5c51f124SMoriah Waterland  */
793*5c51f124SMoriah Waterland int
794*5c51f124SMoriah Waterland eval_path(char **server_ptr, char **client_ptr, char **map_ptr, char *path)
795*5c51f124SMoriah Waterland {
796*5c51f124SMoriah Waterland 	static int client_offset;
797*5c51f124SMoriah Waterland 	static int offsets_valid, retcode;
798*5c51f124SMoriah Waterland 	int path_size;
799*5c51f124SMoriah Waterland 
800*5c51f124SMoriah Waterland 	if (!offsets_valid) {
801*5c51f124SMoriah Waterland 		/*
802*5c51f124SMoriah Waterland 		 * This is the offset from the beginning of the evaluated
803*5c51f124SMoriah Waterland 		 * path to the start of the relative path. Note that we
804*5c51f124SMoriah Waterland 		 * are accounting for the '/' inserted between the
805*5c51f124SMoriah Waterland 		 * basedir and the path with the '+ 1'. If there is a
806*5c51f124SMoriah Waterland 		 * relative path, then there is always a basedir. The
807*5c51f124SMoriah Waterland 		 * only way this will come up '0' is if this is an
808*5c51f124SMoriah Waterland 		 * absolute package.
809*5c51f124SMoriah Waterland 		 */
810*5c51f124SMoriah Waterland 		orig_offset_rel = (is_a_basedir()) ? (strlen(basedir) +
811*5c51f124SMoriah Waterland 		    base_sepr) : 0;
812*5c51f124SMoriah Waterland 
813*5c51f124SMoriah Waterland 		/*
814*5c51f124SMoriah Waterland 		 * This is the position of the client-relative path
815*5c51f124SMoriah Waterland 		 * in that it points to the '/' beginning the base
816*5c51f124SMoriah Waterland 		 * directory or the absolute path. Once the basedir has
817*5c51f124SMoriah Waterland 		 * been afixed, the path is absolute. For that reason,
818*5c51f124SMoriah Waterland 		 * the client path is the same thing as the original path
819*5c51f124SMoriah Waterland 		 * if it were absolute.
820*5c51f124SMoriah Waterland 		 */
821*5c51f124SMoriah Waterland 		client_offset = (is_an_inst_root()) ? install_root_len : 0;
822*5c51f124SMoriah Waterland 
823*5c51f124SMoriah Waterland 		offsets_valid = 1;
824*5c51f124SMoriah Waterland 	}
825*5c51f124SMoriah Waterland 
826*5c51f124SMoriah Waterland 	/*
827*5c51f124SMoriah Waterland 	 * If we've evaluated the base directory and come up trumps,
828*5c51f124SMoriah Waterland 	 * then we can procede with this operation, otherwise, the
829*5c51f124SMoriah Waterland 	 * available data is too ambiguous to resolve the issue.
830*5c51f124SMoriah Waterland 	 */
831*5c51f124SMoriah Waterland 	if (eval_valid) {
832*5c51f124SMoriah Waterland 		if (RELATIVE(path)) {
833*5c51f124SMoriah Waterland 			if (relocatable) {
834*5c51f124SMoriah Waterland 				/*
835*5c51f124SMoriah Waterland 				 * Figure out how long our buffer will
836*5c51f124SMoriah Waterland 				 * have to be.
837*5c51f124SMoriah Waterland 				 */
838*5c51f124SMoriah Waterland 				path_size = orig_offset_rel + strlen(path);
839*5c51f124SMoriah Waterland 
840*5c51f124SMoriah Waterland 				(*server_ptr) = pathalloc(path_size);
841*5c51f124SMoriah Waterland 
842*5c51f124SMoriah Waterland 				*client_ptr = *server_ptr + client_offset;
843*5c51f124SMoriah Waterland 
844*5c51f124SMoriah Waterland 				if (map_ptr)
845*5c51f124SMoriah Waterland 					*map_ptr = *server_ptr +
846*5c51f124SMoriah Waterland 					    orig_offset_rel;
847*5c51f124SMoriah Waterland 
848*5c51f124SMoriah Waterland 				/* LINTED warning: variable format specifier */
849*5c51f124SMoriah Waterland 				(void) snprintf(*server_ptr, path_size+1,
850*5c51f124SMoriah Waterland 					rel_fmt[base_sepr], basedir, path);
851*5c51f124SMoriah Waterland 			} else {
852*5c51f124SMoriah Waterland 				ptext(stderr, gettext(ERR_RELINABS), path);
853*5c51f124SMoriah Waterland 				retcode = 0;
854*5c51f124SMoriah Waterland 			}
855*5c51f124SMoriah Waterland 		} else {	/* NOT RELATIVE */
856*5c51f124SMoriah Waterland 			*server_ptr = fixpath_dup(path);
857*5c51f124SMoriah Waterland 
858*5c51f124SMoriah Waterland 			if ((*client_ptr = *server_ptr + client_offset) == NULL)
859*5c51f124SMoriah Waterland 				*client_ptr = "/";
860*5c51f124SMoriah Waterland 
861*5c51f124SMoriah Waterland 			if (map_ptr)
862*5c51f124SMoriah Waterland 				*map_ptr = *client_ptr;
863*5c51f124SMoriah Waterland 		}
864*5c51f124SMoriah Waterland 
865*5c51f124SMoriah Waterland 		retcode = 1;
866*5c51f124SMoriah Waterland 	} else {
867*5c51f124SMoriah Waterland 		ptext(stderr, gettext(ERR_AMBDIRS));
868*5c51f124SMoriah Waterland 		retcode = 0;
869*5c51f124SMoriah Waterland 	}
870*5c51f124SMoriah Waterland 
871*5c51f124SMoriah Waterland 	return (retcode);
872*5c51f124SMoriah Waterland }
873*5c51f124SMoriah Waterland 
874*5c51f124SMoriah Waterland void
875*5c51f124SMoriah Waterland export_client_env(char *root_path)
876*5c51f124SMoriah Waterland {
877*5c51f124SMoriah Waterland 	char	*inst_release_path;
878*5c51f124SMoriah Waterland 	char	*key;
879*5c51f124SMoriah Waterland 	char	*value;
880*5c51f124SMoriah Waterland 	FILE	*inst_fp;
881*5c51f124SMoriah Waterland 	size_t	len;
882*5c51f124SMoriah Waterland 
883*5c51f124SMoriah Waterland 	/*
884*5c51f124SMoriah Waterland 	 * Put the variables found in a clients INST_RELEASE file into the
885*5c51f124SMoriah Waterland 	 * package environment so procedure scripts can know what
886*5c51f124SMoriah Waterland 	 * release/version/revision a client is running. Also this function
887*5c51f124SMoriah Waterland 	 * doesn't return state since the INST_RELEASE file may not exist in
888*5c51f124SMoriah Waterland 	 * some package installation environments
889*5c51f124SMoriah Waterland 	 */
890*5c51f124SMoriah Waterland 
891*5c51f124SMoriah Waterland 	len = strlen(root_path) + strlen(INST_RELEASE) + 2;
892*5c51f124SMoriah Waterland 
893*5c51f124SMoriah Waterland 	inst_release_path = (char *)malloc(len);
894*5c51f124SMoriah Waterland 
895*5c51f124SMoriah Waterland 	key = (char *)malloc(PATH_MAX);
896*5c51f124SMoriah Waterland 
897*5c51f124SMoriah Waterland 	(void) snprintf(inst_release_path, len, "%s/%s", root_path,
898*5c51f124SMoriah Waterland 				INST_RELEASE);
899*5c51f124SMoriah Waterland 
900*5c51f124SMoriah Waterland 	if ((inst_fp = fopen(inst_release_path, "r")) != NULL) {
901*5c51f124SMoriah Waterland 		while (value = fpkgparam(inst_fp, key)) {
902*5c51f124SMoriah Waterland 			if (strcmp(key, "OS") == 0) {
903*5c51f124SMoriah Waterland 				putparam("PKG_CLIENT_OS", value);
904*5c51f124SMoriah Waterland 			} else if (strcmp(key, "VERSION") == 0) {
905*5c51f124SMoriah Waterland 				putparam("PKG_CLIENT_VERSION", value);
906*5c51f124SMoriah Waterland 			} else if (strcmp(key, "REV") == 0) {
907*5c51f124SMoriah Waterland 				putparam("PKG_CLIENT_REVISION", value);
908*5c51f124SMoriah Waterland 			}
909*5c51f124SMoriah Waterland 			*key = '\0';
910*5c51f124SMoriah Waterland 		}
911*5c51f124SMoriah Waterland 		(void) fclose(inst_fp);
912*5c51f124SMoriah Waterland 	}
913*5c51f124SMoriah Waterland 	free(inst_release_path);
914*5c51f124SMoriah Waterland 	free(key);
915*5c51f124SMoriah Waterland }
916*5c51f124SMoriah Waterland 
917*5c51f124SMoriah Waterland /*
918*5c51f124SMoriah Waterland  * Increment variable indicating the installation is from a partially spooled
919*5c51f124SMoriah Waterland  * package.
920*5c51f124SMoriah Waterland  */
921*5c51f124SMoriah Waterland void
922*5c51f124SMoriah Waterland set_partial_inst(void)
923*5c51f124SMoriah Waterland {
924*5c51f124SMoriah Waterland 	partial_inst++;
925*5c51f124SMoriah Waterland }
926*5c51f124SMoriah Waterland 
927*5c51f124SMoriah Waterland /*
928*5c51f124SMoriah Waterland  * Return variable indicating that the installation is from a partially spooled
929*5c51f124SMoriah Waterland  * package.
930*5c51f124SMoriah Waterland  * Returns:  !0 for true
931*5c51f124SMoriah Waterland  *           0 for false
932*5c51f124SMoriah Waterland  */
933*5c51f124SMoriah Waterland int
934*5c51f124SMoriah Waterland is_partial_inst(void)
935*5c51f124SMoriah Waterland {
936*5c51f124SMoriah Waterland 	return (partial_inst);
937*5c51f124SMoriah Waterland }
938*5c51f124SMoriah Waterland 
939*5c51f124SMoriah Waterland /*
940*5c51f124SMoriah Waterland  * Increment variable indicating that only the depend and pkginfo DB's are to be
941*5c51f124SMoriah Waterland  * updated
942*5c51f124SMoriah Waterland  */
943*5c51f124SMoriah Waterland 
944*5c51f124SMoriah Waterland void
945*5c51f124SMoriah Waterland set_depend_pkginfo_DB(boolean_t a_setting)
946*5c51f124SMoriah Waterland {
947*5c51f124SMoriah Waterland 	depend_pkginfo_DB = a_setting;
948*5c51f124SMoriah Waterland }
949*5c51f124SMoriah Waterland 
950*5c51f124SMoriah Waterland /*
951*5c51f124SMoriah Waterland  * Return variable indicating that the installation only updates the depend
952*5c51f124SMoriah Waterland  * and pkginfo DB's.
953*5c51f124SMoriah Waterland  * Returns:  !0 for true
954*5c51f124SMoriah Waterland  *           0 for false
955*5c51f124SMoriah Waterland  */
956*5c51f124SMoriah Waterland 
957*5c51f124SMoriah Waterland boolean_t
958*5c51f124SMoriah Waterland is_depend_pkginfo_DB(void)
959*5c51f124SMoriah Waterland {
960*5c51f124SMoriah Waterland 	return (depend_pkginfo_DB);
961*5c51f124SMoriah Waterland }
962*5c51f124SMoriah Waterland 
963*5c51f124SMoriah Waterland /*
964*5c51f124SMoriah Waterland  * Increment variable indicating that packages should not be spooled in
965*5c51f124SMoriah Waterland  * var/sadm/pkg/<pkgabbrev>/save/pspool/
966*5c51f124SMoriah Waterland  */
967*5c51f124SMoriah Waterland void
968*5c51f124SMoriah Waterland disable_spool_create(void)
969*5c51f124SMoriah Waterland {
970*5c51f124SMoriah Waterland 	partial_spool_create++;
971*5c51f124SMoriah Waterland }
972*5c51f124SMoriah Waterland 
973*5c51f124SMoriah Waterland /*
974*5c51f124SMoriah Waterland  * Return variable indicating whether or not the partial spool directory
975*5c51f124SMoriah Waterland  * should be created.
976*5c51f124SMoriah Waterland  * Returns:  1 for true
977*5c51f124SMoriah Waterland  *           0 for false
978*5c51f124SMoriah Waterland  */
979*5c51f124SMoriah Waterland int
980*5c51f124SMoriah Waterland is_spool_create(void)
981*5c51f124SMoriah Waterland {
982*5c51f124SMoriah Waterland 	return (partial_spool_create);
983*5c51f124SMoriah Waterland }
984