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) 2017 Peter Tribble.
27 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
30 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
31 /* All Rights Reserved */
46 #include <sys/param.h>
53 * libinstzones includes
56 #include <instzones_api.h>
59 * consolidation pkg command library includes
65 * local pkg command library includes
75 * pkginstall local includes
78 #include "pkginstall.h"
80 extern int pkgverbose
;
81 extern fsblkcnt_t pkgmap_blks
; /* main.c */
83 extern struct pkgdev pkgdev
;
87 extern char instdir
[];
88 extern char saveSpoolInstallDir
[];
98 #define ck_efile(s, p) \
99 ((p->cinfo.modtime >= 0) && \
101 cverify(0, &p->ftype, s, &p->cinfo, 1))
106 * The variable below indicates that fix_attributes() will be inadequate
107 * because a replacement was permitted.
109 static int repl_permitted
= 0;
111 static int domerg(struct cfextra
**extlist
, int part
, int nparts
,
112 int myclass
, char **srcp
, char **dstp
,
114 static void endofclass(struct cfextra
**extlist
, int myclass
,
115 int ckflag
, PKGserver server
, VFP_T
**a_cfTmpVfp
);
116 static int fix_attributes(struct cfextra
**, int);
117 static int dir_is_populated(char *dirpath
);
118 static boolean_t
absolutepath(char *path
);
119 static boolean_t
parametricpath(char *path
, char **relocpath
);
121 /* Used to keep track of the entries in extlist that are regular files. */
123 struct reg_files
*next
;
126 static struct reg_files
*regfiles_head
= NULL
;
129 * This is the function that actually installs one volume (usually that's
130 * all there is). Upon entry, the extlist is entirely correct:
132 * 1. It contains only those files which are to be installed
134 * 2. The mode bits in the ainfo structure for each file are set
135 * correctly in accordance with administrative defaults.
136 * 3. mstat.setuid/setgid reflect what the status *was* before
137 * pkgdbmerg() processed compliance.
140 instvol(struct cfextra
**extlist
, char *srcinst
, int part
,
141 int nparts
, PKGserver pkgserver
, VFP_T
**a_cfTmpVfp
,
142 char **r_updated
, char *a_zoneName
)
145 char *updated
= (char *)NULL
;
146 char *relocpath
= (char *)NULL
;
151 char scrpt_dst
[PATH_MAX
];
153 int entryidx
; /* array of current package objects */
156 int pass
; /* pass count through the for loop. */
160 struct mergstat
*mstat
;
161 struct reg_files
*rfp
= NULL
;
164 * r_updated is an optional parameter that can be passed in
165 * by the caller if the caller wants to know if any objects are
166 * updated. Do not initialize r_updated; the call to instvol
167 * could be cumulative and any previous update indication must not
168 * be disturbed - this flag is only set, it must never be reset.
169 * This flag is a "char *" pointer so that the object that was
170 * updated can be displayed in debugging output.
174 pkgvolume(&pkgdev
, srcinst
, part
, nparts
);
181 * For each class in this volume, install those files.
183 * NOTE : This loop index may be decremented by code below forcing a
184 * second trip through for the same class. This happens only when a
185 * class is split between an archive and the tree. Examples would be
186 * old WOS packages and the occasional class containing dynamic
187 * libraries which require special treatment.
190 if (is_depend_pkginfo_DB() == B_FALSE
) {
191 int classidx
; /* the current class */
193 for (classidx
= 0; classidx
< nc
; classidx
++) {
194 int pass_relative
= 0;
197 eocflag
= count
= pass
= 0;
201 /* Now what do we pass to the class action script */
203 if (cl_pthrel(classidx
) == REL_2_CAS
) {
209 /* first file to install */
210 if (a_zoneName
== (char *)NULL
) {
211 echo(MSG_INS_N_N
, part
, nparts
);
213 echo(MSG_INS_N_N_LZ
, part
, nparts
,
219 * If there's an install class action script and no
220 * list file has been created yet, create that file
221 * and provide the pointer in listfp.
223 if (cl_iscript(classidx
) && !listfp
) {
224 /* create list file */
225 putparam("TMPDIR", tmpdir
);
226 listfile
= tempnam(tmpdir
, "list");
227 if ((listfp
= fopen(listfile
, "w")) == NULL
) {
228 progerr(ERR_WTMPFILE
, listfile
);
234 * The following function goes through the package
235 * object list returning the array index of the next
236 * regular file. If it encounters a directory,
237 * symlink, named pipe or device, it just creates it.
240 entryidx
= domerg(extlist
, (pass
++ ? 0 : part
), nparts
,
241 classidx
, &srcp
, &dstp
, &updated
);
243 /* Evaluate the return code */
244 if (entryidx
== DMRG_DONE
) {
246 * Set ept to the first entry in extlist
247 * which is guaranteed to exist so
248 * later checks against ept->ftype are
249 * not compared to NULL.
252 ept
= &(ext
->cf_ent
);
253 break; /* no more entries to process */
256 ext
= extlist
[entryidx
];
257 ept
= &(ext
->cf_ent
);
258 mstat
= &(ext
->mstat
);
261 * If not installing from a partially spooled package
262 * (the "save/pspool" area), and the file contents can
263 * be changed (type is 'e' or 'v'), and the class is not
264 * "none": copy the file from the package (in pristine
265 * state with no actions performed) into the appropriate
266 * location in the packages destination "save/pspool"
270 if ((!is_partial_inst()) &&
271 ((ept
->ftype
== 'e') || (ept
->ftype
== 'v')) &&
272 (strcmp(ept
->pkg_class
, "none") != 0)) {
274 if (absolutepath(ext
->map_path
) == B_TRUE
&&
275 parametricpath(ext
->cf_ent
.ainfo
.local
,
276 &relocpath
) == B_FALSE
) {
282 n
= snprintf(scrpt_dst
, PATH_MAX
, "%s/%s/%s",
283 saveSpoolInstallDir
, pspool_loc
,
284 relocpath
? relocpath
: ext
->map_path
);
287 progerr(ERR_CREATE_PATH_2
,
293 /* copy, preserve source file mode */
295 if (cppath(MODE_SRC
, srcp
, scrpt_dst
, 0644)) {
301 * If this isn't writeable anyway, it's not going
302 * into the list file. Only count it if it's going
303 * into the list file.
305 if (is_fs_writeable(ext
->cf_ent
.path
,
309 pkgvolume(&pkgdev
, srcinst
, part
, nparts
);
312 * If source verification is OK for this class, make
313 * sure the source we're passing to the class action
316 if (cl_svfy(classidx
) != NOVERIFY
) {
317 if (cl_iscript(classidx
) ||
318 ((ept
->ftype
== 'e') ||
319 (ept
->ftype
== 'n'))) {
320 if (ck_efile(srcp
, ept
)) {
323 logerr(getErrbufAddr());
331 * If there's a class action script for this class,
332 * just collect names in a temporary file
333 * that will be used as the stdin when the
334 * class action script is invoked.
337 if ((cl_iscript(classidx
)) &&
338 ((is_fs_writeable(ept
->path
,
339 &(ext
->fsys_value
))))) {
342 (void) fputs(instdir
, listfp
);
343 (void) putc('\n', listfp
);
346 (void) fputs(ext
->map_path
, listfp
);
347 (void) putc('\n', listfp
);
350 srcp
: "/dev/null", listfp
);
351 (void) putc(' ', listfp
);
352 (void) fputs(dstp
, listfp
);
353 (void) putc('\n', listfp
);
356 * Note which entries in extlist are regular
357 * files to be installed via the class action
360 if (regfiles_head
== NULL
) {
363 malloc(sizeof (struct reg_files
));
364 if (regfiles_head
== NULL
) {
365 progerr(ERR_MEMORY
, errno
);
368 regfiles_head
->next
= NULL
;
369 regfiles_head
->val
= entryidx
;
374 malloc(sizeof (struct reg_files
));
375 if (rfp
->next
== NULL
) {
376 progerr(ERR_MEMORY
, errno
);
385 * A warning message about unwritable targets
386 * in a class may be appropriate here.
392 * If not installing from a partially spooled package
393 * (the "save/pspool" area), and the file contents can
394 * be changed (type is 'e' or 'v') and the class
395 * identifier is not "none": copy the file from the
396 * package (in pristine state with no actions performed)
397 * into the appropriate location in the packages
398 * destination "save/pspool" area.
401 if ((!is_partial_inst()) &&
402 ((ept
->ftype
== 'e') || (ept
->ftype
== 'v') &&
403 (strcmp(ept
->pkg_class
, "none") != 0))) {
405 if (absolutepath(ext
->map_path
) == B_TRUE
&&
406 parametricpath(ext
->cf_ent
.ainfo
.local
,
407 &relocpath
) == B_FALSE
) {
413 n
= snprintf(scrpt_dst
, PATH_MAX
, "%s/%s/%s",
414 saveSpoolInstallDir
, pspool_loc
,
415 relocpath
? relocpath
: ext
->map_path
);
418 progerr(ERR_CREATE_PATH_2
,
424 /* copy, preserve source file mode */
426 if (cppath(MODE_SRC
, srcp
, scrpt_dst
, 0644)) {
432 * There are several tests here to determine
433 * how we're going to deal with objects
434 * intended for remote read-only filesystems.
435 * We don't use is_served() because this may be
436 * a server. We're actually interested in if
437 * it's *really* remote and *really* not
441 n
= is_remote_fs(ept
->path
, &(ext
->fsys_value
));
443 !is_fs_writeable(ept
->path
,
444 &(ext
->fsys_value
))) {
447 * Don't change the file, we can't write
455 * If it's currently mounted, we can
456 * at least test it for existence.
459 if (is_mounted(ept
->path
, &(ext
->fsys_value
))) {
460 if (!isfile(NULL
, dstp
)) {
461 echo(MSG_IS_PRESENT
, dstp
);
463 echo(WRN_INSTVOL_NONE
, dstp
);
468 server_host
= get_server_host(
471 /* If not, we're just stuck. */
472 echo(WRN_INSTVOL_NOVERIFY
,
479 /* echo output destination name */
484 * if no source then no need to copy/verify
487 if (srcp
== (char *)NULL
) {
492 * If doing a partial installation (creating a
493 * non-global zone), extra steps need to be taken:
495 * If the file is not type 'e' and not type 'v' and
496 * the class is "none": then the file must already
497 * exist (as a result of the initial non-global zone
498 * installation which caused all non-e/v files to be
499 * copied from the global zone to the non-global
500 * zone). If this is the case, verify that the file
501 * exists and has the correct attributes.
504 if (is_partial_inst() != 0) {
507 * if not type 'e|v' and class 'none', then the
508 * file must already exist.
511 if ((ept
->ftype
!= 'e') &&
512 (ept
->ftype
!= 'v') &&
513 (strcmp(cl_nam(ept
->pkg_class_idx
),
516 /* is file changed? */
517 n
= finalck(ept
, 1, 1, B_TRUE
);
519 /* not - ok - warn */
521 /* output warning message */
522 logerr(NOTE_INSTVOL_FINALCKFAIL
,
523 pkginst
, ext
->map_path
);
530 * Copy from source media to target path and fix file
531 * mode and permission now in case installation halted.
535 * If the filesystem is read-only don't attempt
536 * to copy a file. Just check that the content
537 * and attributes of the file are correct.
539 * Normally this doesn't happen, because files,
540 * which don't change, are not returned by
544 if (is_fs_writeable(ept
->path
,
546 n
= cppath(MODE_SET
|DIR_DISPLAY
, srcp
,
547 dstp
, ept
->ainfo
.mode
);
551 } else if (!finalck(ept
, 1, 1, B_FALSE
)) {
553 * everything checks here
559 /* NOTE: a package object was updated */
561 if (updated
== (char *)NULL
) {
562 echoDebug(DBG_INSTVOL_OBJ_UPDATED
, dstp
);
568 * We have now completed processing of all pathnames
569 * associated with this volume and class.
571 if (cl_iscript(classidx
)) {
573 * Execute appropriate class action script
574 * with list of source/destination pathnames
575 * as the input to the script.
579 progerr(ERR_CHGDIR
, pkgbin
);
584 (void) fclose(listfp
);
587 /* nothing updated */
589 echoDebug(DBG_INSTVOL_CAS_INFO
, is_partial_inst(),
590 updated
? updated
: "");
592 if ((is_partial_inst() != 0) &&
593 (updated
== (char *)NULL
)) {
596 * installing in non-global zone, and no object
597 * has been updated (installed/verified):
598 * do not run the class action script.
601 echoDebug(DBG_INSTVOL_NOT_RUNNING_CAS
,
602 a_zoneName
? a_zoneName
: "?",
603 eocflag
? "ENDOFCLASS" :
604 cl_iscript(classidx
),
606 cl_iscript(classidx
));
609 /* run the class action script */
611 echoDebug(DBG_INSTVOL_RUNNING_CAS
,
612 a_zoneName
? a_zoneName
: "?",
613 eocflag
? "ENDOFCLASS" :
614 cl_iscript(classidx
),
616 cl_iscript(classidx
));
618 /* Use ULIMIT if supplied. */
619 set_ulimit(cl_iscript(classidx
), ERR_CASFAIL
);
623 * end of class detected.
624 * Since there are no more volumes which
625 * contain pathnames associated with
626 * this class, execute class action
627 * script with the ENDOFCLASS argument;
628 * we do this even if none of the path
629 * names associated with this class and
630 * volume needed installation to
631 * guarantee the class action script is
632 * executed at least once during package
636 n
= pkgexecl((listfp
?
637 listfile
: CAS_STDIN
),
641 cl_iscript(classidx
),
646 listfile
: CAS_STDIN
),
647 CAS_STDOUT
, CAS_USER
,
649 cl_iscript(classidx
),
652 ckreturn(n
, ERR_CASFAIL
);
654 /* execute class action script */
656 n
= pkgexecl(listfile
,
657 CAS_STDOUT
, CAS_USER
,
658 CAS_GRP
, SHELL
, "-x",
659 cl_iscript(classidx
),
662 n
= pkgexecl(listfile
,
663 CAS_STDOUT
, CAS_USER
,
665 cl_iscript(classidx
),
668 ckreturn(n
, ERR_CASFAIL
);
672 * Ensure the mod times on disk match those
673 * in the pkgmap. In this case, call cverify
674 * with checksumming disabled, since the only
675 * action that needs to be done is to verify
676 * that the attributes are correct.
679 if ((rfp
= regfiles_head
) != NULL
) {
680 while (rfp
!= NULL
) {
681 ept
= &(extlist
[rfp
->val
]->cf_ent
);
682 cverify(1, &ept
->ftype
, ept
->path
,
691 if ((r_updated
!= (char **)NULL
) &&
692 (*r_updated
== (char *)NULL
) &&
693 (updated
== (char *)NULL
)) {
694 updated
= "postinstall";
695 echoDebug(DBG_INSTVOL_OBJ_UPDATED
,
700 (void) remove(listfile
);
704 if (eocflag
&& (!is_partial_inst() || (is_partial_inst() &&
705 strcmp(cl_nam(classidx
), "none") != 0))) {
706 if (cl_dvfy(classidx
) == QKVERIFY
&& !repl_permitted
) {
708 * The quick verify just fixes everything.
709 * If it returns 0, all is well. If it
710 * returns 1, then the class installation
711 * was incomplete and we retry on the
712 * stuff that failed in the conventional
713 * way (without a CAS). this is primarily
714 * to accomodate old archives such as are
715 * found in pre-2.5 WOS; but, it is also
716 * used when a critical dynamic library
717 * is not archived with its class.
719 if (!fix_attributes(extlist
, classidx
)) {
721 * Reset the CAS pointer. If the
722 * function returns 0 then there
723 * was no script there in the first
724 * place and we'll just have to
727 if (cl_deliscript(classidx
))
729 * Decrement classidx for
736 * Finalize merge. This checks to make sure
737 * file attributes are correct and any links
738 * specified are created.
740 (void) endofclass(extlist
, classidx
,
741 (cl_iscript(classidx
) ? 0 : 1),
742 pkgserver
, a_cfTmpVfp
);
749 * Instead of creating links back to the GZ files the logic is
750 * to let zdo recreate the files from the GZ then invoke pkgadd to
751 * install the editable files and skip over any 'f'type files.
752 * The commented out block is to create the links which should be
753 * removed once the current code is tested to be correct.
757 * Go through extlist creating links for 'f'type files
758 * if we're in a global zone. Note that this code lies
759 * here instead of in the main loop to support CAF packages.
760 * In a CAF package the files are installed by the i.none script
761 * and don't exist until all files are done being processed, thus
762 * the additional loop through extlist.
766 * output appropriate completion message
769 if (is_depend_pkginfo_DB() == B_TRUE
) {
770 /* updating database only (hollow package) */
771 if (a_zoneName
== (char *)NULL
) {
772 echo(MSG_DBUPD_N_N
, part
, nparts
);
774 echo(MSG_DBUPD_N_N_LZ
, part
, nparts
, a_zoneName
);
776 } else if (tcount
== 0) {
777 /* updating package (non-hollow package) */
778 if (a_zoneName
== (char *)NULL
) {
779 echo(MSG_INST_N_N
, part
, nparts
);
781 echo(MSG_INST_N_N_LZ
, part
, nparts
, a_zoneName
);
786 * if any package objects were updated (not otherwise already in
787 * existence), set the updated flag as appropriate
790 if (updated
!= (char *)NULL
) {
791 echoDebug(DBG_INSTVOL_OBJ_UPDATED
, updated
);
792 if (r_updated
!= (char **)NULL
) {
793 *r_updated
= updated
;
801 * Description: For the specified class, review each entry and return the array
802 * index number of the next regular file to process. Hard links are
803 * skipped (they are created in endofclass() and directories,
804 * symlinks, pipes and devices are created here, as well as any
805 * file that already exists and has the correct attributes.
806 * Arguments: struct cfextra **extlist - [RO, *RW]
807 * - Pointer to list of cfextra structures representing
808 * the pkgmap of the package to be installed
809 * int part - [RO, *RO]
810 * - the part of the package currently being processed;
811 * packages begin with part "1" and proceed for the
812 * number (nparts) that comprise the package (volume).
813 * int nparts - [RO, *RO]
814 * - the number of parts the package is divided into
815 * int myclass - [RO, *RO]
816 * - index into class array of the current class
817 * char **srcp - [RW, *RW]
818 * - pointer to pointer to string representing the source
819 * path for the next package to process - if this
820 * function returns != DMRG_DONE then this pointer is
821 * set to a pointer to a string representing the source
822 * path for the next object from the package to process
823 * char **dstp - [RW, *RW]
824 * - pointer to pointer to string representing the target
825 * path for the next package to process - if this
826 * function returns != DMRG_DONE then this pointer is
827 * set to a pointer to a string representing the target
828 * path for the next object from the package to process
829 * char **r_updated - [RO, *RW]
830 * - pointer to pointer to string - set if the last path
831 * returned exists or does not need updating. This is
832 * always set when a path to be installed exists and
833 * has the correct contents.
835 * != DMRG_DONE - index into extlist of the next path to
836 * be processed - that needs to be installed/copied
837 * == DMRG_DONE - all entries processed
841 domerg(struct cfextra
**extlist
, int part
, int nparts
,
842 int myclass
, char **srcp
, char **dstp
,
845 boolean_t stateFlag
= B_FALSE
;
848 static int maxvol
= 0;
849 static int svindx
= 0;
850 static int svpart
= 0;
851 struct cfent
*ept
= (struct cfent
*)NULL
;
852 struct mergstat
*mstat
= (struct mergstat
*)NULL
;
854 /* reset returned path pointers */
856 *dstp
= (char *)NULL
;
857 *srcp
= (char *)NULL
;
859 /* set to start or continue based on which part being processed */
871 * This goes through the pkgmap entries one by one testing them
872 * for inclusion in the package database as well as for validity
873 * against existing files.
875 for (i
= svindx
; extlist
[i
]; i
++) {
876 ept
= &(extlist
[i
]->cf_ent
);
877 mstat
= &(extlist
[i
]->mstat
);
879 /* if this isn't the class of current interest, skip it */
881 if (myclass
!= ept
->pkg_class_idx
) {
885 /* if the class is invalid, announce it & exit */
886 if (ept
->pkg_class_idx
== -1) {
887 progerr(ERR_CLIDX
, ept
->pkg_class_idx
,
888 (ept
->path
&& *ept
->path
) ? ept
->path
: "unknown");
889 logerr(gettext("pathname=%s"),
890 (ept
->path
&& *ept
->path
) ? ept
->path
: "unknown");
891 logerr(gettext("class=<%s>"),
892 (ept
->pkg_class
&& *ept
->pkg_class
) ?
893 ept
->pkg_class
: "Unknown");
894 logerr(gettext("CLASSES=<%s>"),
895 getenv("CLASSES") ? getenv("CLASSES") : "Not Set");
900 * Next check to see if we are going to try to delete a
901 * populated directory in some distressing way.
903 if (mstat
->dir2nondir
)
904 if (dir_is_populated(ept
->path
)) {
905 logerr(WRN_INSTVOL_NOTDIR
, ept
->path
);
907 mstat
->denied
= 1; /* install denied! */
909 } else { /* Replace is OK. */
911 * Remove this directory, so it won't
912 * interfere with creation of the new object.
914 if (rmdir(ept
->path
)) {
916 * If it didn't work, there's nothing
917 * we can do. To continue would
918 * likely corrupt the filesystem
919 * which is unacceptable.
921 progerr(ERR_RMDIR
, ept
->path
);
925 repl_permitted
= 1; /* flag it */
928 /* adjust the max volume number appropriately */
930 if (ept
->volno
> maxvol
) {
934 /* if this part goes into another volume, skip it */
936 if (part
!= ept
->volno
) {
941 * If it's a conflicting file and it's not supposed to be
942 * installed, note it and skip.
944 if (nocnflct
&& mstat
->shared
&& ept
->ftype
!= 'e') {
945 if (mstat
->contchg
|| mstat
->attrchg
) {
946 echo(MSG_SHIGN
, ept
->path
);
952 * If we want to set uid or gid but user says no, note it.
953 * Remember that the actual mode bits in the structure have
954 * already been adjusted and the mstat flag is telling us
955 * about the original mode.
957 if (nosetuid
&& (mstat
->setuid
|| mstat
->setgid
)) {
958 msg_ugid
= 1; /* don't repeat attribute message. */
959 if (is_fs_writeable(ept
->path
,
960 &(extlist
[i
]->fsys_value
))) {
961 if (!(mstat
->contchg
) && mstat
->attrchg
) {
962 echo(MSG_UGMOD
, ept
->path
);
964 echo(MSG_UGID
, ept
->path
);
971 switch (ept
->ftype
) {
972 case 'l': /* hard link */
973 /* links treated as object "update/skip" */
975 continue; /* defer to final proc */
977 case 's': /* for symlink, verify without fix first */
978 /* links treated as object "update/skip" */
981 /* Do this only for default verify */
982 if (cl_dvfy(myclass
) == DEFAULT
) {
983 if (averify(0, &ept
->ftype
,
984 ept
->path
, &ept
->ainfo
))
985 echo(MSG_SLINK
, ept
->path
);
990 case 'd': /* directory */
991 case 'x': /* exclusive directory */
992 case 'c': /* character special device */
993 case 'b': /* block special device */
994 case 'p': /* named pipe */
995 /* these NOT treated as object "update/skip" */
999 * If we can't get to it for legitimate reasons,
1000 * don't try to verify it.
1002 if (is_remote_fs(ept
->path
,
1003 &(extlist
[i
]->fsys_value
)) &&
1004 !is_fs_writeable(ept
->path
,
1005 &(extlist
[i
]->fsys_value
))) {
1011 if (averify(1, &ept
->ftype
, ept
->path
,
1012 &ept
->ainfo
) == 0) {
1013 mstat
->contchg
= mstat
->attrchg
= 0;
1015 progerr(ERR_CREATE_PKGOBJ
, ept
->path
);
1016 logerr(getErrbufAddr());
1022 case 'i': /* information file */
1023 /* not treated as object "update/skip" */
1024 stateFlag
= B_FALSE
;
1028 /* all files treated as object "update/skip" */
1034 * Both contchg and shared flags have to be taken into
1035 * account. contchg is set if the file is already present
1036 * in the package database, if it does not exist or if it
1037 * exists and is modified.
1038 * The shared flag is set when 'e' or 'v' file is not
1039 * present in the package database, exists and is not
1040 * modified. It also has to be checked here.
1041 * Shared flag is also set when file is present in package
1042 * database and owned by more than one package, but for
1043 * this case contchg has already been set.
1045 if (mstat
->contchg
|| (mstat
->shared
&&
1046 ((ept
->ftype
== 'e') || (ept
->ftype
== 'v')))) {
1048 if ((ept
->ftype
== 'f') || (ept
->ftype
== 'e') ||
1049 (ept
->ftype
== 'v')) {
1050 *srcp
= ept
->ainfo
.local
;
1051 if (is_partial_inst() != 0) {
1052 if (*srcp
[0] == '~') {
1053 /* Done only for C style */
1055 tmp_ptr
= extlist
[i
]->map_path
;
1056 if (ept
->ftype
!= 'f') {
1068 * instdir has the absolute path
1069 * to saveSpoolInstallDir for
1070 * the package. This is only
1071 * useful for 'e','v' types.
1073 * For 'f', we generate the
1074 * absolute src path with the
1075 * help of install root and the
1078 *srcp
= trans_srcp_pi(
1082 *srcp
= extlist
[i
]->map_path
;
1085 if (*srcp
[0] == '~') {
1086 /* translate source pathname */
1087 *srcp
= srcpath(instdir
,
1088 &(ept
->ainfo
.local
[1]),
1093 echoDebug(DBG_DOMERG_NO_SUCH_FILE
,
1094 ept
->ftype
, cl_nam(ept
->pkg_class_idx
),
1098 * At this point, we're returning a non-file
1099 * that couldn't be created in the standard
1100 * way. If it refers to a filesystem that is
1101 * not writeable by us, don't waste the
1102 * calling process's time.
1104 if (!is_fs_writeable(ept
->path
,
1105 &(extlist
[i
]->fsys_value
))) {
1106 echoDebug(DBG_DOMERG_NOT_WRITABLE
,
1108 cl_nam(ept
->pkg_class_idx
),
1114 echoDebug(DBG_DOMERG_NOT_THERE
,
1115 ept
->ftype
, cl_nam(ept
->pkg_class_idx
),
1124 if (mstat
->attrchg
) {
1125 backup(ept
->path
, 0);
1127 echo(MSG_ATTRIB
, ept
->path
);
1129 /* fix the attributes now for robustness sake */
1130 if (averify(1, &ept
->ftype
,
1132 &ept
->ainfo
) == 0) {
1138 * package object exists, or does not need updating:
1139 * treat the object as if it were "updated"
1142 /* LINTED warning: statement has no consequent: if */
1143 if ((stateFlag
== B_FALSE
) || (ept
== (struct cfent
*)NULL
)) {
1145 * the object in question is a directory or special
1146 * file - the fact that this type of object already
1147 * exists or does not need updating must not trigger
1148 * the object updated indication - that would cause
1149 * class action scripts to be run when installing a
1150 * new non-global zone
1153 if (r_updated
!= (char **)NULL
) {
1154 if (*r_updated
== (char *)NULL
) {
1155 echoDebug(DBG_INSTVOL_OBJ_UPDATED
,
1158 *r_updated
= ept
->path
;
1163 if (maxvol
== part
) {
1164 eocflag
++; /* endofclass */
1167 return (DMRG_DONE
); /* no remaining entries on this volume */
1171 * Determine if the provided directory is populated. Return 0 if so and 1 if
1172 * not. This also returns 0 if the dirpath is not a directory or if it does
1176 dir_is_populated(char *dirpath
) {
1181 if ((dirfp
= opendir(dirpath
)) != NULL
) {
1182 while ((drp
= readdir(dirfp
)) != NULL
) {
1183 if (strcmp(drp
->d_name
, ".") == 0) {
1186 if (strcmp(drp
->d_name
, "..") == 0) {
1190 * If we get here, there's a real file in the
1196 (void) closedir(dirfp
);
1203 * This is the function that cleans up the installation of this class.
1204 * This is where hard links get put in since the stuff they're linking
1205 * probably exists by now.
1208 endofclass(struct cfextra
**extlist
, int myclass
, int ckflag
,
1209 PKGserver pkgserver
, VFP_T
**a_cfTmpVfp
)
1213 char *relocpath
= (char *)NULL
;
1214 char scrpt_dst
[PATH_MAX
];
1218 struct cfent
*ept
; /* entry from the internal list */
1219 struct cfextra entry
; /* entry from the package database */
1220 struct mergstat
*mstat
; /* merge status */
1221 struct pinfo
*pinfo
;
1223 /* open the package database (contents) file */
1225 if (!ocfile(&pkgserver
, a_cfTmpVfp
, pkgmap_blks
)) {
1229 echo(MSG_VERIFYING_CLASS
, cl_nam(myclass
));
1231 for (idx
= 0; /* void */; idx
++) {
1232 /* find next package object in this class */
1233 while (extlist
[idx
]) {
1234 if ((extlist
[idx
]->cf_ent
.ftype
!= 'i') &&
1235 extlist
[idx
]->cf_ent
.pkg_class_idx
== myclass
) {
1241 if (extlist
[idx
] == NULL
)
1245 ept
= &(extlist
[idx
]->cf_ent
);
1246 mstat
= &(extlist
[idx
]->mstat
);
1248 temppath
= extlist
[idx
]->client_path
;
1251 * At this point the only difference between the entry
1252 * in the contents file and the entry in extlist[] is
1253 * that the status indicator contains CONFIRM_CONT.
1254 * This function should return one or something is wrong.
1257 n
= srchcfile(&(entry
.cf_ent
), temppath
, pkgserver
);
1260 char *errstr
= getErrstr();
1262 logerr(gettext("pathname=%s"),
1263 entry
.cf_ent
.path
&& *entry
.cf_ent
.path
?
1264 entry
.cf_ent
.path
: "Unknown");
1265 logerr(gettext("problem=%s"),
1266 (errstr
&& *errstr
) ? errstr
: "Unknown");
1268 } else if (n
!= 1) {
1270 * Check if path should be in the package
1273 if ((mstat
->shared
&& nocnflct
)) {
1276 progerr(ERR_CFMISSING
, ept
->path
);
1281 * If merge was not appropriate for this object, now is the
1282 * time to choose one or the other.
1284 if (mstat
->denied
) {
1286 * If installation was denied AFTER the package
1287 * database was updated, skip this. We've already
1288 * announced the discrepancy and the verifications
1289 * that follow will make faulty decisions based on
1290 * the ftype, which may not be correct.
1292 progerr(ERR_COULD_NOT_INSTALL
, ept
->path
);
1297 * This replaces the old entry with the new
1298 * one. This should never happen in the new
1299 * DB since the entries are already identical.
1301 repl_cfent(ept
, &(entry
.cf_ent
));
1304 * Validate this entry and change the status flag in
1305 * the package database.
1307 if (ept
->ftype
== RM_RDY
) {
1308 (void) eptstat(&(entry
.cf_ent
), pkginst
,
1311 /* check the hard link now. */
1312 if (ept
->ftype
== 'l') {
1313 if (averify(0, &ept
->ftype
,
1314 ept
->path
, &ept
->ainfo
)) {
1322 * Don't install or verify objects for
1323 * remote, read-only filesystems. We need
1324 * only flag them as shared from some server.
1325 * Otherwise, ok to do final check.
1327 if (is_remote_fs(ept
->path
,
1328 &(extlist
[idx
]->fsys_value
)) &&
1329 !is_fs_writeable(ept
->path
,
1330 &(extlist
[idx
]->fsys_value
))) {
1333 flag
= finalck(ept
, mstat
->attrchg
,
1334 (ckflag
? mstat
->contchg
:
1338 pinfo
= entry
.cf_ent
.pinfo
;
1340 /* Find this package in the list. */
1342 if (strcmp(pkginst
, pinfo
->pkg
) == 0) {
1345 pinfo
= pinfo
->next
;
1349 * If this package owns this file, then store
1350 * it in the database with the appropriate
1351 * status. Need to check pinfo in case it
1352 * points to NULL which could happen if
1353 * pinfo->next = NULL above.
1356 if (flag
< 0 || is_served(ept
->path
,
1357 &(extlist
[idx
]->fsys_value
))) {
1359 * This is provided to
1360 * clients by a server.
1362 pinfo
->status
= SERVED_FILE
;
1365 * It's either there or it's
1368 pinfo
->status
= (flag
?
1369 NOT_FND
: ENTRY_OK
);
1376 * If not installing from a partially spooled package, the
1377 * "save/pspool" area, and the file contents can be
1378 * changed (type is 'e' or 'v'), and the class IS "none":
1379 * copy the installed volatile file into the appropriate
1380 * location in the packages destination "save/pspool" area.
1383 if ((!is_partial_inst()) &&
1384 ((ept
->ftype
== 'e') || (ept
->ftype
== 'v')) &&
1385 (strcmp(ept
->pkg_class
, "none") == 0)) {
1387 if (absolutepath(extlist
[idx
]->map_path
) == B_TRUE
&&
1388 parametricpath(extlist
[idx
]->cf_ent
.ainfo
.local
,
1389 &relocpath
) == B_FALSE
) {
1395 n
= snprintf(scrpt_dst
, PATH_MAX
, "%s/%s/%s",
1396 saveSpoolInstallDir
, pspool_loc
,
1397 relocpath
? relocpath
: extlist
[idx
]->map_path
);
1399 if (n
>= PATH_MAX
) {
1400 progerr(ERR_CREATE_PATH_2
,
1401 saveSpoolInstallDir
,
1402 extlist
[idx
]->map_path
);
1406 /* copy, preserve source file mode */
1408 if (cppath(MODE_SRC
, ept
->path
, scrpt_dst
, 0644)) {
1414 * Now insert this potentially changed package database
1417 if (entry
.cf_ent
.npkgs
) {
1418 if (putcvfpfile(&(entry
.cf_ent
), *a_cfTmpVfp
)) {
1424 n
= swapcfile(pkgserver
, a_cfTmpVfp
, pkginst
, dbchg
);
1425 if (n
== RESULT_WRN
) {
1427 } else if (n
== RESULT_ERR
) {
1433 * This function goes through and fixes all the attributes. This is called
1434 * out by using DST_QKVERIFY=this_class in the pkginfo file. The primary
1435 * use for this is to fix up files installed by a class action script
1436 * which is time-critical and reliable enough to assume likely success.
1437 * The first such format was for WOS compressed-cpio'd file sets.
1438 * The second format is the Class Archive Format.
1441 fix_attributes(struct cfextra
**extlist
, int idx
)
1443 struct cfextra
*ext
;
1448 struct mergstat
*mstat
;
1449 char scrpt_dst
[PATH_MAX
];
1451 char *relocpath
= (char *)NULL
;
1453 for (i
= 0; extlist
[i
]; i
++) {
1455 ept
= &(extlist
[i
]->cf_ent
);
1456 mstat
= &(extlist
[i
]->mstat
);
1459 * We don't care about 'i'nfo files because, they
1460 * aren't laid down, 'e'ditable files can change
1461 * anyway, so who cares and 's'ymlinks were already
1462 * fixed in domerg(); however, certain old WOS
1463 * package symlinks depend on a bug in the old
1464 * pkgadd which has recently been expunged. For
1465 * those packages in 2.2, we repeat the verification
1468 * By 2.6 or so, ftype == 's' should be added to this.
1470 if (ept
->ftype
== 'i' || ept
->ftype
== 'e' ||
1471 (mstat
->shared
&& nocnflct
))
1474 if (mstat
->denied
) {
1475 progerr(ERR_COULD_NOT_INSTALL
, ept
->path
);
1480 if (ept
->pkg_class_idx
< 0 || ept
->pkg_class_idx
> nc
) {
1481 progerr(ERR_CLIDX
, ept
->pkg_class_idx
,
1482 (ept
->path
&& *ept
->path
) ? ept
->path
: "unknown");
1486 /* If this is the right class, do the fast verify. */
1487 if (ept
->pkg_class_idx
== idx
) {
1488 if (fverify(1, &ept
->ftype
, ept
->path
,
1489 &ept
->ainfo
, &ept
->cinfo
) == 0) {
1492 } else /* We'll try full verify later */
1496 * Need to copy the installed volitale file back to the
1497 * partial spooled area if we are installing to a local zone
1498 * or similar installation method.
1501 if ((!is_partial_inst()) &&
1502 ((ept
->ftype
== 'e') || (ept
->ftype
== 'v')) &&
1503 (strcmp(ept
->pkg_class
, "none") == 0)) {
1505 if (absolutepath(ext
->map_path
) == B_TRUE
&&
1506 parametricpath(ext
->cf_ent
.ainfo
.local
,
1507 &relocpath
) == B_FALSE
) {
1513 n
= snprintf(scrpt_dst
, PATH_MAX
, "%s/%s/%s",
1514 saveSpoolInstallDir
, pspool_loc
,
1515 relocpath
? relocpath
: ext
->map_path
);
1517 if (n
>= PATH_MAX
) {
1518 progerr(ERR_CREATE_PATH_2
,
1519 saveSpoolInstallDir
,
1524 /* copy, preserve source file mode */
1526 if (cppath(MODE_SRC
, ept
->path
, scrpt_dst
, 0644)) {
1536 * Check to see if first charcter in path is a '/'.
1539 * B_TRUE - if path is prepended with '/'
1543 absolutepath(char *path
)
1545 assert(path
!= NULL
);
1546 assert(path
[0] != '\0');
1548 return (path
[0] == '/' ? B_TRUE
: B_FALSE
);
1552 * Check to see if path contains a '$' which makes it
1553 * a parametric path and therefore relocatable.
1556 * path - The path to determine if it is absolute
1557 * relocpath - The value of the unconditioned path
1558 * i.e. $OPTDIR/usr/ls
1560 * B_TRUE - if path is a parametric path
1564 parametricpath(char *path
, char **relocpath
)
1566 assert(path
!= NULL
);
1567 assert(path
[0] != '\0');
1570 * If this is a valid parametric path then a '$' MUST occur at the
1571 * first or second character.
1574 if (path
[0] == '$' || path
[1] == '$') {
1576 * If a parametric path exists then when copying the
1577 * path to the pspool directoy from the installing
1578 * pkgs reloc directory we want to use the uncononditional
1581 *relocpath
= (path
+ 1);
1590 if (regfiles_head
!= NULL
) {
1591 struct reg_files
*rfp
= regfiles_head
->next
;
1593 while (rfp
!= NULL
) {
1594 free(regfiles_head
);
1595 regfiles_head
= rfp
;
1596 rfp
= regfiles_head
->next
;
1598 free(regfiles_head
);
1599 regfiles_head
= NULL
;