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