xref: /titanic_50/usr/src/tools/protocmp/depend.c (revision 20c794b39650d115e17a15983b6b82e46238cf45)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 
30 #include <stdio.h>
31 #include <sys/param.h>
32 #include <fcntl.h>
33 #include <stdlib.h>
34 #include <strings.h>
35 #include <errno.h>
36 #include <dirent.h>
37 #include <ctype.h>
38 #include <sys/stat.h>
39 
40 #include "list.h"
41 #include "protodir.h"
42 #include "arch.h"
43 
44 static pkg_list *packages[HASH_SIZE];
45 
46 #define	HASH(name) (hash(name) % HASH_SIZE)
47 
48 int
49 processed_package(const char *pkgname)
50 {
51 	int	bucket;
52 	pkg_list *tmp;
53 
54 	bucket = HASH(pkgname);
55 	for (tmp = packages[bucket]; tmp != NULL; tmp = tmp->next) {
56 		if (strcmp(tmp->pkg_name, pkgname) == 0)
57 			return (1);
58 	}
59 	return (0);
60 }
61 
62 void
63 mark_processed(const char *pkgname)
64 {
65 	int	bucket;
66 	pkg_list *tmp;
67 
68 	bucket = HASH(pkgname);
69 	tmp = malloc(sizeof (pkg_list));
70 	bzero(tmp, sizeof (pkg_list));
71 	(void) strcpy(tmp->pkg_name, pkgname);
72 	tmp->next = packages[bucket];
73 	packages[bucket] = tmp;
74 }
75 
76 static pkg_list *
77 add_dependency(pkg_list *dependlist, const char *pkgname)
78 {
79 	pkg_list *tmp;
80 	pkg_list *pkg;
81 
82 	pkg = malloc(sizeof (pkg_list));
83 	bzero(pkg, sizeof (pkg_list));
84 	(void) strcpy(pkg->pkg_name, pkgname);
85 
86 	/* easy case */
87 	if (dependlist == NULL)
88 		return (pkg);
89 	/* insert at end, since the order matters */
90 	for (tmp = dependlist; tmp->next != NULL; tmp = tmp->next) {
91 		/* NULL */
92 	}
93 	tmp->next = pkg;
94 	return (dependlist);
95 }
96 
97 static void
98 free_dependency_list(pkg_list *dependlist)
99 {
100 	pkg_list *tmp;
101 
102 	while (dependlist) {
103 		tmp = dependlist;
104 		dependlist = dependlist->next;
105 		tmp->next = NULL;
106 		free(tmp);
107 	}
108 }
109 
110 #ifdef DEBUG
111 void
112 print_dependencies(const char *pkgname, pkg_list *dependlist)
113 {
114 	pkg_list *tmp;
115 
116 	fprintf(stderr, "%s:", pkgname);
117 	for (tmp = dependlist; tmp != NULL; tmp = tmp->next)
118 		fprintf(stderr, " %s", tmp->pkg_name);
119 	fprintf(stderr, "\n");
120 }
121 #endif
122 
123 static char *suffix_list[] = {
124 #if defined(__i386)
125 	".i",
126 #elif defined(__sparc)
127 	".c",
128 	".d",
129 	".m",
130 	".u",
131 #else
132 #error "Unknown architecture."
133 #endif
134 	NULL,
135 };
136 
137 static pkg_list *
138 find_dependencies(const char *pkgname, const char *parentdir)
139 {
140 	char	dependfile[MAXPATHLEN + 1];
141 	char	pkgdir[MAXPATHLEN + 1];
142 	char	buf[BUFSIZ];
143 	char	deppkg[MAXNAME];
144 	char	archpkg[MAXNAME];
145 	struct stat sbuf;
146 	FILE	*fp;
147 	pkg_list *dependlist = NULL;
148 	char	**suffixes;
149 
150 	(void) sprintf(dependfile, "%s/%s/depend", parentdir, pkgname);
151 	fp = fopen(dependfile, "r");
152 	if (fp == NULL) {
153 		/*
154 		 * depend won't exist in ON packages until a build
155 		 * has been done, but it would be nice if you didn't have
156 		 * to do that. So try the generic depend file that those
157 		 * packages would copy in during the build.
158 		 */
159 		(void) sprintf(dependfile, "%s/common_files/depend", parentdir);
160 		fp = fopen(dependfile, "r");
161 		if (fp == NULL)
162 			return (NULL);
163 	}
164 	while (fgets(buf, BUFSIZ, fp) != NULL) {
165 		if ((buf[0] == '\0') || (buf[0] == '#') || isspace(buf[0]))
166 			continue;
167 		/* we only care about prerequisites */
168 		if (buf[0] != 'P')
169 			continue;
170 		(void) sscanf(buf, "P %s", deppkg);
171 		/*
172 		 * We have to be careful with some of the packages that are
173 		 * listed as dependencies but exist under a different name -
174 		 * SUNWcar is good, because it's actually SUNWcar.{c,d,i,m,u}.
175 		 * What do we do there? We can't just go for all the '.'
176 		 * packages, since on x86 we only want the .i one, and on sparc
177 		 * we want everything _but_ .i. Maybe
178 		 *
179 		 * I think perhaps what we do is, if we don't find a package
180 		 * dependency, on intel we append '.i' and try for that, and on
181 		 * sparc we try the other extensions. Any we find get added.
182 		 *
183 		 * Note also we're quiet on failures. This is because you might
184 		 * be dependant on some outside package.
185 		 */
186 		(void) sprintf(pkgdir, "%s/%s", parentdir, deppkg);
187 		if (stat(pkgdir, &sbuf) == -1) {
188 			if (errno != ENOENT) {
189 				continue;
190 			}
191 			for (suffixes = &suffix_list[0]; *suffixes != NULL;
192 			    suffixes++) {
193 				(void) sprintf(archpkg, "%s%s", deppkg,
194 				    *suffixes);
195 				(void) sprintf(pkgdir, "%s/%s", parentdir,
196 				    archpkg);
197 				if (stat(pkgdir, &sbuf) == -1) {
198 					continue;
199 				}
200 				if (!S_ISDIR(sbuf.st_mode)) {
201 					continue;
202 				}
203 				/* found one */
204 				dependlist = add_dependency(dependlist,
205 				    archpkg);
206 			}
207 		}
208 		if (!S_ISDIR(sbuf.st_mode)) {
209 			continue;
210 		}
211 		dependlist = add_dependency(dependlist, deppkg);
212 	}
213 	(void) fclose(fp);
214 	return (dependlist);
215 }
216 
217 int
218 process_dependencies(const char *pkgname, const char *parentdir,
219     elem_list *list, int verbose)
220 {
221 	int	count = 0;
222 	char	pkgdir[MAXPATHLEN + 1];
223 	pkg_list *dependlist;
224 	pkg_list *tmp;
225 
226 	dependlist = find_dependencies(pkgname, parentdir);
227 /*
228  *	print_dependencies(pkgname, dependlist);
229  */
230 	if (dependlist == NULL)
231 		return (0);
232 
233 	for (tmp = dependlist; tmp != NULL; tmp = tmp->next) {
234 		(void) sprintf(pkgdir, "%s/%s", parentdir, tmp->pkg_name);
235 		count += process_package_dir(tmp->pkg_name, pkgdir, list,
236 		    verbose);
237 	}
238 
239 	free_dependency_list(dependlist);
240 	return (count);
241 }
242