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 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 31 #include <stdio.h> 32 #include <errno.h> 33 #include <string.h> 34 #include <limits.h> 35 #include <stdlib.h> 36 #include <unistd.h> 37 #include <sys/types.h> 38 #include <pkgstrct.h> 39 #include <locale.h> 40 #include <libintl.h> 41 #include <pkglib.h> 42 #include "install.h" 43 #include "libinst.h" 44 #include "libadm.h" 45 46 extern struct cfextra **extlist; 47 extern struct cfent **eptlist; 48 49 extern char *pkginst; 50 51 #define ERR_WRITE "write of intermediate contents file failed" 52 53 static char *check_db_entry(VFP_T *, struct cfextra *, int, char *, int *); 54 55 /*ARGSUSED*/ 56 int 57 dofinal(VFP_T *vfp, VFP_T *vfpo, int rmflag, char *myclass, char *prog) 58 { 59 struct cfextra entry; 60 int n, indx, dbchg; 61 char *save_path = NULL; 62 63 entry.cf_ent.pinfo = NULL; 64 entry.fsys_value = BADFSYS; 65 entry.fsys_base = BADFSYS; 66 indx = 0; 67 68 while (extlist && extlist[indx] && (extlist[indx]->cf_ent.ftype == 'i')) 69 indx++; 70 71 dbchg = 0; 72 73 while (n = srchcfile(&(entry.cf_ent), "*", vfp, vfpo)) { 74 if (n < 0) { 75 char *errstr = getErrstr(); 76 progerr(gettext 77 ("bad entry read in contents file")); 78 logerr(gettext("pathname=%s"), 79 (entry.cf_ent.path && 80 *(entry.cf_ent.path)) ? 81 entry.cf_ent.path : "Unknown"); 82 logerr(gettext("problem=%s"), 83 (errstr && *errstr) ? errstr : 84 "Unknown"); 85 quit(99); 86 } 87 save_path = check_db_entry( 88 vfpo, &entry, rmflag, myclass, &dbchg); 89 90 /* Restore original server-relative path, if needed */ 91 if (save_path != NULL) { 92 entry.cf_ent.path = save_path; 93 save_path = NULL; 94 } 95 } 96 97 return (dbchg); 98 } 99 100 static char * 101 check_db_entry(VFP_T *vfpo, struct cfextra *entry, int rmflag, char *myclass, 102 int *dbchg) 103 { 104 struct pinfo *pinfo; 105 int fs_entry; 106 char *save_path = NULL; 107 char *tp; 108 109 /* write this entry to the contents file */ 110 111 if (myclass && strcmp(myclass, entry->cf_ent.pkg_class)) { 112 if (putcvfpfile(&entry->cf_ent, vfpo)) { 113 progerr(gettext(ERR_WRITE)); 114 quit(99); 115 } 116 return (NULL); 117 } 118 119 /* 120 * Now scan each package instance holding this file or 121 * directory and see if it matches the package we are 122 * updating here. 123 */ 124 pinfo = entry->cf_ent.pinfo; 125 while (pinfo) { 126 if (strcmp(pkginst, pinfo->pkg) == 0) 127 break; 128 pinfo = pinfo->next; 129 } 130 131 /* 132 * If pinfo == NULL at this point, then this file or 133 * directory isn't part of the package of interest. 134 * So the loop below executes only on files in the package 135 * of interest. 136 */ 137 138 save_path = NULL; 139 140 if (pinfo) { 141 if (rmflag && (pinfo->status == RM_RDY)) { 142 *dbchg = 1; 143 144 (void) eptstat(&(entry->cf_ent), pkginst, '@'); 145 146 if (entry->cf_ent.npkgs) { 147 if (putcvfpfile(&(entry->cf_ent), vfpo)) { 148 progerr(gettext(ERR_WRITE)); 149 quit(99); 150 } 151 } 152 return (NULL); 153 154 } else if (!rmflag && (pinfo->status == INST_RDY)) { 155 *dbchg = 1; 156 157 /* tp is the server-relative path */ 158 tp = fixpath(entry->cf_ent.path); 159 /* save_path is the cmd line path */ 160 save_path = entry->cf_ent.path; 161 /* entry has the server-relative path */ 162 entry->cf_ent.path = tp; 163 164 /* 165 * The next if statement figures out how 166 * the contents file entry should be 167 * annotated. 168 * 169 * Don't install or verify objects for 170 * remote, read-only filesystems. We 171 * need only verify their presence and 172 * flag them appropriately from some 173 * server. Otherwise, ok to do final 174 * check. 175 */ 176 fs_entry = fsys(entry->cf_ent.path); 177 178 if (is_remote_fs_n(fs_entry) && 179 !is_fs_writeable_n(fs_entry)) { 180 /* 181 * Mark it shared whether it's present 182 * or not. life's too funny for me 183 * to explain. 184 */ 185 pinfo->status = SERVED_FILE; 186 187 /* 188 * restore for now. This may 189 * chg soon. 190 */ 191 entry->cf_ent.path = save_path; 192 } else { 193 /* 194 * If the object is accessible, check 195 * the new entry for existence and 196 * attributes. If there's a problem, 197 * mark it NOT_FND; otherwise, 198 * ENTRY_OK. 199 */ 200 if (is_mounted_n(fs_entry)) { 201 int n; 202 203 n = finalck((&entry->cf_ent), 1, 1, 204 B_FALSE); 205 206 pinfo->status = ENTRY_OK; 207 if (n != 0) { 208 pinfo->status = NOT_FND; 209 } 210 } 211 212 /* 213 * It's not remote, read-only but it 214 * may look that way to the client. 215 * If it does, overwrite the above 216 * result - mark it shared. 217 */ 218 if (is_served_n(fs_entry)) 219 pinfo->status = SERVED_FILE; 220 221 /* restore original path */ 222 entry->cf_ent.path = save_path; 223 /* and clear save_path */ 224 save_path = NULL; 225 } 226 } 227 } 228 229 /* Output entry to contents file. */ 230 if (putcvfpfile(&(entry->cf_ent), vfpo)) { 231 progerr(gettext(ERR_WRITE)); 232 quit(99); 233 } 234 235 return (save_path); 236 } 237