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
set_continue_not_ok(void)142 set_continue_not_ok(void)
143 {
144 dr_info.do_not_continue = 1;
145 }
146
147 int
continue_is_ok(void)148 continue_is_ok(void)
149 {
150 return (!dr_info.do_not_continue);
151 }
152
153 static void
wr_OK(FILE * fp,char * parameter,int set,int value)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
add_pkg_to_list(char * pkgname)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
write_pkglist_ascii(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
write_string(int fd,char * string)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 *
read_string(int fd,char * buffer)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
write_dryrun_ascii()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
write_dryrun_bin()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
init_drinfo(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
read_continue_bin(void)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
in_dryrun_mode(void)650 in_dryrun_mode(void)
651 {
652 return (dryrun_mode);
653 }
654
655 void
set_dryrun_mode(void)656 set_dryrun_mode(void)
657 {
658 dryrun_mode = 1;
659 }
660
661 int
in_continue_mode(void)662 in_continue_mode(void)
663 {
664 return (continue_mode);
665 }
666
667 void
set_continue_mode(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
init_drfile(char ** targ_ptr,char * path)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
init_dryrunfile(char * dr_dir)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
init_contfile(char * cn_dir)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
set_dr_exitmsg(char * value)763 set_dr_exitmsg(char *value)
764 {
765 exitmsg = value;
766 }
767
768 void
set_dr_info(int type,int value)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
write_dryrun_file(struct cfextra ** extlist)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
read_continuation(int * error)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