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 2007 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 28 #include <stdio.h> 29 #include <stdlib.h> 30 #include <string.h> 31 #include <sys/types.h> 32 #include <sys/wait.h> 33 #include <sys/stat.h> 34 #include <fcntl.h> 35 #include <pkgstrct.h> 36 #include <unistd.h> 37 #include <pkglib.h> 38 #include <libintl.h> 39 #include "libadm.h" 40 #include "libinst.h" 41 #include "dryrun.h" 42 43 #define HDR_FSUSAGE "#name remote_name writeable bfree bused ifree iused" 44 45 #define ERR_NOCREAT "cannot create %s." 46 #define ERR_NOOPEN "cannot open %s." 47 #define ERR_NOWRITE "cannot write to %s." 48 #define ERR_NOREAD "cannot read from %s." 49 #define ERR_FSFAIL "cannot construct filesystem table entry." 50 #define ERR_BADTYPE "cannot record %s dryrun from %s continuation file." 51 #define ERR_NOCONT "cannot install from continue file due to error " \ 52 "stacking." 53 54 #define ISUMASC_SUFFIX ".isum.asc" 55 #define FSASC_SUFFIX ".fs.asc" 56 #define IPOASC_SUFFIX ".ipo.asc" 57 #define IBIN_SUFFIX ".inst.bin" 58 59 #define MALCOUNT 5 /* package entries to allocate in a block */ 60 #define PKGNAMESIZE 32 /* package entries to allocate in a block */ 61 62 extern struct cfextra **extlist; 63 extern char *pkginst; 64 65 static struct cfextra **extptr; 66 static int dryrun_mode = 0; 67 static int continue_mode = 0; 68 static int this_exitcode = 0; 69 70 /* The dryrun and continuation filenames */ 71 static char *dryrun_sumasc; 72 static char *dryrun_fsasc; 73 static char *dryrun_poasc; 74 static char *dryrun_bin; 75 static char *continue_bin; 76 77 /* These tell us if the actual files are initialized yet. */ 78 static int dryrun_initialized = 0; 79 static int continue_initialized = 0; 80 81 static int this_type; /* type of transaction from main.c */ 82 83 static int pkg_handle = -1; 84 static int tot_pkgs; 85 86 /* Their associated file pointers */ 87 static FILE *fp_dra; 88 static int fd_drb; 89 static int fd_cnb; 90 91 struct dr_pkg_entry { 92 char pkginst[PKGNAMESIZE + 2]; 93 struct dr_pkg_entry *next; 94 }; 95 96 static struct drinfo { 97 unsigned partial_set:1; /* 1 if a partial installation was detected. */ 98 unsigned partial:1; /* 1 if a partial installation was detected. */ 99 unsigned runlevel_set:1; 100 unsigned runlevel:1; /* 1 if runlevel test returned an error. */ 101 unsigned pkgfiles_set:1; 102 unsigned pkgfiles:1; 103 unsigned depend_set:1; 104 unsigned depend:1; 105 unsigned space_set:1; 106 unsigned space:1; 107 unsigned conflict_set:1; 108 unsigned conflict:1; 109 unsigned setuid_set:1; 110 unsigned setuid:1; 111 unsigned priv_set:1; 112 unsigned priv:1; 113 unsigned pkgdirs_set:1; 114 unsigned pkgdirs:1; 115 unsigned reqexit_set:1; 116 unsigned checkexit_set:1; 117 118 int type; /* type of operation */ 119 int reqexit; /* request script exit code */ 120 int checkexit; /* checkinstall script exit code */ 121 int exitcode; /* overall program exit code. */ 122 123 struct dr_pkg_entry *packages; /* pointer to the list of packages */ 124 125 int total_ext_recs; /* total extlist entries */ 126 int total_fs_recs; /* total fs_tab entries */ 127 int total_pkgs; /* total number of dryrun packages */ 128 int do_not_continue; /* error stacking is likely */ 129 } dr_info; 130 131 static char *exitmsg; /* the last meaningful message printed */ 132 133 /* 134 * In the event that live continue (continue from a dryrun source only) 135 * becomes a feature, it will be necessary to keep track of those events such 136 * as multiply edited files and files dependent upon multiple class action 137 * scripts that will lead to "tolerance stacking". Calling this function 138 * states that we've lost the level of precision necessary for a live 139 * continue. 140 */ 141 void 142 set_continue_not_ok(void) 143 { 144 dr_info.do_not_continue = 1; 145 } 146 147 int 148 continue_is_ok(void) 149 { 150 return (!dr_info.do_not_continue); 151 } 152 153 static void 154 wr_OK(FILE *fp, char *parameter, int set, int value) 155 { 156 (void) fprintf(fp, "%s=%s\n", parameter, 157 (set ? (value ? "OK" : "NOT_OK") : "NOT_TESTED")); 158 } 159 160 static void 161 add_pkg_to_list(char *pkgname) 162 { 163 struct dr_pkg_entry **pkg_entry; 164 165 if (pkg_handle == -1) { 166 if ((pkg_handle = bl_create(MALCOUNT, 167 sizeof (struct dr_pkg_entry), "package dryrun")) == -1) 168 return; 169 } 170 171 pkg_entry = &(dr_info.packages); 172 173 while (*pkg_entry != NULL) 174 pkg_entry = &((*pkg_entry)->next); 175 176 /* LINTED pointer cast may result in improper alignment */ 177 *pkg_entry = (struct dr_pkg_entry *)bl_next_avail(pkg_handle); 178 dr_info.total_pkgs++; 179 180 (void) snprintf((*pkg_entry)->pkginst, PKGNAMESIZE, "%s%s", 181 (pkgname ? pkgname : ""), ((this_exitcode == 0) ? "" : "-")); 182 } 183 184 static void 185 write_pkglist_ascii(void) 186 { 187 struct dr_pkg_entry *pkg_entry; 188 189 (void) fprintf(fp_dra, "PKG_LIST=\""); 190 191 pkg_entry = dr_info.packages; 192 while (pkg_entry) { 193 (void) fprintf(fp_dra, " %s", pkg_entry->pkginst); 194 pkg_entry = pkg_entry->next; 195 } 196 197 (void) fprintf(fp_dra, "\"\n"); 198 } 199 200 static int 201 write_string(int fd, char *string) 202 { 203 int string_size; 204 205 if (string) 206 string_size = strlen(string) + 1; 207 else 208 string_size = 0; 209 210 if (write(fd, &string_size, sizeof (string_size)) == -1) { 211 progerr(gettext(ERR_NOWRITE), dryrun_bin); 212 return (0); 213 } 214 215 if (string_size > 0) { 216 if (write(fd, string, string_size) == -1) { 217 progerr(gettext(ERR_NOWRITE), dryrun_bin); 218 return (0); 219 } 220 } 221 222 return (1); 223 } 224 225 static char * 226 read_string(int fd, char *buffer) 227 { 228 size_t string_size; 229 230 if (read(fd, &(string_size), sizeof (string_size)) == -1) { 231 progerr(gettext(ERR_NOREAD), continue_bin); 232 return (NULL); 233 } 234 235 if (string_size != 0) { 236 if (read(fd, buffer, string_size) == -1) { 237 progerr(gettext(ERR_NOREAD), continue_bin); 238 return (NULL); 239 } 240 } else { 241 return (NULL); 242 } 243 244 return (buffer); 245 } 246 247 static void 248 write_dryrun_ascii() 249 { 250 int n; 251 char *fs_mntpt, *src_name; 252 253 if ((fp_dra = fopen(dryrun_sumasc, "wb")) == NULL) { 254 progerr(gettext(ERR_NOOPEN), dryrun_sumasc); 255 return; 256 } 257 258 (void) fprintf(fp_dra, "DR_TYPE=%s\n", (dr_info.type == REMOVE_TYPE ? 259 "REMOVE" : "INSTALL")); 260 261 (void) fprintf(fp_dra, "PKG_INSTALL_ROOT=%s\n", (((get_inst_root()) && 262 (strcmp(get_inst_root(), "/") != 0)) ? 263 get_inst_root() : "")); 264 265 write_pkglist_ascii(); 266 267 wr_OK(fp_dra, "CONTINUE", 1, !(dr_info.do_not_continue)); 268 269 wr_OK(fp_dra, "PARTIAL", dr_info.partial_set, dr_info.partial); 270 271 wr_OK(fp_dra, "RUNLEVEL", dr_info.runlevel_set, dr_info.runlevel); 272 273 (void) fprintf(fp_dra, "REQUESTEXITCODE=%d\n", dr_info.reqexit); 274 275 (void) fprintf(fp_dra, "CHECKINSTALLEXITCODE=%d\n", dr_info.checkexit); 276 277 wr_OK(fp_dra, "PKGFILES", dr_info.pkgfiles_set, dr_info.pkgfiles); 278 279 wr_OK(fp_dra, "DEPEND", dr_info.depend_set, dr_info.depend); 280 281 wr_OK(fp_dra, "SPACE", dr_info.space_set, dr_info.space); 282 283 wr_OK(fp_dra, "CONFLICT", dr_info.conflict_set, dr_info.conflict); 284 285 wr_OK(fp_dra, "SETUID", dr_info.setuid_set, dr_info.setuid); 286 287 wr_OK(fp_dra, "PRIV", dr_info.priv_set, dr_info.priv); 288 289 wr_OK(fp_dra, "PKGDIRS", dr_info.pkgdirs_set, dr_info.pkgdirs); 290 291 (void) fprintf(fp_dra, "EXITCODE=%d\n", dr_info.exitcode); 292 293 (void) fprintf(fp_dra, "ERRORMSG=%s\n", (exitmsg ? exitmsg : "NONE")); 294 295 (void) fclose(fp_dra); 296 297 if ((fp_dra = fopen(dryrun_fsasc, "wb")) == NULL) { 298 progerr(gettext(ERR_NOOPEN), dryrun_fsasc); 299 return; 300 } 301 302 (void) fprintf(fp_dra, "%s\nFSUSAGE=\\\n\"\\\n", HDR_FSUSAGE); 303 304 for (n = 0; fs_mntpt = get_fs_name_n(n); n++) { 305 int bfree, bused; 306 bfree = get_blk_free_n(n); 307 bused = get_blk_used_n(n); 308 309 if (bfree || bused) { 310 (void) fprintf(fp_dra, "%s %s %s %d %d %lu %lu \\\n", 311 fs_mntpt, 312 ((src_name = get_source_name_n(n)) ? 313 src_name : "none?"), 314 (is_fs_writeable_n(n) ? "TRUE" : "FALSE"), 315 bfree, 316 bused, 317 get_inode_free_n(n), 318 get_inode_used_n(n)); 319 } 320 } 321 322 dr_info.total_fs_recs = n; 323 324 (void) fprintf(fp_dra, "\"\n"); 325 326 (void) fclose(fp_dra); 327 328 if ((fp_dra = fopen(dryrun_poasc, "wb")) == NULL) { 329 progerr(gettext(ERR_NOOPEN), dryrun_poasc); 330 return; 331 } 332 333 dr_info.total_ext_recs = 0; 334 335 (void) fprintf(fp_dra, "WOULD_INSTALL=\\\n\"\\\n"); 336 337 for (n = 0; extptr && extptr[n]; n++) { 338 /* 339 * Write it out if it's a successful change or it is from the 340 * prior dryrun file (meaning it was a change back then). 341 */ 342 if ((this_exitcode == 0 && 343 (extptr[n]->mstat.contchg || extptr[n]->mstat.attrchg)) || 344 extptr[n]->mstat.preloaded) { 345 (void) fprintf(fp_dra, "%c %s \\\n", 346 extptr[n]->cf_ent.ftype, 347 extptr[n]->client_path); 348 349 /* Count it, if it's going into the dryrun file. */ 350 if (extptr[n]->cf_ent.ftype != 'i') 351 dr_info.total_ext_recs++; 352 } 353 } 354 355 (void) fprintf(fp_dra, "\"\n"); 356 357 (void) fclose(fp_dra); 358 } 359 360 /* 361 * This writes out a dryrun file. 362 */ 363 static void 364 write_dryrun_bin() 365 { 366 struct fstable *fs_entry; 367 struct pinfo *pkginfo; 368 struct dr_pkg_entry *pkg_entry; 369 int n; 370 int fsentry_size = sizeof (struct fstable); 371 int extentry_size = sizeof (struct cfextra); 372 int pinfoentry_size = sizeof (struct pinfo); 373 374 if ((fd_drb = open(dryrun_bin, 375 O_RDWR | O_APPEND | O_TRUNC)) == -1) { 376 progerr(gettext(ERR_NOOPEN), dryrun_bin); 377 return; 378 } 379 380 /* Write the dryrun info table. */ 381 if (write(fd_drb, &dr_info, sizeof (struct drinfo)) == -1) { 382 progerr(gettext(ERR_NOWRITE), dryrun_bin); 383 return; 384 } 385 386 /* Write out the package instance list. */ 387 pkg_entry = dr_info.packages; 388 while (pkg_entry) { 389 if (write(fd_drb, pkg_entry->pkginst, PKGNAMESIZE) == -1) { 390 progerr(gettext(ERR_NOWRITE), dryrun_bin); 391 return; 392 } 393 pkg_entry = pkg_entry->next; 394 } 395 396 /* Write out the fstable records. */ 397 for (n = 0; n < dr_info.total_fs_recs; n++) { 398 fs_entry = get_fs_entry(n); 399 400 if (write(fd_drb, fs_entry, fsentry_size) == -1) { 401 progerr(gettext(ERR_NOWRITE), dryrun_bin); 402 return; 403 } 404 405 if (!write_string(fd_drb, fs_entry->name)) 406 return; 407 408 if (!write_string(fd_drb, fs_entry->fstype)) 409 return; 410 411 if (!write_string(fd_drb, fs_entry->remote_name)) 412 return; 413 } 414 415 /* Write out the package objects and their attributes. */ 416 for (n = 0; extptr && extptr[n]; n++) { 417 /* Don't save metafiles. */ 418 if (extptr[n]->cf_ent.ftype == 'i') 419 continue; 420 421 /* 422 * If it's a new package object (not left over from the 423 * continuation file) and it indicates no changes to the 424 * system, skip it. Only files that will change the system 425 * are stored. 426 */ 427 if (extptr[n]->mstat.preloaded == 0 && 428 !(this_exitcode == 0 && 429 (extptr[n]->mstat.contchg || extptr[n]->mstat.attrchg))) 430 continue; 431 432 if (write(fd_drb, extptr[n], extentry_size) == -1) { 433 progerr(gettext(ERR_NOWRITE), dryrun_bin); 434 return; 435 } 436 437 if (!write_string(fd_drb, extptr[n]->cf_ent.path)) 438 return; 439 440 if (!write_string(fd_drb, extptr[n]->cf_ent.ainfo.local)) 441 return; 442 443 extptr[n]->cf_ent.pinfo = eptstat(&(extptr[n]->cf_ent), 444 pkginst, CONFIRM_CONT); 445 446 /* 447 * Now all of the entries about the various packages that own 448 * this entry. 449 */ 450 pkginfo = extptr[n]->cf_ent.pinfo; 451 452 do { 453 if (write(fd_drb, pkginfo, 454 pinfoentry_size) == -1) { 455 progerr(gettext(ERR_NOWRITE), dryrun_bin); 456 return; 457 } 458 pkginfo = pkginfo->next; /* May be several */ 459 } while (pkginfo); 460 } 461 462 (void) close(fd_drb); 463 } 464 465 static void 466 init_drinfo(void) { 467 468 if (dr_info.partial != 0) 469 dr_info.partial_set = 0; 470 471 if (dr_info.runlevel != 0) 472 dr_info.runlevel_set = 0; 473 474 if (dr_info.pkgfiles != 0) 475 dr_info.pkgfiles_set = 0; 476 477 if (dr_info.depend != 0) 478 dr_info.depend_set = 0; 479 480 if (dr_info.space != 0) 481 dr_info.space_set = 0; 482 483 if (dr_info.conflict != 0) 484 dr_info.conflict_set = 0; 485 486 if (dr_info.setuid != 0) 487 dr_info.setuid_set = 0; 488 489 if (dr_info.priv != 0) 490 dr_info.priv_set = 0; 491 492 if (dr_info.pkgdirs != 0) 493 dr_info.pkgdirs_set = 0; 494 495 if (dr_info.reqexit == 0) 496 dr_info.reqexit_set = 0; 497 498 if (dr_info.checkexit == 0) 499 dr_info.checkexit_set = 0; 500 501 dr_info.packages = NULL; 502 tot_pkgs = dr_info.total_pkgs; 503 dr_info.total_pkgs = 0; 504 } 505 506 /* 507 * This function reads in the various continuation file data in order to seed 508 * the internal data structures. 509 */ 510 static boolean_t 511 read_continue_bin(void) 512 { 513 int n; 514 int fsentry_size = sizeof (struct fstable); 515 int extentry_size = sizeof (struct cfextra); 516 int pinfoentry_size = sizeof (struct pinfo); 517 518 pkgobjinit(); 519 if (!init_pkgobjspace()) 520 return (B_FALSE); 521 522 if ((fd_cnb = open(continue_bin, O_RDONLY)) == -1) { 523 progerr(gettext(ERR_NOOPEN), continue_bin); 524 return (B_FALSE); 525 } 526 527 /* Read the dryrun info structure. */ 528 if (read(fd_cnb, &dr_info, sizeof (struct drinfo)) == -1) { 529 progerr(gettext(ERR_NOREAD), continue_bin); 530 return (B_FALSE); 531 } 532 533 init_drinfo(); 534 535 if (this_type != dr_info.type) { 536 progerr(gettext(ERR_BADTYPE), 537 (this_type == REMOVE_TYPE) ? 538 "a remove" : "an install", 539 (dr_info.type == REMOVE_TYPE) ? 540 "a remove" : "an install"); 541 return (B_FALSE); 542 } 543 544 /* Read in the dryrun package records. */ 545 for (n = 0; n < tot_pkgs; n++) { 546 char pkg_name[PKGNAMESIZE]; 547 548 if (read(fd_cnb, &pkg_name, PKGNAMESIZE) == -1) { 549 progerr(gettext(ERR_NOREAD), continue_bin); 550 return (B_FALSE); 551 } 552 553 add_pkg_to_list(pkg_name); 554 } 555 556 /* Read in the fstable records. */ 557 for (n = 0; n < dr_info.total_fs_recs; n++) { 558 struct fstable fs_entry; 559 char name[PATH_MAX], remote_name[PATH_MAX]; 560 char fstype[200]; 561 562 if (read(fd_cnb, &fs_entry, fsentry_size) == -1) { 563 progerr(gettext(ERR_NOREAD), continue_bin); 564 return (B_FALSE); 565 } 566 567 if (read_string(fd_cnb, &name[0]) == NULL) 568 return (B_FALSE); 569 570 if (read_string(fd_cnb, &fstype[0]) == NULL) 571 return (B_FALSE); 572 573 if (read_string(fd_cnb, &remote_name[0]) == NULL) 574 return (B_FALSE); 575 576 if (load_fsentry(&fs_entry, name, fstype, remote_name)) { 577 progerr(gettext(ERR_FSFAIL)); 578 return (B_FALSE); 579 } 580 } 581 582 /* Read in the package objects and their attributes. */ 583 for (n = 0; n < dr_info.total_ext_recs; n++) { 584 struct cfextra ext_entry; 585 struct pinfo pinfo_area, *pinfo_ptr; 586 char path[PATH_MAX], local[PATH_MAX], *local_ptr; 587 588 if (read(fd_cnb, &ext_entry, extentry_size) == -1) { 589 progerr(gettext(ERR_NOREAD), continue_bin); 590 return (B_FALSE); 591 } 592 593 /* 594 * If the previous dryrun replaced a directory with a 595 * non-directory and we're going into *another* dryrun, we're 596 * stacking errors and continuation should not be permitted. 597 */ 598 if (ext_entry.mstat.dir2nondir && dryrun_mode) 599 dr_info.do_not_continue = 1; 600 601 /* 602 * Since we just read this from a continuation file; it is, 603 * by definition, preloaded. 604 */ 605 ext_entry.mstat.preloaded = 1; 606 607 if (read_string(fd_cnb, &path[0]) == NULL) 608 return (B_FALSE); 609 610 local_ptr = read_string(fd_cnb, &local[0]); 611 612 ext_entry.cf_ent.pinfo = NULL; 613 614 /* 615 * Now all of the entries about the various packages that own 616 * this entry. 617 */ 618 do { 619 if (read(fd_cnb, &pinfo_area, pinfoentry_size) == -1) { 620 progerr(gettext(ERR_NOREAD), continue_bin); 621 return (B_FALSE); 622 623 } 624 625 pinfo_ptr = eptstat(&(ext_entry.cf_ent), 626 pinfo_area.pkg, CONFIRM_CONT); 627 628 if (pinfo_ptr->next) { 629 pinfo_ptr = pinfo_ptr->next; 630 } else { 631 pinfo_ptr = NULL; 632 } 633 634 } while (pinfo_ptr); 635 636 seed_pkgobjmap(&ext_entry, path, local_ptr); 637 } 638 639 (void) close(fd_cnb); 640 641 /* 642 * Return as reading is done, so pkginstall doesn't 643 * read the same info from the system. 644 */ 645 646 return (B_TRUE); 647 } 648 649 int 650 in_dryrun_mode(void) 651 { 652 return (dryrun_mode); 653 } 654 655 void 656 set_dryrun_mode(void) 657 { 658 dryrun_mode = 1; 659 } 660 661 int 662 in_continue_mode(void) 663 { 664 return (continue_mode); 665 } 666 667 void 668 set_continue_mode(void) 669 { 670 continue_mode = 1; 671 } 672 673 /* 674 * Initialize a dryrun file by assigning it a name and creating it 675 * empty. 676 */ 677 static int 678 init_drfile(char **targ_ptr, char *path) 679 { 680 int n; 681 char *targ_file; 682 683 *targ_ptr = strdup(path); 684 targ_file = *targ_ptr; 685 686 if (access(targ_file, W_OK) == 0) { 687 (void) unlink(targ_file); 688 } 689 690 n = open(targ_file, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644); 691 if (n < 0) { 692 progerr(gettext(ERR_NOCREAT), targ_file); 693 return (0); 694 } else { 695 (void) close(n); 696 } 697 698 return (1); 699 } 700 701 /* 702 * Initialize all required dryrun files and see that the target directory is 703 * present. If all goes well, we're in dryrun mode. If it doesn't, we're not. 704 */ 705 void 706 init_dryrunfile(char *dr_dir) 707 { 708 char temp_path[PATH_MAX]; 709 char *dot_pos = (temp_path+strlen(dr_dir)+7); 710 711 /* First create or confirm the directory. */ 712 if (isdir(dr_dir) != 0) { 713 (void) mkpath(dr_dir); 714 } 715 716 (void) snprintf(temp_path, sizeof (temp_path), "%s/dryrun", dr_dir); 717 718 (void) strcpy(dot_pos, ISUMASC_SUFFIX); 719 720 if (!init_drfile(&dryrun_sumasc, temp_path)) 721 return; 722 723 (void) strcpy(dot_pos, FSASC_SUFFIX); 724 725 if (!init_drfile(&dryrun_fsasc, temp_path)) 726 return; 727 728 (void) strcpy(dot_pos, IPOASC_SUFFIX); 729 730 if (!init_drfile(&dryrun_poasc, temp_path)) 731 return; 732 733 (void) strcpy(dot_pos, IBIN_SUFFIX); 734 735 if (!init_drfile(&dryrun_bin, temp_path)) 736 return; 737 738 dryrun_initialized = 1; 739 } 740 741 void 742 init_contfile(char *cn_dir) 743 { 744 char temp_path[PATH_MAX]; 745 746 /* First confirm the directory. */ 747 if (isdir(cn_dir) != 0) 748 return; /* no continuation directory */ 749 750 (void) snprintf(temp_path, sizeof (temp_path), 751 "%s/dryrun%s", cn_dir, IBIN_SUFFIX); 752 continue_bin = strdup(temp_path); 753 754 if (access(continue_bin, W_OK) != 0) { 755 free(continue_bin); 756 return; 757 } 758 759 continue_initialized = 1; 760 } 761 762 void 763 set_dr_exitmsg(char *value) 764 { 765 exitmsg = value; 766 } 767 768 void 769 set_dr_info(int type, int value) 770 { 771 switch (type) { 772 case PARTIAL: 773 if (dr_info.partial_set == 0) { 774 dr_info.partial_set = 1; 775 dr_info.partial = (value ? 1 : 0); 776 } 777 break; 778 779 case RUNLEVEL: 780 if (dr_info.runlevel_set == 0) { 781 dr_info.runlevel_set = 1; 782 dr_info.runlevel = (value ? 1 : 0); 783 } 784 break; 785 786 case PKGFILES: 787 if (dr_info.pkgfiles_set == 0) { 788 dr_info.pkgfiles_set = 1; 789 dr_info.pkgfiles = (value ? 1 : 0); 790 } 791 break; 792 793 case DEPEND: 794 if (dr_info.depend_set == 0) { 795 dr_info.depend_set = 1; 796 dr_info.depend = (value ? 1 : 0); 797 } 798 break; 799 800 case SPACE: 801 if (dr_info.space_set == 0) { 802 dr_info.space_set = 1; 803 dr_info.space = (value ? 1 : 0); 804 } 805 break; 806 807 case CONFLICT: 808 if (dr_info.conflict_set == 0) { 809 dr_info.conflict_set = 1; 810 dr_info.conflict = (value ? 1 : 0); 811 } 812 break; 813 814 case SETUID: 815 if (dr_info.setuid_set == 0) { 816 dr_info.setuid_set = 1; 817 dr_info.setuid = (value ? 1 : 0); 818 } 819 break; 820 821 case PRIV: 822 if (dr_info.priv_set == 0) { 823 dr_info.priv_set = 1; 824 dr_info.priv = (value ? 1 : 0); 825 } 826 827 break; 828 829 case PKGDIRS: 830 if (dr_info.pkgdirs_set == 0) { 831 dr_info.pkgdirs_set = 1; 832 dr_info.pkgdirs = (value ? 1 : 0); 833 } 834 835 break; 836 837 case REQUESTEXITCODE: 838 if (dr_info.reqexit_set == 0) { 839 dr_info.reqexit_set = 1; 840 dr_info.reqexit = value; 841 } 842 843 break; 844 845 case CHECKEXITCODE: 846 if (dr_info.checkexit_set == 0) { 847 dr_info.checkexit_set = 1; 848 dr_info.checkexit = value; 849 } 850 851 break; 852 853 case EXITCODE: 854 if (dr_info.exitcode == 0) { 855 dr_info.exitcode = value; 856 } 857 858 this_exitcode = value; 859 860 break; 861 862 /* default to install if the value is kookie. */ 863 case DR_TYPE: 864 if (value == REMOVE_TYPE) 865 this_type = REMOVE_TYPE; 866 else 867 this_type = INSTALL_TYPE; 868 869 break; 870 } 871 } 872 873 void 874 write_dryrun_file(struct cfextra **extlist) 875 { 876 extptr = extlist; 877 878 if (dryrun_initialized) { 879 dr_info.type = this_type; 880 881 add_pkg_to_list(pkginst); 882 write_dryrun_ascii(); 883 write_dryrun_bin(); 884 885 if (dryrun_mode) { 886 free(dryrun_sumasc); 887 free(dryrun_fsasc); 888 free(dryrun_poasc); 889 free(dryrun_bin); 890 } 891 } 892 } 893 894 /* 895 * Name: read_continuation 896 * Description: If continuation is initialised, reads the 897 * continuation binary file. The path for the 898 * same is freed, if set, as this is the last 899 * chance to do so. 900 * Sets: Error condition, through the pointer passed 901 * if read failed. 902 * Returns: B_TRUE - if the continuation binary file 903 * from previous dryrun is read successfully. 904 * B_FALSE - if either continuation is not initialised 905 * or read was not successful. 906 */ 907 boolean_t 908 read_continuation(int *error) 909 { 910 boolean_t ret = B_FALSE; 911 *error = 0; 912 if (continue_initialized) { 913 if (!read_continue_bin()) { 914 continue_mode = 0; 915 free(continue_bin); 916 *error = -1; 917 return (ret); 918 } 919 920 if (continue_mode) { 921 free(continue_bin); 922 } 923 ret = B_TRUE; 924 } 925 return (ret); 926 } 927