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
processed_package(const char * pkgname)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
mark_processed(const char * pkgname)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 *
add_dependency(pkg_list * dependlist,const char * pkgname)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
free_dependency_list(pkg_list * dependlist)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
print_dependencies(const char * pkgname,pkg_list * dependlist)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 *
find_dependencies(const char * pkgname,const char * parentdir)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
process_dependencies(const char * pkgname,const char * parentdir,elem_list * list,int verbose)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