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