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