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 2009 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
dofinal(PKGserver server,VFP_T * vfpo,int rmflag,char * myclass,char * prog)57 dofinal(PKGserver server, 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 if (pkgopenfilter(server, pkginst) != 0)
74 quit(99);
75
76 while (n = srchcfile(&(entry.cf_ent), "*", server)) {
77 if (n < 0) {
78 char *errstr = getErrstr();
79 progerr(gettext("bad entry read in contents file"));
80 logerr(gettext("pathname=%s"),
81 (entry.cf_ent.path && *(entry.cf_ent.path)) ?
82 entry.cf_ent.path : "Unknown");
83 logerr(gettext("problem=%s"),
84 (errstr && *errstr) ? errstr : "Unknown");
85 quit(99);
86 }
87 save_path = check_db_entry(vfpo, &entry, rmflag, myclass,
88 &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 pkgclosefilter(server);
98
99 return (dbchg);
100 }
101
102 static char *
check_db_entry(VFP_T * vfpo,struct cfextra * entry,int rmflag,char * myclass,int * dbchg)103 check_db_entry(VFP_T *vfpo, struct cfextra *entry, int rmflag, char *myclass,
104 int *dbchg)
105 {
106 struct pinfo *pinfo;
107 int fs_entry;
108 char *save_path = NULL;
109 char *tp;
110
111 if (myclass && strcmp(myclass, entry->cf_ent.pkg_class)) {
112 /*
113 * We already have it in the database we don't want
114 * to modify it.
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 code below executes only on files in the package
135 * of interest.
136 */
137
138 if (pinfo == NULL)
139 return (NULL);
140
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 } else if (entry->cf_ent.path != NULL) {
152 (void) vfpSetModified(vfpo);
153 /* add "-<path>" to the file */
154 vfpPutc(vfpo, '-');
155 vfpPuts(vfpo, entry->cf_ent.path);
156 vfpPutc(vfpo, '\n');
157 }
158 return (NULL);
159
160 } else if (!rmflag && (pinfo->status == INST_RDY)) {
161 *dbchg = 1;
162
163 /* tp is the server-relative path */
164 tp = fixpath(entry->cf_ent.path);
165 /* save_path is the cmd line path */
166 save_path = entry->cf_ent.path;
167 /* entry has the server-relative path */
168 entry->cf_ent.path = tp;
169
170 /*
171 * The next if statement figures out how
172 * the contents file entry should be
173 * annotated.
174 *
175 * Don't install or verify objects for
176 * remote, read-only filesystems. We
177 * need only verify their presence and
178 * flag them appropriately from some
179 * server. Otherwise, ok to do final
180 * check.
181 */
182 fs_entry = fsys(entry->cf_ent.path);
183
184 if (is_remote_fs_n(fs_entry) && !is_fs_writeable_n(fs_entry)) {
185 /*
186 * Mark it shared whether it's present
187 * or not. life's too funny for me
188 * to explain.
189 */
190 pinfo->status = SERVED_FILE;
191
192 /*
193 * restore for now. This may
194 * chg soon.
195 */
196 entry->cf_ent.path = save_path;
197 } else {
198 /*
199 * If the object is accessible, check
200 * the new entry for existence and
201 * attributes. If there's a problem,
202 * mark it NOT_FND; otherwise,
203 * ENTRY_OK.
204 */
205 if (is_mounted_n(fs_entry)) {
206 int n;
207
208 n = finalck((&entry->cf_ent), 1, 1, B_FALSE);
209
210 pinfo->status = ENTRY_OK;
211 if (n != 0) {
212 pinfo->status = NOT_FND;
213 }
214 }
215
216 /*
217 * It's not remote, read-only but it
218 * may look that way to the client.
219 * If it does, overwrite the above
220 * result - mark it shared.
221 */
222 if (is_served_n(fs_entry))
223 pinfo->status = SERVED_FILE;
224
225 /* restore original path */
226 entry->cf_ent.path = save_path;
227 /* and clear save_path */
228 save_path = NULL;
229 }
230 }
231
232 /* Output entry to contents file. */
233 if (putcvfpfile(&(entry->cf_ent), vfpo)) {
234 progerr(gettext(ERR_WRITE));
235 quit(99);
236 }
237
238 return (save_path);
239 }
240