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 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 * 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 * 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 * 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 * 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 == '\0') 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 * 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 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 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 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 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 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 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 * 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 * 693 get_basedir(void) 694 { 695 return (basedir); 696 } 697 698 char * 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 * 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 720 is_an_inst_root(void) 721 { 722 return (install_root_exists); 723 } 724 725 int 726 is_a_basedir(void) 727 { 728 return (basedir_exists); 729 } 730 731 int 732 is_relocatable(void) 733 { 734 return (relocatable); 735 } 736 737 int 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 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 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 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 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 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 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 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 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 980 is_spool_create(void) 981 { 982 return (partial_spool_create); 983 } 984