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 (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
28
29 #include <stdio.h>
30 #include <errno.h>
31 #include <limits.h>
32 #include <stdlib.h>
33 #include <unistd.h>
34 #include <string.h>
35 #include <ctype.h>
36 #include <dirent.h>
37 #include <sys/types.h>
38 #include <pkgstrct.h>
39 #include <pkginfo.h>
40 #include <locale.h>
41 #include <libintl.h>
42 #include <pkglib.h>
43 #include "libinst.h"
44 #include "libadm.h"
45 #include "messages.h"
46
47 #define LSIZE 256
48 #define NVERS 50
49
50 /*
51 * internal global variables
52 */
53
54 static struct pkginfo info;
55
56 static char type;
57 static char *alist[NVERS];
58 static char *rmpkginst;
59 static char *vlist[NVERS];
60 static char file[128];
61 static char name[128];
62 static char rmpkg[PKGSIZ+1];
63 static char wabbrev[128];
64
65 static int errflg = 0;
66 static int nlist;
67 static int pkgexist;
68 static int pkgokay;
69 static int is_update;
70
71 /*
72 * IMPORTANT NOTE: THE SIZE OF 'abbrev' IS HARD CODED INTO THE CHARACTER
73 * ARRAY SSCANF_FORMAT -- YOU MUST UPDATE BOTH VALUES AT THE SAME TIME!!
74 */
75
76 static char abbrev[128+1];
77 static char *SSCANF_FORMAT = "%c %128s %[^\n]";
78
79 /*
80 * forward declarations
81 */
82
83 static void ckrdeps(boolean_t a_preinstallCheck);
84 static void ckpreq(FILE *fp, char *dname, boolean_t a_preinstallCheck);
85 static void deponme(char *pkginst, char *pkgname,
86 boolean_t a_preinstallCheck);
87 static void prereq(char *pkginst, char *pkgname,
88 boolean_t a_preinstallCheck);
89 static void incompat(char *pkginst, char *pkgname,
90 boolean_t a_preinstallCheck);
91 static int getaline(FILE *fp);
92
93 /*
94 * *****************************************************************************
95 * global external (public) functions
96 * *****************************************************************************
97 */
98
99 int
dockdeps(char * a_depfile,int a_removeFlag,boolean_t a_preinstallCheck)100 dockdeps(char *a_depfile, int a_removeFlag, boolean_t a_preinstallCheck)
101 {
102 FILE *fp;
103 int i;
104 char *inst;
105
106 if (a_removeFlag) {
107 /* check removal dependencies */
108 rmpkginst = a_depfile;
109 (void) strncpy(rmpkg, rmpkginst, PKGSIZ);
110 (void) strtok(rmpkg, ".");
111 (void) snprintf(file, sizeof (file),
112 "%s/%s/%s", pkgdir, rmpkginst, DEPEND_FILE);
113 if ((fp = fopen(file, "r")) == NULL)
114 goto done;
115 } else {
116 if ((fp = fopen(a_depfile, "r")) == NULL) {
117 progerr(ERR_CANNOT_OPEN_DEPEND_FILE, a_depfile,
118 strerror(errno));
119 quit(99);
120 }
121 }
122
123 while (getaline(fp)) {
124 switch (type) {
125 case 'I':
126 case 'P':
127 if (a_removeFlag) {
128 continue;
129 }
130 break;
131
132 case 'R':
133 if (!a_removeFlag) {
134 continue;
135 }
136 break;
137
138 default:
139 errflg++;
140 progerr(ERR_UNKNOWN_DEPENDENCY, type);
141 break;
142 }
143
144 /* check to see if any versions listed are installed */
145 pkgexist = pkgokay = 0;
146 i = 0;
147 if (strchr(abbrev, '.')) {
148 progerr(ERR_PKGABRV, abbrev);
149 }
150 (void) snprintf(wabbrev, sizeof (wabbrev), "%s.*", abbrev);
151
152 do {
153 inst = fpkginst(wabbrev, alist[i], vlist[i]);
154 if (inst && (pkginfo(&info, inst, NULL, NULL) == 0)) {
155 pkgexist++;
156 if (info.status == PI_INSTALLED)
157 pkgokay++;
158 }
159 } while (++i < nlist);
160 (void) fpkginst(NULL); /* force closing/rewind of files */
161
162 if (!info.name) {
163 info.name = name;
164 }
165
166 switch (type) {
167 case 'I':
168 incompat(abbrev, info.name, a_preinstallCheck);
169 break;
170
171 case 'P':
172 prereq(abbrev, name, a_preinstallCheck);
173 break;
174
175 case 'R':
176 deponme(abbrev, info.name, a_preinstallCheck);
177 }
178 }
179 (void) fclose(fp);
180
181 done:
182 if (a_removeFlag) {
183 ckrdeps(a_preinstallCheck);
184 }
185
186 return (errflg);
187 }
188
189 void
setUpdate(void)190 setUpdate(void)
191 {
192 is_update = 1;
193 }
194
195 int
isUpdate(void)196 isUpdate(void)
197 {
198 return ((is_update) ? 1 : 0);
199 }
200
201 /*
202 * *****************************************************************************
203 * static internal (private) functions
204 * *****************************************************************************
205 */
206
207 static void
incompat(char * pkginst,char * pkgname,boolean_t a_preinstallCheck)208 incompat(char *pkginst, char *pkgname, boolean_t a_preinstallCheck)
209 {
210 char buf[512];
211
212 if (!pkgexist)
213 return;
214
215 errflg++;
216 if (a_preinstallCheck == B_TRUE) {
217 (void) fprintf(stdout, "incompat=%s\n", pkginst);
218 return;
219 }
220
221 logerr(ERR_WARNING);
222 (void) snprintf(buf, sizeof (buf), ERR_INCOMP_VERS, pkginst, pkgname);
223 puttext(stderr, buf, 4, 0);
224 (void) putc('\n', stderr);
225 }
226
227 static void
prereq(char * pkginst,char * pkgname,boolean_t a_preinstallCheck)228 prereq(char *pkginst, char *pkgname, boolean_t a_preinstallCheck)
229 {
230 register int i;
231 char buf[512];
232
233 if (pkgokay) {
234 return;
235 }
236
237 errflg++;
238
239 if (a_preinstallCheck == B_TRUE) {
240 if (pkgexist) {
241 (void) fprintf(stdout,
242 "prerequisite-incomplete=%s\n", pkginst);
243 } else {
244 (void) fprintf(stdout,
245 "prerequisite-installed=%s\n", pkginst);
246 }
247 return;
248 }
249
250 logerr(ERR_WARNING);
251 if (pkgexist) {
252 (void) snprintf(buf, sizeof (buf), ERR_PRENCI, pkginst,
253 pkgname);
254 puttext(stderr, buf, 4, 0);
255 (void) putc('\n', stderr);
256 } else {
257 (void) snprintf(buf, sizeof (buf), ERR_PREREQ, pkginst,
258 pkgname);
259 if (nlist) {
260 (void) strcat(buf, ERR_VALINST);
261 }
262 puttext(stderr, buf, 4, 0);
263 (void) putc('\n', stderr);
264 for (i = 0; i < nlist; i++) {
265 (void) printf(" ");
266 if (alist[i])
267 (void) printf("(%s) ", alist[i]);
268 if (vlist[i])
269 (void) printf("%s", vlist[i]);
270 (void) printf("\n");
271 }
272 }
273 }
274
275 static void
deponme(char * pkginst,char * pkgname,boolean_t a_preinstallCheck)276 deponme(char *pkginst, char *pkgname, boolean_t a_preinstallCheck)
277 {
278 char buf[512];
279
280 if (!pkgexist)
281 return;
282
283 errflg++;
284
285 if (a_preinstallCheck == B_TRUE) {
286 if (!pkgname || !pkgname[0]) {
287 (void) snprintf(buf, sizeof (buf),
288 "dependonme=%s", pkginst);
289 } else {
290 (void) snprintf(buf, sizeof (buf),
291 "dependsonme=%s:%s", pkginst, pkgname);
292 }
293 (void) fprintf(stdout, "%s\n", buf);
294 return;
295 }
296
297 logerr(ERR_WARNING);
298 if (!pkgname || !pkgname[0]) {
299 (void) snprintf(buf, sizeof (buf), ERR_DEPONME, pkginst);
300 } else {
301 (void) snprintf(buf, sizeof (buf), ERR_DEPNAM, pkginst,
302 pkgname);
303 }
304 puttext(stderr, buf, 4, 0);
305 (void) putc('\n', stderr);
306 }
307
308 static int
getaline(FILE * fp)309 getaline(FILE *fp)
310 {
311 register int i, c, found;
312 char *pt, *new, line[LSIZE];
313
314 abbrev[0] = name[0] = type = '\0';
315
316 for (i = 0; i < nlist; i++) {
317 if (alist[i]) {
318 free(alist[i]);
319 alist[i] = NULL;
320 }
321 if (vlist[i]) {
322 free(vlist[i]);
323 vlist[i] = NULL;
324 }
325 }
326 alist[0] = vlist[0] = NULL;
327
328 found = (-1);
329 nlist = 0;
330 while ((c = getc(fp)) != EOF) {
331 (void) ungetc(c, fp);
332 if ((found >= 0) && !isspace(c))
333 return (1);
334
335 if (!fgets(line, LSIZE, fp))
336 break;
337
338 for (pt = line; isspace(*pt); /* void */)
339 pt++;
340 if (!*pt || (*pt == '#'))
341 continue;
342
343 if (pt == line) {
344 /* begin new definition */
345 /* LINTED variable format specifier to sscanf(): */
346 (void) sscanf(line, SSCANF_FORMAT, &type, abbrev, name);
347 found++;
348 continue;
349 }
350 if (found < 0)
351 return (0);
352
353 if (*pt == '(') {
354 /* architecture is specified */
355 if (new = strchr(pt, ')'))
356 *new++ = '\0';
357 else
358 return (-1); /* bad specification */
359 alist[found] = qstrdup(pt+1);
360 pt = new;
361 }
362 while (isspace(*pt))
363 pt++;
364 if (*pt) {
365 vlist[found] = qstrdup(pt);
366 if (pt = strchr(vlist[found], '\n'))
367 *pt = '\0';
368 }
369 found++;
370 nlist++;
371 }
372 return ((found >= 0) ? 1 : 0);
373 }
374
375 static void
ckrdeps(boolean_t a_preinstallCheck)376 ckrdeps(boolean_t a_preinstallCheck)
377 {
378 struct dirent *drp;
379 DIR *dirfp;
380 FILE *fp;
381 char depfile[PATH_MAX+1];
382
383 if ((dirfp = opendir(pkgdir)) == NULL)
384 return;
385
386 while ((drp = readdir(dirfp)) != NULL) {
387 if (drp->d_name[0] == '.')
388 continue;
389
390 if (strcmp(drp->d_name, rmpkginst) == 0)
391 continue; /* others don't include me */
392 (void) snprintf(depfile, sizeof (depfile),
393 "%s/%s/%s", pkgdir, drp->d_name, DEPEND_FILE);
394 if ((fp = fopen(depfile, "r")) == NULL)
395 continue;
396
397 ckpreq(fp, drp->d_name, a_preinstallCheck);
398 }
399 (void) closedir(dirfp);
400 }
401
402 static void
ckpreq(FILE * fp,char * dname,boolean_t a_preinstallCheck)403 ckpreq(FILE *fp, char *dname, boolean_t a_preinstallCheck)
404 {
405 register int i;
406 char *inst;
407
408 while (getaline(fp)) {
409 if (type != 'P')
410 continue;
411
412 if (strcmp(abbrev, rmpkg))
413 continue;
414
415 /* see if package is installed */
416 i = 0;
417 if (strchr(abbrev, '.') == 0) {
418 (void) strcat(abbrev, ".*");
419 }
420 pkgexist = 1;
421
422 do {
423 if (inst = fpkginst(abbrev, alist[i], vlist[i])) {
424 if (strcmp(inst, rmpkginst) == 0) {
425 deponme(dname, "", a_preinstallCheck);
426 (void) fclose(fp);
427 (void) fpkginst(NULL);
428 return;
429 }
430 }
431 } while (++i < nlist);
432 (void) fpkginst(NULL);
433 }
434 (void) fclose(fp);
435 }
436