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.
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.
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]
23 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
42 #include <instzones_api.h>
47 /* merg() return codes */
49 #define MRG_DIFFERENT 1
52 /* typechg() return codes */
54 #define TYPE_WARNING 1
55 #define TYPE_IGNORED 2
56 #define TYPE_REPLACE 3
60 #define ERR_OUTPUT "unable to update package database"
61 #define ERR_PINFO "missing pinfo structure for <%s>"
62 #define INFO_PROCESS " %2ld%% of information processed; continuing ..."
64 #define WRN_NOTFILE "WARNING: %s <no longer a regular file>"
65 #define WRN_NOTSYMLN "WARNING: %s <no longer a symbolic link>"
66 #define WRN_NOTLINK "WARNING: %s <no longer a linked file>"
67 #define WRN_NOTDIR "WARNING: %s <no longer a directory>"
68 #define WRN_NOTCHAR "WARNING: %s <no longer a character special device>"
69 #define WRN_NOTBLOCK "WARNING: %s <no longer a block special device>"
70 #define WRN_NOTPIPE "WARNING: %s <no longer a named pipe>"
71 #define WRN_TOEXCL "WARNING: cannot convert %s to an exclusive directory."
72 #define WRN_ODDVERIFY "WARNING: quick verify disabled for class %s."
74 #define MSG_TYPIGN "Object type change ignored."
75 #define MSG_TYPE_ERR "Package attempts fatal object type change."
78 extern int nosetuid
, nocnflct
, otherstoo
;
81 extern int cp_cfent(struct cfent
*cf_ent
, struct cfextra
*el_ent
);
84 extern void cl_def_dverify(int idx
);
86 char dbst
= '\0'; /* usually set by installf() or removef() */
88 int files_installed(void); /* return number of files installed. */
90 static int errflg
= 0;
92 static int installed
; /* # of files, already properly installed. */
93 static struct pinfo
*pkgpinfo
= (struct pinfo
*)0;
95 static int is_setuid(struct cfent
*ent
);
96 static int is_setgid(struct cfent
*ent
);
97 static int merg(struct cfextra
*el_ent
, struct cfent
*cf_ent
);
98 static int do_like_ent(VFP_T
*vfpo
, struct cfextra
*el_ent
,
99 struct cfent
*cf_ent
, int ctrl
);
100 static int do_new_ent(VFP_T
*vfpo
, struct cfextra
*el_ent
, int ctrl
);
101 static int typechg(struct cfent
*el_ent
, struct cfent
*cf_ent
,
102 struct mergstat
*mstat
);
104 static void set_change(struct cfextra
*el_ent
);
105 static void chgclass(struct cfent
*cf_ent
, struct pinfo
*pinfo
);
106 static void output(VFP_T
*vfpo
, struct cfent
*ent
, struct pinfo
*pinfo
);
109 * This scans the extlist (pkgmap) and matches them to the database, copying
110 * out the modified contents to the file at tmpfp. It updates the mergstat
111 * structures and deals with administrative defaults regarding setuid and
116 pkgdbmerg(PKGserver server
, VFP_T
*tmpvfp
, struct cfextra
**extlist
)
118 static struct cfent cf_ent
; /* scratch area */
119 struct cfextra
*el_ent
; /* extlist entry under review */
124 cf_ent
.pinfo
= (NULL
);
126 installed
= changed
= 0;
130 for (eptnum
= 0; (el_ent
= extlist
[eptnum
]) != NULL
; eptnum
++) {
132 * If there's an entry in the extlist at this position,
133 * process that entry.
135 /* Metafiles don't get merged. */
136 if ((el_ent
->cf_ent
.ftype
== 'i') ||
137 (el_ent
->cf_ent
.ftype
== 'n')) {
142 * Copy cfextra structure for duplicated paths.
143 * This is not just an optimization, it is
144 * necessary for correct operation of algorithm.
146 if ((eptnum
> 0) && (strncmp(el_ent
->cf_ent
.path
,
147 extlist
[eptnum
-1]->cf_ent
.path
, PATH_MAX
) == 0)) {
148 memcpy(extlist
[eptnum
], extlist
[eptnum
-1],
149 sizeof (struct cfextra
));
154 * Normally dbst comes to us from installf() or
155 * removef() in order to specify their special
156 * database status codes. They cannot implement a
157 * quick verify (it just doesn't make sense). For
158 * that reason, we can test to see if we already have
159 * a special database status. If we don't (it's from
160 * pkgadd) then we can test to see if this is calling
161 * for a quick verify wherein we assume the install
162 * will work and fix it if it doesn't. In that case
163 * we set our own dbst to be ENTRY_OK.
166 if (cl_dvfy(el_ent
->cf_ent
.pkg_class_idx
) ==
172 * If we DO end up with an installf/quick
173 * verify combination, we fix that by simply
174 * denying the quick verify for this class.
175 * This forces everything to come out alright
176 * by forcing the standard assumptions as
177 * regards package database for the rest of
180 if (cl_dvfy(el_ent
->cf_ent
.pkg_class_idx
) ==
182 logerr(gettext(WRN_ODDVERIFY
),
183 cl_nam(el_ent
->cf_ent
.pkg_class_idx
));
185 * Set destination verification to
188 cl_def_dverify(el_ent
->cf_ent
.pkg_class_idx
);
193 * Comply with administrative requirements regarding
194 * setuid/setgid processes.
196 if (is_setuid(&(el_ent
->cf_ent
))) {
197 el_ent
->mstat
.setuid
= 1;
199 if (is_setgid(&(el_ent
->cf_ent
))) {
200 el_ent
->mstat
.setgid
= 1;
204 * If setuid/setgid processes are not allowed, reset
207 if (nosetuid
&& (el_ent
->mstat
.setgid
||
208 el_ent
->mstat
.setuid
)) {
209 el_ent
->cf_ent
.ainfo
.mode
&= ~(S_ISUID
| S_ISGID
);
212 /* Search package database for this entry. */
213 n
= srchcfile(&cf_ent
, el_ent
->cf_ent
.path
, server
);
216 * If there was an error, note it and return an error
220 char *errstr
= getErrstr();
222 logerr(gettext("pathname: %s"),
223 (cf_ent
.path
&& *cf_ent
.path
) ?
224 cf_ent
.path
: "Unknown");
225 logerr(gettext("problem: %s"),
226 (errstr
&& *errstr
) ? errstr
: "Unknown");
229 * If there was a match, then merge them into a
234 * If this package is overwriting a setuid or
235 * setgid process, set the status bits so we
236 * can inform the administrator.
238 if (is_setuid(&cf_ent
)) {
239 el_ent
->mstat
.osetuid
= 1;
242 if (is_setgid(&cf_ent
)) {
243 el_ent
->mstat
.osetgid
= 1;
246 * Detect if a symlink has changed to directory
247 * If so mark all the files/dir supposed to be
248 * iniside this dir, so that they are not miss
249 * understood by do_new_ent later as already
252 if ((cf_ent
.ftype
== 's') &&
253 (el_ent
->cf_ent
.ftype
== 'd')) {
255 int plen
= strlen(el_ent
->cf_ent
.path
);
256 for (i
= eptnum
+ 1; extlist
[i
]; i
++) {
257 if (strncmp(el_ent
->cf_ent
.path
,
258 extlist
[i
]->cf_ent
.path
,
261 extlist
[i
]->mstat
.parentsyml2dir
266 if (do_like_ent(tmpvfp
, el_ent
, &cf_ent
, assume_ok
)) {
272 * The file doesn't exist in the database.
274 if (do_new_ent(tmpvfp
, el_ent
, assume_ok
)) {
280 return (errflg
? -1 : changed
);
284 * Merge a new entry with an installed package object of the same name and
285 * insert that object into the package database. Obey administrative defaults
286 * as regards conflicting files.
290 do_like_ent(VFP_T
*vfpo
, struct cfextra
*el_ent
, struct cfent
*cf_ent
, int ctrl
)
292 int stflag
, ignore
, changed
, mrg_result
;
294 ignore
= changed
= 0;
297 * Construct the record defining the current package. If there are
298 * other packages involved, this will be appended to the existing
299 * list. If this is an update of the same package, it will get merged
300 * with the existing record. If this is a preloaded record (like from
301 * a dryrun file), it will keep it's current pinfo pointer and will
302 * pass it on to the record from the contents file - because on the
303 * final continuation, the contents file will be wrong.
305 if (el_ent
->mstat
.preloaded
) {
306 struct pinfo
*pkginfo
;
308 /* Contents file is not to be trusted for this list. */
309 pkginfo
= cf_ent
->pinfo
;
311 /* Free the potentially bogus list. */
314 next
= pkginfo
->next
;
319 cf_ent
->pinfo
= el_ent
->cf_ent
.pinfo
;
322 pkgpinfo
= eptstat(cf_ent
, pkginst
, DUP_ENTRY
);
324 stflag
= pkgpinfo
->status
;
327 el_ent
->mstat
.shared
= 1;
329 /* If it's marked for erasure, make it official */
330 if (el_ent
->cf_ent
.ftype
== RM_RDY
) {
332 pkgpinfo
= eptstat(cf_ent
, pkginst
, RM_RDY
);
335 * Get copy of status character in case the object is
336 * "shared" by a server, in which case we need to
337 * maintain the shared status after the entry is
338 * written to the package database with RM_RDY
339 * status. This is needed to support the `removef'
342 stflag
= pkgpinfo
->status
;
343 pkgpinfo
->status
= RM_RDY
;
345 if (putcvfpfile(cf_ent
, vfpo
)) {
346 progerr(gettext(ERR_OUTPUT
));
351 * If object is provided by a server, allocate an
352 * info block and set the status to indicate this.
353 * This is needed to support the `removef' command.
355 if (stflag
== SERVED_FILE
) {
356 el_ent
->cf_ent
.pinfo
=
357 (struct pinfo
*)calloc(1,
358 sizeof (struct pinfo
));
359 el_ent
->cf_ent
.pinfo
->next
= NULL
;
360 el_ent
->cf_ent
.pinfo
->status
= SERVED_FILE
;
367 * If there is no package associated with it, there's something
371 progerr(gettext(ERR_PINFO
), cf_ent
->path
);
376 * Do not allow installation if nocnflct is set and other packages
377 * reference this pathname. The cp_cfent() function below writes the
378 * information from the installed file over the new entry, so the
379 * package database will be unchanged.
381 * By the way, ftype "e" is often shared and that's OK, so ftype
382 * "e" doesn't count here.
384 if ((nocnflct
&& el_ent
->mstat
.shared
&& el_ent
->cf_ent
.ftype
!= 'e')) {
386 * First set the attrchg and contchg entries for proper
387 * messaging in the install phase.
392 * Now overwrite the new entry with the entry for the
393 * currently installed object.
395 if (cp_cfent(cf_ent
, el_ent
) == 0)
400 mrg_result
= merg(el_ent
, cf_ent
);
402 switch (mrg_result
) {
412 * We'll pick one or the other later. For now, cf_ent
413 * will have the fault value and el_ent will retain
414 * the other value. This is the only state that allows
415 * the database and the pkgmap to differ.
418 el_ent
->mstat
.contchg
= 1; /* subject to change */
427 /* el_ent structure now contains updated entry */
428 if (!el_ent
->mstat
.contchg
&& !ignore
) {
430 * We know the DB entry matches the pkgmap, so now we need to
431 * see if the actual object matches the pkgmap.
437 if (ctrl
== 1) { /* quick verify assumes OK */
439 * The pkgpinfo entry is already correctly
440 * constructed. Look into dropping this soon.
442 pkgpinfo
= eptstat(&(el_ent
->cf_ent
), pkginst
,
445 if (stflag
!= DUP_ENTRY
) {
450 * We could trust the prior pkginfo entry, but things
451 * could have changed and we need to update the
452 * fs_tab[] anyway. We check for a server object
455 if (is_served(el_ent
->server_path
,
456 &(el_ent
->fsys_value
)))
457 pkgpinfo
->status
= SERVED_FILE
;
459 if (!ignore
&& el_ent
->mstat
.contchg
) {
461 eptstat(&(el_ent
->cf_ent
), pkginst
,
462 (dbst
? dbst
: CONFIRM_CONT
));
463 } else if (!ignore
&& el_ent
->mstat
.attrchg
) {
465 eptstat(&(el_ent
->cf_ent
), pkginst
,
466 (dbst
? dbst
: CONFIRM_ATTR
));
467 } else if (!ignore
&& el_ent
->mstat
.shared
) {
469 eptstat(&(el_ent
->cf_ent
), pkginst
,
472 } else if (stflag
!= DUP_ENTRY
) {
473 pkgpinfo
= eptstat(&(el_ent
->cf_ent
),
475 if (stflag
!= ENTRY_OK
) {
481 if (mrg_result
== MRG_REPLACE
) {
483 * Put the original package database entry back into
484 * the package database for now.
486 output(vfpo
, cf_ent
, pkgpinfo
);
488 /* Put the merged entry into the package database. */
489 output(vfpo
, &(el_ent
->cf_ent
), pkgpinfo
);
493 if (pkgpinfo
->aclass
[0] != '\0') {
494 (void) strcpy(el_ent
->cf_ent
.pkg_class
, pkgpinfo
->aclass
);
498 * If a sym link entry exists in the contents file and
499 * and the destination of the link does not exist on the the system
500 * then the contents file needs to be updated appropriately so a
501 * subsequent invocation of "installf -f" will create the destination.
503 if (el_ent
->mstat
.contchg
&& pkgpinfo
->status
== INST_RDY
) {
507 if (!(el_ent
->mstat
.preloaded
))
508 el_ent
->cf_ent
.pinfo
= NULL
;
511 * If no change during the merg and we don't have a case where types
512 * were different in odd ways, count this as installed.
514 if (!el_ent
->mstat
.attrchg
&& !el_ent
->mstat
.contchg
&&
515 !el_ent
->mstat
.replace
)
520 /* Insert an entirely new entry into the package database. */
522 do_new_ent(VFP_T
*vfpo
, struct cfextra
*el_ent
, int ctrl
)
528 if (el_ent
->cf_ent
.ftype
== RM_RDY
) {
532 tp
= el_ent
->server_path
;
534 * Check the file/dir existence only if any of the parent directory
535 * of the file/dir has not changed from symbolic link to directory.
536 * At this time we are only doing a dry run, the symlink is not yet
537 * replaced, so if this is done directly then access will result in
538 * incorrect information in case a file with the same attr and cont
539 * exists in the link target.
541 if ((!el_ent
->mstat
.parentsyml2dir
) && (access(tp
, F_OK
) == 0)) {
543 * Path exists, and although its not referenced by any
544 * package we make it look like it is so it appears as a
545 * conflicting file in case the user doesn't want it
546 * installed. We set the rogue flag to distinguish this from
547 * package object conflicts if the administrator is queried
548 * about this later. Note that noconflict means NO conflict
549 * at the file level. Even rogue files count.
551 el_ent
->mstat
.shared
= 1;
552 el_ent
->mstat
.rogue
= 1;
555 /* since path doesn't exist, we're changing everything */
556 el_ent
->mstat
.rogue
= 0;
557 el_ent
->mstat
.contchg
= 1;
558 el_ent
->mstat
.attrchg
= 1;
561 if (el_ent
->cf_ent
.ainfo
.mode
== WILDCARD
) {
562 if (el_ent
->cf_ent
.ftype
== 'd') {
563 el_ent
->cf_ent
.ainfo
.mode
= DEFAULT_MODE
;
565 el_ent
->cf_ent
.ainfo
.mode
= DEFAULT_MODE_FILE
;
567 logerr(WRN_SET_DEF_MODE
, el_ent
->cf_ent
.path
,
568 (int)el_ent
->cf_ent
.ainfo
.mode
);
571 if (strcmp(el_ent
->cf_ent
.ainfo
.owner
, DB_UNDEFINED_ENTRY
) == 0)
572 (void) strcpy(el_ent
->cf_ent
.ainfo
.owner
,
574 if (strcmp(el_ent
->cf_ent
.ainfo
.group
, DB_UNDEFINED_ENTRY
) == 0)
575 (void) strcpy(el_ent
->cf_ent
.ainfo
.group
,
579 * Do not allow installation if nocnflct is set and this pathname is
580 * already in place. Since this entry is new (not associated with a
581 * package), we don't issue anything to the database we're building.
583 if (nocnflct
&& el_ent
->mstat
.shared
) {
588 if (el_ent
->mstat
.preloaded
) {
589 /* Add this package to the already established list. */
590 pinfo
= eptstat(&(el_ent
->cf_ent
), pkginst
, DUP_ENTRY
);
592 el_ent
->cf_ent
.npkgs
= 1;
593 pinfo
= (struct pinfo
*)calloc(1,
594 sizeof (struct pinfo
));
596 progerr(gettext(ERR_MEMORY
), errno
);
599 el_ent
->cf_ent
.pinfo
= pinfo
;
600 (void) strcpy(pinfo
->pkg
, pkginst
);
603 if (ctrl
== 1) { /* quick verify assumes OK */
604 pinfo
->status
= dbst
? dbst
: ENTRY_OK
;
606 * The entry won't be verified, but the entry in the
607 * database isn't necessarily ENTRY_OK. If this is
608 * coming from a server, we need to note that
611 if (is_served(el_ent
->server_path
,
612 &(el_ent
->fsys_value
)))
613 pinfo
->status
= SERVED_FILE
;
615 pinfo
->status
= dbst
? dbst
: CONFIRM_CONT
;
618 output(vfpo
, &(el_ent
->cf_ent
), pinfo
);
622 el_ent
->cf_ent
.pinfo
= NULL
;
624 if (!el_ent
->mstat
.attrchg
&& !el_ent
->mstat
.contchg
) {
632 files_installed(void)
638 * This function determines if there is a difference between the file on
639 * the disk and the file to be laid down. It set's mstat flags attrchg
640 * and contchg accordingly.
643 set_change(struct cfextra
*el_ent
)
648 tp
= el_ent
->server_path
;
649 if ((el_ent
->cf_ent
.ftype
== 'f') || (el_ent
->cf_ent
.ftype
== 'e') ||
650 (el_ent
->cf_ent
.ftype
== 'v')) {
651 if (cverify(0, &(el_ent
->cf_ent
.ftype
), tp
,
652 &(el_ent
->cf_ent
.cinfo
), 1)) {
653 el_ent
->mstat
.contchg
= 1;
654 } else if (!el_ent
->mstat
.contchg
&& !el_ent
->mstat
.attrchg
) {
655 if (averify(0, &(el_ent
->cf_ent
.ftype
), tp
,
656 &(el_ent
->cf_ent
.ainfo
)))
657 el_ent
->mstat
.attrchg
= 1;
659 } else if (!el_ent
->mstat
.attrchg
&&
660 ((el_ent
->cf_ent
.ftype
== 'd') ||
661 (el_ent
->cf_ent
.ftype
== 'x') ||
662 (el_ent
->cf_ent
.ftype
== 'c') ||
663 (el_ent
->cf_ent
.ftype
== 'b') ||
664 (el_ent
->cf_ent
.ftype
== 'p'))) {
665 n
= averify(0, &(el_ent
->cf_ent
.ftype
), tp
,
666 &(el_ent
->cf_ent
.ainfo
));
668 el_ent
->mstat
.attrchg
= 1;
669 else if (n
&& (n
!= VE_EXIST
)) {
670 el_ent
->mstat
.contchg
= 1;
672 } else if (!el_ent
->mstat
.attrchg
&&
673 ((el_ent
->cf_ent
.ftype
== 's') ||
674 (el_ent
->cf_ent
.ftype
== 'l'))) {
675 n
= averify(0, &(el_ent
->cf_ent
.ftype
), tp
,
676 &(el_ent
->cf_ent
.ainfo
));
678 el_ent
->mstat
.attrchg
= 1;
679 else if (n
&& (n
== VE_EXIST
)) {
680 el_ent
->mstat
.contchg
= 1;
686 is_setuid(struct cfent
*ent
)
688 return (((ent
->ftype
== 'f') || (ent
->ftype
== 'v') ||
689 (ent
->ftype
== 'e')) &&
690 (ent
->ainfo
.mode
!= BADMODE
) &&
691 (ent
->ainfo
.mode
!= WILDCARD
) &&
692 (ent
->ainfo
.mode
& S_ISUID
));
696 is_setgid(struct cfent
*ent
)
698 return (((ent
->ftype
== 'f') || (ent
->ftype
== 'v') ||
699 (ent
->ftype
== 'e')) && (ent
->ainfo
.mode
!= BADMODE
) &&
700 (ent
->ainfo
.mode
!= WILDCARD
) &&
701 (ent
->ainfo
.mode
& S_ISGID
) &&
702 (ent
->ainfo
.mode
& (S_IEXEC
|S_IXUSR
|S_IXOTH
)));
706 "fev", /* type 1, regular files */
707 "s", /* type 2, symbolic links */
708 "l", /* type 3, linked files */
709 "dx", /* type 4, directories */
710 "c", /* type 5, character special devices */
711 "b", /* type 6, block special devices */
712 "p", /* type 7, named pipes */
717 * This determines if the ftype of the file on the disk and the file to be
718 * laid down are close enough. If they aren't, this either returns an error
719 * or displays a warning. This returns :
720 * TYPE_OK they're identical or close enough
721 * TYPE_WARNING they're pretty close (probably no problem)
722 * TYPE_IGNORED the type change was not allowed
723 * TYPE_REPLACE to be reviewed later - in endofclass() maybe
724 * TYPE_FATAL something awful happened
727 typechg(struct cfent
*el_ent
, struct cfent
*cf_ent
, struct mergstat
*mstat
)
729 int i
, etype
, itype
, retcode
;
731 /* If they are identical, return OK */
732 if (cf_ent
->ftype
== el_ent
->ftype
)
736 * If package database entry is ambiguous, set it to the new entity's
739 if (cf_ent
->ftype
== BADFTYPE
) {
740 cf_ent
->ftype
= el_ent
->ftype
;
741 return (TYPE_OK
); /* do nothing; not really different */
744 /* If the new entity is ambiguous, wait for the verify */
745 if (el_ent
->ftype
== BADFTYPE
)
749 * If we're trying to convert an existing regular directory to an
750 * exclusive directory, this is very dangerous. We will continue, but
751 * we will deny the conversion.
753 if (el_ent
->ftype
== 'x' && cf_ent
->ftype
== 'd') {
754 logerr(gettext(WRN_TOEXCL
), el_ent
->path
);
755 return (TYPE_IGNORED
);
760 /* Set etype to that of the new entity */
761 for (i
= 0; types
[i
]; ++i
) {
762 if (strchr(types
[i
], el_ent
->ftype
)) {
768 /* Set itype to that in the package database. */
769 for (i
= 0; types
[i
]; ++i
) {
770 if (strchr(types
[i
], cf_ent
->ftype
)) {
776 if (itype
== etype
) {
777 /* same basic object type */
781 retcode
= TYPE_WARNING
;
784 * If a simple object (like a file) is overwriting a directory, mark
785 * it for full inspection during installation.
787 if (etype
!= 4 && itype
== 4) {
788 mstat
->dir2nondir
= 1;
789 retcode
= TYPE_REPLACE
;
792 /* allow change, but warn user of possible problems */
795 logerr(gettext(WRN_NOTFILE
), el_ent
->path
);
799 logerr(gettext(WRN_NOTSYMLN
), el_ent
->path
);
803 logerr(gettext(WRN_NOTLINK
), el_ent
->path
);
807 logerr(gettext(WRN_NOTDIR
), el_ent
->path
);
811 logerr(gettext(WRN_NOTCHAR
), el_ent
->path
);
815 logerr(gettext(WRN_NOTBLOCK
), el_ent
->path
);
819 logerr(gettext(WRN_NOTPIPE
), el_ent
->path
);
829 * This function takes el_ent (the entry from the pkgmap) and cf_ent (the
830 * entry from the package database) and merge them into el_ent. The rules
831 * are still being figured out, but the comments should make the approach
835 * MRG_DIFFERENT The two entries are different and el_ent now contains
836 * the intended new entry to be installed.
837 * MRG_SAME The two entries were identical and the old database
838 * entry will be replaced unchanged.
839 * MRG_REPLACE One or the other entry will be used but the decision
840 * has to be made at install time.
843 merg(struct cfextra
*el_ent
, struct cfent
*cf_ent
)
848 * We need to change the original entry to make it look like the new
849 * entry (the eptstat() routine has already added appropriate package
850 * information, but not about 'aclass' which may represent a change
851 * in class from the previous installation.
853 * NOTE: elent->cf_ent.pinfo (the list of associated packages) is NULL
854 * upon entry to this function.
857 el_ent
->cf_ent
.pinfo
= cf_ent
->pinfo
;
859 if (dbst
== INST_RDY
&& el_ent
->cf_ent
.ftype
== '?') {
860 el_ent
->cf_ent
.ftype
= cf_ent
->ftype
;
864 * Evaluate the ftype change. Usually the ftype won't change. If it
865 * does it may be easy (s -> f), not allowed (d -> x), so complex we
866 * can't figure it 'til later (d -> s) or fatal (a hook for later).
868 if (cf_ent
->ftype
!= el_ent
->cf_ent
.ftype
) {
869 n
= typechg(&(el_ent
->cf_ent
), cf_ent
, &(el_ent
->mstat
));
875 /* This is an allowable change. */
877 el_ent
->mstat
.contchg
= 1;
880 /* Not allowed, but leaving it as is is OK. */
882 logerr(gettext(MSG_TYPIGN
));
883 if (cp_cfent(cf_ent
, el_ent
) == 0)
887 /* Future analysis will reveal if this is OK. */
889 el_ent
->mstat
.replace
= 1;
890 return (MRG_REPLACE
);
892 /* Kill it before it does any damage. */
894 logerr(gettext(MSG_TYPE_ERR
));
904 /* Evaluate and merge the class. */
905 if (strcmp(cf_ent
->pkg_class
, el_ent
->cf_ent
.pkg_class
)) {
907 * we always allow a class change as long as we have
908 * consistent ftypes, which at this point we must
911 if (strcmp(cf_ent
->pkg_class
, "?")) {
912 (void) strcpy(pkgpinfo
->aclass
,
913 el_ent
->cf_ent
.pkg_class
);
914 (void) strcpy(el_ent
->cf_ent
.pkg_class
,
916 chgclass(&(el_ent
->cf_ent
), pkgpinfo
);
921 * Evaluate and merge based upon the ftype of the intended package
924 if (((el_ent
->cf_ent
.ftype
== 's') || (el_ent
->cf_ent
.ftype
== 'l'))) {
926 /* If both have link sources, then they need to be merged. */
927 if (cf_ent
->ainfo
.local
&& el_ent
->cf_ent
.ainfo
.local
) {
929 * If both sources are identical, the merge is
932 if (strcmp(cf_ent
->ainfo
.local
,
933 el_ent
->cf_ent
.ainfo
.local
) != NULL
) {
937 * Otherwise, if the pkgmap entry is
938 * ambiguous, it will inherit the database
941 if (strcmp(el_ent
->cf_ent
.ainfo
.local
,
944 el_ent
->cf_ent
.ainfo
.local
,
948 el_ent
->mstat
.contchg
= 1;
952 return (changed
? MRG_DIFFERENT
: MRG_SAME
);
954 } else if (el_ent
->cf_ent
.ftype
== 'e') {
957 * The contents of edittable files are assumed to be changing
958 * since some class action script will be doing the work and
959 * we have no way of evaluating what it will actually do.
961 el_ent
->mstat
.contchg
= 1;
963 } else if (((el_ent
->cf_ent
.ftype
== 'f') ||
964 (el_ent
->cf_ent
.ftype
== 'v'))) {
966 * For regular files, Look at content information; a BADCONT
967 * in any el_ent field indicates the contents are unknown --
968 * since cf_ent is guaranteed to have a valid entry here (bad
969 * assumption?) this function will recognize this as a
970 * change. The ambiguous el_ent values will be evaluated and
974 if (cf_ent
->cinfo
.size
!= el_ent
->cf_ent
.cinfo
.size
) {
976 el_ent
->mstat
.contchg
= 1;
977 } else if (cf_ent
->cinfo
.modtime
!=
978 el_ent
->cf_ent
.cinfo
.modtime
) {
980 el_ent
->mstat
.contchg
= 1;
981 } else if (cf_ent
->cinfo
.cksum
!= el_ent
->cf_ent
.cinfo
.cksum
) {
983 el_ent
->mstat
.contchg
= 1;
985 } else if (((el_ent
->cf_ent
.ftype
== 'c') ||
986 (el_ent
->cf_ent
.ftype
== 'b'))) {
988 * For devices, if major or minor numbers are identical the
989 * merge is trivial. If the el_ent value is ambiguous (BAD),
990 * the cf_ent value is inherited. Otherwise, the el_ent value
993 if (cf_ent
->ainfo
.major
!= el_ent
->cf_ent
.ainfo
.major
) {
995 if (el_ent
->cf_ent
.ainfo
.major
== BADMAJOR
) {
996 el_ent
->cf_ent
.ainfo
.major
=
999 el_ent
->mstat
.contchg
= 1;
1002 if (cf_ent
->ainfo
.minor
!= el_ent
->cf_ent
.ainfo
.minor
) {
1004 if (el_ent
->cf_ent
.ainfo
.minor
== BADMINOR
)
1005 el_ent
->cf_ent
.ainfo
.minor
=
1006 cf_ent
->ainfo
.minor
;
1008 el_ent
->mstat
.contchg
= 1;
1013 * For mode, owner and group follow the same rules as above - if
1014 * ambiguous, inherit, otherwise keep the new one.
1016 if (cf_ent
->ainfo
.mode
!= el_ent
->cf_ent
.ainfo
.mode
) {
1017 changed
++; /* attribute info is changing */
1018 if (el_ent
->cf_ent
.ainfo
.mode
== BADMODE
) {
1019 el_ent
->cf_ent
.ainfo
.mode
= cf_ent
->ainfo
.mode
;
1020 } else if (el_ent
->cf_ent
.ainfo
.mode
== WILDCARD
) {
1022 * If pkgmap has a '?' set for mode, use the mode from
1023 * the pkg DB (contents file).
1025 el_ent
->cf_ent
.ainfo
.mode
= cf_ent
->ainfo
.mode
;
1026 el_ent
->mstat
.attrchg
= 0;
1028 el_ent
->mstat
.attrchg
= 1;
1031 if (strcmp(cf_ent
->ainfo
.owner
, el_ent
->cf_ent
.ainfo
.owner
) != 0) {
1032 changed
++; /* attribute info is changing */
1033 if (strcmp(el_ent
->cf_ent
.ainfo
.owner
, BADOWNER
) == 0)
1034 (void) strcpy(el_ent
->cf_ent
.ainfo
.owner
,
1035 cf_ent
->ainfo
.owner
);
1037 el_ent
->mstat
.attrchg
= 1;
1039 if (strcmp(cf_ent
->ainfo
.group
, el_ent
->cf_ent
.ainfo
.group
) != 0) {
1040 changed
++; /* attribute info is changing */
1041 if (strcmp(el_ent
->cf_ent
.ainfo
.group
, BADGROUP
) == 0)
1042 (void) strcpy(el_ent
->cf_ent
.ainfo
.group
,
1043 cf_ent
->ainfo
.group
);
1045 el_ent
->mstat
.attrchg
= 1;
1047 return (changed
? MRG_DIFFERENT
: MRG_SAME
);
1051 * This puts the current entry into the package database in the appropriate
1052 * intermediate format for this stage of the installation. This also assures
1053 * the correct format for the various package object ftypes, stripping the
1054 * link name before storing a regular file and stuff like that.
1058 output(VFP_T
*vfpo
, struct cfent
*ent
, struct pinfo
*pinfo
)
1063 /* output without volume information */
1064 svvolno
= ent
->volno
;
1067 pinfo
->editflag
= 0;
1068 if (((ent
->ftype
== 's') || (ent
->ftype
== 'l'))) {
1069 if (putcvfpfile(ent
, vfpo
)) {
1070 progerr(gettext(ERR_OUTPUT
));
1075 /* output without local pathname */
1076 svpt
= ent
->ainfo
.local
;
1077 ent
->ainfo
.local
= NULL
;
1078 if (putcvfpfile(ent
, vfpo
)) {
1079 progerr(gettext(ERR_OUTPUT
));
1083 ent
->ainfo
.local
= svpt
;
1085 * If this entry represents a file which is being edited, we
1086 * need to store in memory the fact that it is an edittable
1087 * file so that when we audit it after installation we do not
1088 * worry about its contents; we do this by resetting the ftype
1089 * to 'e' in the memory array which is later used to control
1092 if (pinfo
->editflag
)
1095 /* restore volume information */
1096 ent
->volno
= svvolno
;
1100 chgclass(struct cfent
*cf_ent
, struct pinfo
*pinfo
)
1103 char *oldclass
, newclass
[CLSSIZ
+1];
1107 * we use this routine to minimize the use of the aclass element by
1108 * optimizing the use of the cf_ent->pkg_class element
1111 (void) strlcpy(newclass
, pinfo
->aclass
, sizeof (newclass
));
1114 oldclass
= cf_ent
->pkg_class
;
1118 * count the number of times the newclass will be used and see if it
1119 * exceeds the number of times the oldclass is referenced
1123 if (pp
->aclass
[0] != '\0') {
1124 if (strcmp(pp
->aclass
, newclass
) == 0)
1126 else if (strcmp(pp
->aclass
, oldclass
) == 0)
1131 if (newcnt
> oldcnt
) {
1134 if (pp
->aclass
[0] == '\0') {
1135 (void) strcpy(pp
->aclass
, oldclass
);
1136 } else if (strcmp(pp
->aclass
, newclass
) == 0) {
1137 pp
->aclass
[0] = '\0';
1141 (void) strcpy(cf_ent
->pkg_class
, newclass
);