xref: /dflybsd-src/usr.bin/dsynth/pkglist.c (revision 8e25f19b2ed644acdbb2838b45f94c3f9f6c1cbd)
1*8e25f19bSMatthew Dillon /*
2*8e25f19bSMatthew Dillon  * Copyright (c) 2019 The DragonFly Project.  All rights reserved.
3*8e25f19bSMatthew Dillon  *
4*8e25f19bSMatthew Dillon  * This code is derived from software contributed to The DragonFly Project
5*8e25f19bSMatthew Dillon  * by Matthew Dillon <dillon@backplane.com>
6*8e25f19bSMatthew Dillon  *
7*8e25f19bSMatthew Dillon  * This code uses concepts and configuration based on 'synth', by
8*8e25f19bSMatthew Dillon  * John R. Marino <draco@marino.st>, which was written in ada.
9*8e25f19bSMatthew Dillon  *
10*8e25f19bSMatthew Dillon  * Redistribution and use in source and binary forms, with or without
11*8e25f19bSMatthew Dillon  * modification, are permitted provided that the following conditions
12*8e25f19bSMatthew Dillon  * are met:
13*8e25f19bSMatthew Dillon  *
14*8e25f19bSMatthew Dillon  * 1. Redistributions of source code must retain the above copyright
15*8e25f19bSMatthew Dillon  *    notice, this list of conditions and the following disclaimer.
16*8e25f19bSMatthew Dillon  * 2. Redistributions in binary form must reproduce the above copyright
17*8e25f19bSMatthew Dillon  *    notice, this list of conditions and the following disclaimer in
18*8e25f19bSMatthew Dillon  *    the documentation and/or other materials provided with the
19*8e25f19bSMatthew Dillon  *    distribution.
20*8e25f19bSMatthew Dillon  * 3. Neither the name of The DragonFly Project nor the names of its
21*8e25f19bSMatthew Dillon  *    contributors may be used to endorse or promote products derived
22*8e25f19bSMatthew Dillon  *    from this software without specific, prior written permission.
23*8e25f19bSMatthew Dillon  *
24*8e25f19bSMatthew Dillon  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25*8e25f19bSMatthew Dillon  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26*8e25f19bSMatthew Dillon  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27*8e25f19bSMatthew Dillon  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
28*8e25f19bSMatthew Dillon  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29*8e25f19bSMatthew Dillon  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
30*8e25f19bSMatthew Dillon  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31*8e25f19bSMatthew Dillon  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
32*8e25f19bSMatthew Dillon  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
33*8e25f19bSMatthew Dillon  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
34*8e25f19bSMatthew Dillon  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35*8e25f19bSMatthew Dillon  * SUCH DAMAGE.
36*8e25f19bSMatthew Dillon  */
37*8e25f19bSMatthew Dillon 
38*8e25f19bSMatthew Dillon #include "dsynth.h"
39*8e25f19bSMatthew Dillon 
40*8e25f19bSMatthew Dillon #define PKG_HSIZE	32768
41*8e25f19bSMatthew Dillon #define PKG_HMASK	32767
42*8e25f19bSMatthew Dillon 
43*8e25f19bSMatthew Dillon static void childGetPackageInfo(bulk_t *bulk);
44*8e25f19bSMatthew Dillon static void childGetBinaryDistInfo(bulk_t *bulk);
45*8e25f19bSMatthew Dillon static pkg_t *resolveDeps(pkg_t *dep_list, pkg_t ***list_tailp, int gentopo);
46*8e25f19bSMatthew Dillon static void resolveDepString(pkg_t *pkg, char *depstr, int gentopo);
47*8e25f19bSMatthew Dillon static pkg_t *processPackageListBulk(int total);
48*8e25f19bSMatthew Dillon static int scan_and_queue_dir(const char *path, const char *level1, int level);
49*8e25f19bSMatthew Dillon static int scan_binary_repo(const char *path);
50*8e25f19bSMatthew Dillon #if 0
51*8e25f19bSMatthew Dillon static void pkgfree(pkg_t *pkg);
52*8e25f19bSMatthew Dillon #endif
53*8e25f19bSMatthew Dillon 
54*8e25f19bSMatthew Dillon pkg_t *PkgHash1[PKG_HSIZE];	/* by portdir */
55*8e25f19bSMatthew Dillon pkg_t *PkgHash2[PKG_HSIZE];	/* by pkgfile */
56*8e25f19bSMatthew Dillon 
57*8e25f19bSMatthew Dillon /*
58*8e25f19bSMatthew Dillon  * Allocate a new pkg structure plus basic initialization.
59*8e25f19bSMatthew Dillon  */
60*8e25f19bSMatthew Dillon static __inline pkg_t *
61*8e25f19bSMatthew Dillon allocpkg(void)
62*8e25f19bSMatthew Dillon {
63*8e25f19bSMatthew Dillon 	pkg_t *pkg;
64*8e25f19bSMatthew Dillon 
65*8e25f19bSMatthew Dillon 	pkg = calloc(1, sizeof(*pkg));
66*8e25f19bSMatthew Dillon 	pkg->idepon_list.next = &pkg->idepon_list;
67*8e25f19bSMatthew Dillon 	pkg->idepon_list.prev = &pkg->idepon_list;
68*8e25f19bSMatthew Dillon 	pkg->deponi_list.next = &pkg->deponi_list;
69*8e25f19bSMatthew Dillon 	pkg->deponi_list.prev = &pkg->deponi_list;
70*8e25f19bSMatthew Dillon 
71*8e25f19bSMatthew Dillon 	return pkg;
72*8e25f19bSMatthew Dillon }
73*8e25f19bSMatthew Dillon 
74*8e25f19bSMatthew Dillon /*
75*8e25f19bSMatthew Dillon  * Simple hash for lookups
76*8e25f19bSMatthew Dillon  */
77*8e25f19bSMatthew Dillon static __inline int
78*8e25f19bSMatthew Dillon pkghash(const char *str)
79*8e25f19bSMatthew Dillon {
80*8e25f19bSMatthew Dillon 	int hv = 0xABC32923;
81*8e25f19bSMatthew Dillon 	while (*str) {
82*8e25f19bSMatthew Dillon 		hv = (hv << 5) ^ *str;
83*8e25f19bSMatthew Dillon 		++str;
84*8e25f19bSMatthew Dillon 	}
85*8e25f19bSMatthew Dillon 	hv = hv ^ (hv / PKG_HSIZE) ^ (hv / PKG_HSIZE / PKG_HSIZE);
86*8e25f19bSMatthew Dillon 	return (hv & PKG_HMASK);
87*8e25f19bSMatthew Dillon }
88*8e25f19bSMatthew Dillon 
89*8e25f19bSMatthew Dillon static void
90*8e25f19bSMatthew Dillon pkg_enter(pkg_t *pkg)
91*8e25f19bSMatthew Dillon {
92*8e25f19bSMatthew Dillon 	pkg_t **pkgp;
93*8e25f19bSMatthew Dillon 	pkg_t *scan;
94*8e25f19bSMatthew Dillon 
95*8e25f19bSMatthew Dillon 	if (pkg->portdir) {
96*8e25f19bSMatthew Dillon 		pkgp = &PkgHash1[pkghash(pkg->portdir)];
97*8e25f19bSMatthew Dillon 		while ((scan = *pkgp) != NULL) {
98*8e25f19bSMatthew Dillon 			if (strcmp(pkg->portdir, scan->portdir) == 0)
99*8e25f19bSMatthew Dillon 				break;
100*8e25f19bSMatthew Dillon 			pkgp = &scan->hnext1;
101*8e25f19bSMatthew Dillon 		}
102*8e25f19bSMatthew Dillon 		if (scan && (scan->flags & PKGF_PLACEHOLD)) {
103*8e25f19bSMatthew Dillon 			*pkgp = pkg;
104*8e25f19bSMatthew Dillon 			pkg->hnext1 = scan->hnext1;
105*8e25f19bSMatthew Dillon 			free(scan->portdir);
106*8e25f19bSMatthew Dillon 			free(scan);
107*8e25f19bSMatthew Dillon 			scan = NULL;
108*8e25f19bSMatthew Dillon 		}
109*8e25f19bSMatthew Dillon 		if (scan == NULL)
110*8e25f19bSMatthew Dillon 			*pkgp = pkg;
111*8e25f19bSMatthew Dillon 	}
112*8e25f19bSMatthew Dillon 
113*8e25f19bSMatthew Dillon 	if (pkg->pkgfile) {
114*8e25f19bSMatthew Dillon 		pkgp = &PkgHash2[pkghash(pkg->pkgfile)];
115*8e25f19bSMatthew Dillon 		while ((scan = *pkgp) != NULL) {
116*8e25f19bSMatthew Dillon 			if (strcmp(pkg->pkgfile, scan->pkgfile) == 0)
117*8e25f19bSMatthew Dillon 				break;
118*8e25f19bSMatthew Dillon 			pkgp = &scan->hnext2;
119*8e25f19bSMatthew Dillon 		}
120*8e25f19bSMatthew Dillon 		if (scan == NULL)
121*8e25f19bSMatthew Dillon 			*pkgp = pkg;
122*8e25f19bSMatthew Dillon 	}
123*8e25f19bSMatthew Dillon }
124*8e25f19bSMatthew Dillon 
125*8e25f19bSMatthew Dillon static pkg_t *
126*8e25f19bSMatthew Dillon pkg_find(const char *match)
127*8e25f19bSMatthew Dillon {
128*8e25f19bSMatthew Dillon 	pkg_t **pkgp;
129*8e25f19bSMatthew Dillon 	pkg_t *pkg;
130*8e25f19bSMatthew Dillon 
131*8e25f19bSMatthew Dillon 	pkgp = &PkgHash1[pkghash(match)];
132*8e25f19bSMatthew Dillon 	for (pkg = *pkgp; pkg; pkg = pkg->hnext1) {
133*8e25f19bSMatthew Dillon 		if (strcmp(pkg->portdir, match) == 0)
134*8e25f19bSMatthew Dillon 			return pkg;
135*8e25f19bSMatthew Dillon 	}
136*8e25f19bSMatthew Dillon 	pkgp = &PkgHash2[pkghash(match)];
137*8e25f19bSMatthew Dillon 	for (pkg = *pkgp; pkg; pkg = pkg->hnext2) {
138*8e25f19bSMatthew Dillon 		if (strcmp(pkg->pkgfile, match) == 0)
139*8e25f19bSMatthew Dillon 			return pkg;
140*8e25f19bSMatthew Dillon 	}
141*8e25f19bSMatthew Dillon 	return NULL;
142*8e25f19bSMatthew Dillon }
143*8e25f19bSMatthew Dillon 
144*8e25f19bSMatthew Dillon /*
145*8e25f19bSMatthew Dillon  * Parse a specific list of ports via origin name (portdir/subdir)
146*8e25f19bSMatthew Dillon  */
147*8e25f19bSMatthew Dillon pkg_t *
148*8e25f19bSMatthew Dillon ParsePackageList(int n, char **ary)
149*8e25f19bSMatthew Dillon {
150*8e25f19bSMatthew Dillon 	pkg_t *list;
151*8e25f19bSMatthew Dillon 	int i;
152*8e25f19bSMatthew Dillon 	int total;
153*8e25f19bSMatthew Dillon 
154*8e25f19bSMatthew Dillon 	total = 0;
155*8e25f19bSMatthew Dillon 	initbulk(childGetPackageInfo, MaxBulk);
156*8e25f19bSMatthew Dillon 
157*8e25f19bSMatthew Dillon 	queuebulk("ports-mgmt", "pkg", NULL, NULL);
158*8e25f19bSMatthew Dillon 	for (i = 0; i < n; ++i) {
159*8e25f19bSMatthew Dillon 		char *l1;
160*8e25f19bSMatthew Dillon 		char *l2;
161*8e25f19bSMatthew Dillon 
162*8e25f19bSMatthew Dillon 		l1 = strdup(ary[i]);
163*8e25f19bSMatthew Dillon 		l2 = strchr(l1, '/');
164*8e25f19bSMatthew Dillon 		if (l2) {
165*8e25f19bSMatthew Dillon 			*l2++ = 0;
166*8e25f19bSMatthew Dillon 			queuebulk(l1, l2, NULL, NULL);
167*8e25f19bSMatthew Dillon 			++total;
168*8e25f19bSMatthew Dillon 		} else {
169*8e25f19bSMatthew Dillon 			printf("Bad portdir specification: %s\n", l1);
170*8e25f19bSMatthew Dillon 		}
171*8e25f19bSMatthew Dillon 		free(l1);
172*8e25f19bSMatthew Dillon 	}
173*8e25f19bSMatthew Dillon 	printf("Processing %d ports\n", total);
174*8e25f19bSMatthew Dillon 
175*8e25f19bSMatthew Dillon 	list = processPackageListBulk(total);
176*8e25f19bSMatthew Dillon 
177*8e25f19bSMatthew Dillon 	return list;
178*8e25f19bSMatthew Dillon }
179*8e25f19bSMatthew Dillon 
180*8e25f19bSMatthew Dillon /*
181*8e25f19bSMatthew Dillon  * Parse packages from the list installed on the system.
182*8e25f19bSMatthew Dillon  */
183*8e25f19bSMatthew Dillon pkg_t *
184*8e25f19bSMatthew Dillon GetLocalPackageList(void)
185*8e25f19bSMatthew Dillon {
186*8e25f19bSMatthew Dillon 	pkg_t *list;
187*8e25f19bSMatthew Dillon 	FILE *fp;
188*8e25f19bSMatthew Dillon 	char *base;
189*8e25f19bSMatthew Dillon 	char *l1;
190*8e25f19bSMatthew Dillon 	char *l2;
191*8e25f19bSMatthew Dillon 	int total;
192*8e25f19bSMatthew Dillon 	size_t len;
193*8e25f19bSMatthew Dillon 
194*8e25f19bSMatthew Dillon 	initbulk(childGetPackageInfo, MaxBulk);
195*8e25f19bSMatthew Dillon 	total = 0;
196*8e25f19bSMatthew Dillon 
197*8e25f19bSMatthew Dillon 	fp = popen("pkg info -a -o", "r");
198*8e25f19bSMatthew Dillon 
199*8e25f19bSMatthew Dillon 	queuebulk("ports-mgmt", "pkg", NULL, NULL);
200*8e25f19bSMatthew Dillon 	while ((base = fgetln(fp, &len)) != NULL) {
201*8e25f19bSMatthew Dillon 		if (len == 0 || base[len-1] != '\n')
202*8e25f19bSMatthew Dillon 			continue;
203*8e25f19bSMatthew Dillon 		base[--len] = 0;
204*8e25f19bSMatthew Dillon 		if (strtok(base, " \t") == NULL) {
205*8e25f19bSMatthew Dillon 			printf("Badly formatted pkg info line: %s\n", base);
206*8e25f19bSMatthew Dillon 			continue;
207*8e25f19bSMatthew Dillon 		}
208*8e25f19bSMatthew Dillon 		l1 = strtok(NULL, " \t");
209*8e25f19bSMatthew Dillon 		if (l1 == NULL) {
210*8e25f19bSMatthew Dillon 			printf("Badly formatted pkg info line: %s\n", base);
211*8e25f19bSMatthew Dillon 			continue;
212*8e25f19bSMatthew Dillon 		}
213*8e25f19bSMatthew Dillon 
214*8e25f19bSMatthew Dillon 		l2 = strchr(l1, '/');
215*8e25f19bSMatthew Dillon 		if (l2) {
216*8e25f19bSMatthew Dillon 			*l2++ = 0;
217*8e25f19bSMatthew Dillon 			queuebulk(l1, l2, NULL, NULL);
218*8e25f19bSMatthew Dillon 			++total;
219*8e25f19bSMatthew Dillon 		} else {
220*8e25f19bSMatthew Dillon 			printf("Badly formatted specification: %s\n", l1);
221*8e25f19bSMatthew Dillon 		}
222*8e25f19bSMatthew Dillon 	}
223*8e25f19bSMatthew Dillon 	pclose(fp);
224*8e25f19bSMatthew Dillon 
225*8e25f19bSMatthew Dillon 	printf("Processing %d ports\n", total);
226*8e25f19bSMatthew Dillon 
227*8e25f19bSMatthew Dillon 	list = processPackageListBulk(total);
228*8e25f19bSMatthew Dillon 
229*8e25f19bSMatthew Dillon 	return list;
230*8e25f19bSMatthew Dillon }
231*8e25f19bSMatthew Dillon 
232*8e25f19bSMatthew Dillon pkg_t *
233*8e25f19bSMatthew Dillon GetFullPackageList(void)
234*8e25f19bSMatthew Dillon {
235*8e25f19bSMatthew Dillon 	int total;
236*8e25f19bSMatthew Dillon 
237*8e25f19bSMatthew Dillon 	initbulk(childGetPackageInfo, MaxBulk);
238*8e25f19bSMatthew Dillon 
239*8e25f19bSMatthew Dillon 	total = scan_and_queue_dir(DPortsPath, NULL, 1);
240*8e25f19bSMatthew Dillon 	printf("Scanning %d ports\n", total);
241*8e25f19bSMatthew Dillon 
242*8e25f19bSMatthew Dillon 	return processPackageListBulk(total);
243*8e25f19bSMatthew Dillon }
244*8e25f19bSMatthew Dillon 
245*8e25f19bSMatthew Dillon /*
246*8e25f19bSMatthew Dillon  * Caller has queued the process list for bulk operation.  We retrieve
247*8e25f19bSMatthew Dillon  * the results and clean up the bulk operation (we may have to do a second
248*8e25f19bSMatthew Dillon  * bulk operation so we have to be the ones to clean it up).
249*8e25f19bSMatthew Dillon  */
250*8e25f19bSMatthew Dillon static pkg_t *
251*8e25f19bSMatthew Dillon processPackageListBulk(int total)
252*8e25f19bSMatthew Dillon {
253*8e25f19bSMatthew Dillon 	bulk_t *bulk;
254*8e25f19bSMatthew Dillon 	pkg_t *scan;
255*8e25f19bSMatthew Dillon 	pkg_t *list;
256*8e25f19bSMatthew Dillon 	pkg_t *dep_list;
257*8e25f19bSMatthew Dillon 	pkg_t **list_tail;
258*8e25f19bSMatthew Dillon 	int count;
259*8e25f19bSMatthew Dillon 
260*8e25f19bSMatthew Dillon 	list = NULL;
261*8e25f19bSMatthew Dillon 	list_tail = &list;
262*8e25f19bSMatthew Dillon 	count = 0;
263*8e25f19bSMatthew Dillon 
264*8e25f19bSMatthew Dillon 	while ((bulk = getbulk()) != NULL) {
265*8e25f19bSMatthew Dillon 		++count;
266*8e25f19bSMatthew Dillon 		if ((count & 255) == 0) {
267*8e25f19bSMatthew Dillon 			printf("%6.2f%%\r",
268*8e25f19bSMatthew Dillon 				(double)count * 100.0 / (double)total + 0.001);
269*8e25f19bSMatthew Dillon 			fflush(stdout);
270*8e25f19bSMatthew Dillon 		}
271*8e25f19bSMatthew Dillon 		if (bulk->list) {
272*8e25f19bSMatthew Dillon 			*list_tail = bulk->list;
273*8e25f19bSMatthew Dillon 			bulk->list = NULL;
274*8e25f19bSMatthew Dillon 			while (*list_tail) {
275*8e25f19bSMatthew Dillon 				pkg_enter(*list_tail);
276*8e25f19bSMatthew Dillon 				list_tail = &(*list_tail)->bnext;
277*8e25f19bSMatthew Dillon 			}
278*8e25f19bSMatthew Dillon 		}
279*8e25f19bSMatthew Dillon 		freebulk(bulk);
280*8e25f19bSMatthew Dillon 	}
281*8e25f19bSMatthew Dillon 	printf("\nTotal %d\n", count);
282*8e25f19bSMatthew Dillon 	fflush(stdout);
283*8e25f19bSMatthew Dillon 
284*8e25f19bSMatthew Dillon 	/*
285*8e25f19bSMatthew Dillon 	 * Resolve all dependencies for the related packages, potentially
286*8e25f19bSMatthew Dillon 	 * adding anything that could not be found to the list.  This will
287*8e25f19bSMatthew Dillon 	 * continue to issue bulk operations and process the result until
288*8e25f19bSMatthew Dillon 	 * no dependencies are left.
289*8e25f19bSMatthew Dillon 	 */
290*8e25f19bSMatthew Dillon 	printf("Resolving dependencies...");
291*8e25f19bSMatthew Dillon 	fflush(stdout);
292*8e25f19bSMatthew Dillon 	dep_list = list;
293*8e25f19bSMatthew Dillon 	while (dep_list) {
294*8e25f19bSMatthew Dillon 		dep_list = resolveDeps(dep_list, &list_tail, 0);
295*8e25f19bSMatthew Dillon 	}
296*8e25f19bSMatthew Dillon 	printf("done\n");
297*8e25f19bSMatthew Dillon 
298*8e25f19bSMatthew Dillon 	donebulk();
299*8e25f19bSMatthew Dillon 
300*8e25f19bSMatthew Dillon 	/*
301*8e25f19bSMatthew Dillon 	 * Generate the topology
302*8e25f19bSMatthew Dillon 	 */
303*8e25f19bSMatthew Dillon 	resolveDeps(list, NULL, 1);
304*8e25f19bSMatthew Dillon 
305*8e25f19bSMatthew Dillon 	/*
306*8e25f19bSMatthew Dillon 	 * Do a final count, ignore place holders.
307*8e25f19bSMatthew Dillon 	 */
308*8e25f19bSMatthew Dillon 	count = 0;
309*8e25f19bSMatthew Dillon 	for (scan = list; scan; scan = scan->bnext) {
310*8e25f19bSMatthew Dillon 		if ((scan->flags & PKGF_ERROR) == 0) {
311*8e25f19bSMatthew Dillon 			++count;
312*8e25f19bSMatthew Dillon 		}
313*8e25f19bSMatthew Dillon 	}
314*8e25f19bSMatthew Dillon 	printf("Total Returned %d\n", count);
315*8e25f19bSMatthew Dillon 
316*8e25f19bSMatthew Dillon 	/*
317*8e25f19bSMatthew Dillon 	 * Scan our binary distributions and related dependencies looking
318*8e25f19bSMatthew Dillon 	 * for any packages that have already been built.
319*8e25f19bSMatthew Dillon 	 */
320*8e25f19bSMatthew Dillon 	initbulk(childGetBinaryDistInfo, MaxBulk);
321*8e25f19bSMatthew Dillon 	total = scan_binary_repo(RepositoryPath);
322*8e25f19bSMatthew Dillon 	count = 0;
323*8e25f19bSMatthew Dillon 	printf("Scanning %d packages\n", total);
324*8e25f19bSMatthew Dillon 
325*8e25f19bSMatthew Dillon 	while ((bulk = getbulk()) != NULL) {
326*8e25f19bSMatthew Dillon 		++count;
327*8e25f19bSMatthew Dillon 		if ((count & 255) == 0) {
328*8e25f19bSMatthew Dillon 			printf("%6.2f%%\r",
329*8e25f19bSMatthew Dillon 				(double)count * 100.0 / (double)total + 0.001);
330*8e25f19bSMatthew Dillon 			fflush(stdout);
331*8e25f19bSMatthew Dillon 		}
332*8e25f19bSMatthew Dillon 		freebulk(bulk);
333*8e25f19bSMatthew Dillon 	}
334*8e25f19bSMatthew Dillon 	printf("\nTotal %d\n", count);
335*8e25f19bSMatthew Dillon 	fflush(stdout);
336*8e25f19bSMatthew Dillon 	donebulk();
337*8e25f19bSMatthew Dillon 
338*8e25f19bSMatthew Dillon 	printf("all done\n");
339*8e25f19bSMatthew Dillon 
340*8e25f19bSMatthew Dillon 	return list;
341*8e25f19bSMatthew Dillon }
342*8e25f19bSMatthew Dillon 
343*8e25f19bSMatthew Dillon pkg_t *
344*8e25f19bSMatthew Dillon GetPkgPkg(pkg_t *list)
345*8e25f19bSMatthew Dillon {
346*8e25f19bSMatthew Dillon 	bulk_t *bulk;
347*8e25f19bSMatthew Dillon 	pkg_t *scan;
348*8e25f19bSMatthew Dillon 
349*8e25f19bSMatthew Dillon 	for (scan = list; scan; scan = scan->bnext) {
350*8e25f19bSMatthew Dillon 		if (strcmp(scan->portdir, "ports-mgmt/pkg") == 0)
351*8e25f19bSMatthew Dillon 			return scan;
352*8e25f19bSMatthew Dillon 	}
353*8e25f19bSMatthew Dillon 
354*8e25f19bSMatthew Dillon 	initbulk(childGetPackageInfo, MaxBulk);
355*8e25f19bSMatthew Dillon 	queuebulk("ports-mgmt", "pkg", NULL, NULL);
356*8e25f19bSMatthew Dillon 	bulk = getbulk();
357*8e25f19bSMatthew Dillon 	dassert(bulk, "Cannot find ports-mgmt/pkg");
358*8e25f19bSMatthew Dillon 	scan = bulk->list;
359*8e25f19bSMatthew Dillon 	bulk->list = NULL;
360*8e25f19bSMatthew Dillon 	freebulk(bulk);
361*8e25f19bSMatthew Dillon 	donebulk();
362*8e25f19bSMatthew Dillon 
363*8e25f19bSMatthew Dillon 	return scan;
364*8e25f19bSMatthew Dillon }
365*8e25f19bSMatthew Dillon 
366*8e25f19bSMatthew Dillon /*
367*8e25f19bSMatthew Dillon  * Run through the list resolving dependencies and constructing the topology
368*8e25f19bSMatthew Dillon  * linkages.   This may append packages to the list.
369*8e25f19bSMatthew Dillon  */
370*8e25f19bSMatthew Dillon static pkg_t *
371*8e25f19bSMatthew Dillon resolveDeps(pkg_t *list, pkg_t ***list_tailp, int gentopo)
372*8e25f19bSMatthew Dillon {
373*8e25f19bSMatthew Dillon 	pkg_t *scan;
374*8e25f19bSMatthew Dillon 	pkg_t *ret_list = NULL;
375*8e25f19bSMatthew Dillon 	bulk_t *bulk;
376*8e25f19bSMatthew Dillon 
377*8e25f19bSMatthew Dillon 	for (scan = list; scan; scan = scan->bnext) {
378*8e25f19bSMatthew Dillon 		resolveDepString(scan, scan->fetch_deps, gentopo);
379*8e25f19bSMatthew Dillon 		resolveDepString(scan, scan->ext_deps, gentopo);
380*8e25f19bSMatthew Dillon 		resolveDepString(scan, scan->patch_deps, gentopo);
381*8e25f19bSMatthew Dillon 		resolveDepString(scan, scan->build_deps, gentopo);
382*8e25f19bSMatthew Dillon 		resolveDepString(scan, scan->lib_deps, gentopo);
383*8e25f19bSMatthew Dillon 		resolveDepString(scan, scan->run_deps, gentopo);
384*8e25f19bSMatthew Dillon 	}
385*8e25f19bSMatthew Dillon 
386*8e25f19bSMatthew Dillon 	/*
387*8e25f19bSMatthew Dillon 	 * No bulk ops are queued when doing the final topology
388*8e25f19bSMatthew Dillon 	 * generation.
389*8e25f19bSMatthew Dillon 	 */
390*8e25f19bSMatthew Dillon 	if (gentopo)
391*8e25f19bSMatthew Dillon 		return NULL;
392*8e25f19bSMatthew Dillon 	while ((bulk = getbulk()) != NULL) {
393*8e25f19bSMatthew Dillon 		if (bulk->list) {
394*8e25f19bSMatthew Dillon 			if (ret_list == NULL)
395*8e25f19bSMatthew Dillon 				ret_list = bulk->list;
396*8e25f19bSMatthew Dillon 			**list_tailp = bulk->list;
397*8e25f19bSMatthew Dillon 			bulk->list = NULL;
398*8e25f19bSMatthew Dillon 			while (**list_tailp) {
399*8e25f19bSMatthew Dillon 				pkg_enter(**list_tailp);
400*8e25f19bSMatthew Dillon 				*list_tailp = &(**list_tailp)->bnext;
401*8e25f19bSMatthew Dillon 			}
402*8e25f19bSMatthew Dillon 		}
403*8e25f19bSMatthew Dillon 		freebulk(bulk);
404*8e25f19bSMatthew Dillon 	}
405*8e25f19bSMatthew Dillon 	return (ret_list);
406*8e25f19bSMatthew Dillon }
407*8e25f19bSMatthew Dillon 
408*8e25f19bSMatthew Dillon static void
409*8e25f19bSMatthew Dillon resolveDepString(pkg_t *pkg, char *depstr, int gentopo)
410*8e25f19bSMatthew Dillon {
411*8e25f19bSMatthew Dillon 	char *copy_base;
412*8e25f19bSMatthew Dillon 	char *copy;
413*8e25f19bSMatthew Dillon 	char *dep;
414*8e25f19bSMatthew Dillon 	char *sep;
415*8e25f19bSMatthew Dillon 	char *tag;
416*8e25f19bSMatthew Dillon 	char *flavor;
417*8e25f19bSMatthew Dillon 	pkg_t *dpkg;
418*8e25f19bSMatthew Dillon 
419*8e25f19bSMatthew Dillon 	if (depstr == NULL || depstr[0] == 0)
420*8e25f19bSMatthew Dillon 		return;
421*8e25f19bSMatthew Dillon 
422*8e25f19bSMatthew Dillon 	copy_base = strdup(depstr);
423*8e25f19bSMatthew Dillon 	copy = copy_base;
424*8e25f19bSMatthew Dillon 
425*8e25f19bSMatthew Dillon 	for (;;) {
426*8e25f19bSMatthew Dillon 		do {
427*8e25f19bSMatthew Dillon 			dep = strsep(&copy, " \t");
428*8e25f19bSMatthew Dillon 		} while (dep && *dep == 0);
429*8e25f19bSMatthew Dillon 		if (dep == NULL)
430*8e25f19bSMatthew Dillon 			break;
431*8e25f19bSMatthew Dillon 		dep = strchr(dep, ':');
432*8e25f19bSMatthew Dillon 		if (dep == NULL || *dep != ':') {
433*8e25f19bSMatthew Dillon 			printf("Error parsing dependency for %s: %s\n",
434*8e25f19bSMatthew Dillon 			       pkg->portdir, copy_base);
435*8e25f19bSMatthew Dillon 			continue;
436*8e25f19bSMatthew Dillon 		}
437*8e25f19bSMatthew Dillon 		++dep;
438*8e25f19bSMatthew Dillon 
439*8e25f19bSMatthew Dillon 		/*
440*8e25f19bSMatthew Dillon 		 * Strip-off any DPortsPath prefix.  EXTRACT_DEPENDS
441*8e25f19bSMatthew Dillon 		 * often (always?) generates this prefix.
442*8e25f19bSMatthew Dillon 		 */
443*8e25f19bSMatthew Dillon 		if (strncmp(dep, DPortsPath, strlen(DPortsPath)) == 0) {
444*8e25f19bSMatthew Dillon 			dep += strlen(DPortsPath);
445*8e25f19bSMatthew Dillon 			if (*dep == '/')
446*8e25f19bSMatthew Dillon 				++dep;
447*8e25f19bSMatthew Dillon 		}
448*8e25f19bSMatthew Dillon 
449*8e25f19bSMatthew Dillon 		/*
450*8e25f19bSMatthew Dillon 		 * Strip-off any tag (such as :patch).  We don't try to
451*8e25f19bSMatthew Dillon 		 * organize dependencies at this fine a grain (for now).
452*8e25f19bSMatthew Dillon 		 */
453*8e25f19bSMatthew Dillon 		tag = strchr(dep, ':');
454*8e25f19bSMatthew Dillon 		if (tag)
455*8e25f19bSMatthew Dillon 			*tag++ = 0;
456*8e25f19bSMatthew Dillon 
457*8e25f19bSMatthew Dillon 		/*
458*8e25f19bSMatthew Dillon 		 * Locate the dependency
459*8e25f19bSMatthew Dillon 		 */
460*8e25f19bSMatthew Dillon 		if ((dpkg = pkg_find(dep)) != NULL) {
461*8e25f19bSMatthew Dillon 			if (gentopo) {
462*8e25f19bSMatthew Dillon 				pkglink_t *link;
463*8e25f19bSMatthew Dillon 
464*8e25f19bSMatthew Dillon 				/*
465*8e25f19bSMatthew Dillon 				 * NOTE: idep_count is calculated recursively
466*8e25f19bSMatthew Dillon 				 *	 at build-time
467*8e25f19bSMatthew Dillon 				 */
468*8e25f19bSMatthew Dillon 				ddprintf(0, "Add Dependency %s -> %s\n",
469*8e25f19bSMatthew Dillon 					pkg->portdir, dpkg->portdir);
470*8e25f19bSMatthew Dillon 				link = calloc(1, sizeof(*link));
471*8e25f19bSMatthew Dillon 				link->pkg = dpkg;
472*8e25f19bSMatthew Dillon 				link->next = &pkg->idepon_list;
473*8e25f19bSMatthew Dillon 				link->prev = pkg->idepon_list.prev;
474*8e25f19bSMatthew Dillon 				link->next->prev = link;
475*8e25f19bSMatthew Dillon 				link->prev->next = link;
476*8e25f19bSMatthew Dillon 
477*8e25f19bSMatthew Dillon 				link = calloc(1, sizeof(*link));
478*8e25f19bSMatthew Dillon 				link->pkg = pkg;
479*8e25f19bSMatthew Dillon 				link->next = &dpkg->deponi_list;
480*8e25f19bSMatthew Dillon 				link->prev = dpkg->deponi_list.prev;
481*8e25f19bSMatthew Dillon 				link->next->prev = link;
482*8e25f19bSMatthew Dillon 				link->prev->next = link;
483*8e25f19bSMatthew Dillon 				++dpkg->depi_count;
484*8e25f19bSMatthew Dillon 			}
485*8e25f19bSMatthew Dillon 			continue;
486*8e25f19bSMatthew Dillon 		}
487*8e25f19bSMatthew Dillon 
488*8e25f19bSMatthew Dillon 		/*
489*8e25f19bSMatthew Dillon 		 * This shouldn't happen because we already took a first
490*8e25f19bSMatthew Dillon 		 * pass and should have generated the pkgs.
491*8e25f19bSMatthew Dillon 		 */
492*8e25f19bSMatthew Dillon 		if (gentopo) {
493*8e25f19bSMatthew Dillon 			printf("Topology Generate failed for %s: %s\n",
494*8e25f19bSMatthew Dillon 				pkg->portdir, copy_base);
495*8e25f19bSMatthew Dillon 			continue;
496*8e25f19bSMatthew Dillon 		}
497*8e25f19bSMatthew Dillon 
498*8e25f19bSMatthew Dillon 		/*
499*8e25f19bSMatthew Dillon 		 * Separate out the two dports directory components and
500*8e25f19bSMatthew Dillon 		 * extract the optional '@flavor' specification.
501*8e25f19bSMatthew Dillon 		 */
502*8e25f19bSMatthew Dillon 		sep = strchr(dep, '/');
503*8e25f19bSMatthew Dillon 		if (sep == NULL) {
504*8e25f19bSMatthew Dillon 			printf("Error parsing dependency for %s: %s\n",
505*8e25f19bSMatthew Dillon 			       pkg->portdir, copy_base);
506*8e25f19bSMatthew Dillon 			continue;
507*8e25f19bSMatthew Dillon 		}
508*8e25f19bSMatthew Dillon 		*sep++ = 0;
509*8e25f19bSMatthew Dillon 
510*8e25f19bSMatthew Dillon 		if (tag)
511*8e25f19bSMatthew Dillon 			flavor = strrchr(tag, '@');
512*8e25f19bSMatthew Dillon 		else
513*8e25f19bSMatthew Dillon 			flavor = strrchr(sep, '@');
514*8e25f19bSMatthew Dillon 
515*8e25f19bSMatthew Dillon 		if (flavor)
516*8e25f19bSMatthew Dillon 			*flavor++ = 0;
517*8e25f19bSMatthew Dillon 
518*8e25f19bSMatthew Dillon 		if (flavor)
519*8e25f19bSMatthew Dillon 			ddprintf(0, "QUEUE DEPENDENCY FROM PKG %s: %s/%s@%s\n",
520*8e25f19bSMatthew Dillon 			       pkg->portdir, dep, sep, flavor);
521*8e25f19bSMatthew Dillon 		else
522*8e25f19bSMatthew Dillon 			ddprintf(0, "QUEUE DEPENDENCY FROM PKG %s: %s/%s\n",
523*8e25f19bSMatthew Dillon 			       pkg->portdir, dep, sep);
524*8e25f19bSMatthew Dillon 
525*8e25f19bSMatthew Dillon 		/*
526*8e25f19bSMatthew Dillon 		 * Use a place-holder to prevent duplicate dependencies from
527*8e25f19bSMatthew Dillon 		 * being processed.  The placeholder will be replaced by
528*8e25f19bSMatthew Dillon 		 * the actual dependency.
529*8e25f19bSMatthew Dillon 		 */
530*8e25f19bSMatthew Dillon 		dpkg = allocpkg();
531*8e25f19bSMatthew Dillon 		if (flavor)
532*8e25f19bSMatthew Dillon 			asprintf(&dpkg->portdir, "%s/%s@%s", dep, sep, flavor);
533*8e25f19bSMatthew Dillon 		else
534*8e25f19bSMatthew Dillon 			asprintf(&dpkg->portdir, "%s/%s", dep, sep);
535*8e25f19bSMatthew Dillon 		dpkg->flags = PKGF_PLACEHOLD;
536*8e25f19bSMatthew Dillon 		pkg_enter(dpkg);
537*8e25f19bSMatthew Dillon 
538*8e25f19bSMatthew Dillon 		queuebulk(dep, sep, flavor, NULL);
539*8e25f19bSMatthew Dillon 	}
540*8e25f19bSMatthew Dillon 	free(copy_base);
541*8e25f19bSMatthew Dillon }
542*8e25f19bSMatthew Dillon 
543*8e25f19bSMatthew Dillon void
544*8e25f19bSMatthew Dillon FreePackageList(pkg_t *pkgs __unused)
545*8e25f19bSMatthew Dillon {
546*8e25f19bSMatthew Dillon 	dfatal("not implemented");
547*8e25f19bSMatthew Dillon }
548*8e25f19bSMatthew Dillon 
549*8e25f19bSMatthew Dillon /*
550*8e25f19bSMatthew Dillon  * Scan some or all dports to allocate the related pkg structure.  Dependencies
551*8e25f19bSMatthew Dillon  * are stored but not processed.
552*8e25f19bSMatthew Dillon  *
553*8e25f19bSMatthew Dillon  * Threaded function
554*8e25f19bSMatthew Dillon  */
555*8e25f19bSMatthew Dillon static void
556*8e25f19bSMatthew Dillon childGetPackageInfo(bulk_t *bulk)
557*8e25f19bSMatthew Dillon {
558*8e25f19bSMatthew Dillon 	pkg_t *pkg;
559*8e25f19bSMatthew Dillon 	pkg_t *dummy_node;
560*8e25f19bSMatthew Dillon 	pkg_t **list_tail;
561*8e25f19bSMatthew Dillon 	char buf[1024];
562*8e25f19bSMatthew Dillon 	char *flavors_save;
563*8e25f19bSMatthew Dillon 	char *flavors;
564*8e25f19bSMatthew Dillon 	char *flavor;
565*8e25f19bSMatthew Dillon 	char *ptr;
566*8e25f19bSMatthew Dillon 	FILE *fp;
567*8e25f19bSMatthew Dillon 	int line;
568*8e25f19bSMatthew Dillon 	size_t len;
569*8e25f19bSMatthew Dillon 
570*8e25f19bSMatthew Dillon 	/*
571*8e25f19bSMatthew Dillon 	 * If the package has flavors we will loop on each one.  If a flavor
572*8e25f19bSMatthew Dillon 	 * is not passed in s3 we will loop on all flavors, otherwise we will
573*8e25f19bSMatthew Dillon 	 * only process the passed-in flavor.
574*8e25f19bSMatthew Dillon 	 */
575*8e25f19bSMatthew Dillon 	flavor = bulk->s3;	/* usually NULL */
576*8e25f19bSMatthew Dillon 	flavors = NULL;
577*8e25f19bSMatthew Dillon 	flavors_save = NULL;
578*8e25f19bSMatthew Dillon 	dummy_node = NULL;
579*8e25f19bSMatthew Dillon 
580*8e25f19bSMatthew Dillon 	bulk->list = NULL;
581*8e25f19bSMatthew Dillon 	list_tail = &bulk->list;
582*8e25f19bSMatthew Dillon again:
583*8e25f19bSMatthew Dillon 	snprintf(buf, sizeof(buf),
584*8e25f19bSMatthew Dillon 		 "exec %s -C %s/%s/%s %s%s "
585*8e25f19bSMatthew Dillon 		 "-VPKGVERSION "
586*8e25f19bSMatthew Dillon 		 "-VPKGFILE:T "
587*8e25f19bSMatthew Dillon 		 "-VMAKE_JOBS_NUMBER "
588*8e25f19bSMatthew Dillon 		 "-VIGNORE "
589*8e25f19bSMatthew Dillon 		 "-VFETCH_DEPENDS "
590*8e25f19bSMatthew Dillon 		 "-VEXTRACT_DEPENDS "
591*8e25f19bSMatthew Dillon 		 "-VPATCH_DEPENDS "
592*8e25f19bSMatthew Dillon 		 "-VBUILD_DEPENDS "
593*8e25f19bSMatthew Dillon 		 "-VLIB_DEPENDS "
594*8e25f19bSMatthew Dillon 		 "-VRUN_DEPENDS "
595*8e25f19bSMatthew Dillon 		 "-VSELECTED_OPTIONS "
596*8e25f19bSMatthew Dillon 		 "-VDESELECTED_OPTIONS "
597*8e25f19bSMatthew Dillon 		 "-VUSE_LINUX "
598*8e25f19bSMatthew Dillon 		 "-VFLAVORS",
599*8e25f19bSMatthew Dillon 		 MAKE_BINARY,
600*8e25f19bSMatthew Dillon 		 DPortsPath, bulk->s1, bulk->s2,
601*8e25f19bSMatthew Dillon 		 (flavor ? "FLAVOR=" : ""),
602*8e25f19bSMatthew Dillon 		 (flavor ? flavor : ""));
603*8e25f19bSMatthew Dillon 	fp = popen(buf, "r");
604*8e25f19bSMatthew Dillon 	line = 1;
605*8e25f19bSMatthew Dillon 
606*8e25f19bSMatthew Dillon 	pkg = allocpkg();
607*8e25f19bSMatthew Dillon 	if (flavor)
608*8e25f19bSMatthew Dillon 		asprintf(&pkg->portdir, "%s/%s@%s", bulk->s1, bulk->s2, flavor);
609*8e25f19bSMatthew Dillon 	else
610*8e25f19bSMatthew Dillon 		asprintf(&pkg->portdir, "%s/%s", bulk->s1, bulk->s2);
611*8e25f19bSMatthew Dillon 
612*8e25f19bSMatthew Dillon 	while ((ptr = fgetln(fp, &len)) != NULL) {
613*8e25f19bSMatthew Dillon 		if (len == 0 || ptr[len-1] != '\n') {
614*8e25f19bSMatthew Dillon 			dfatal("Bad package info for %s/%s response line %d",
615*8e25f19bSMatthew Dillon 			       bulk->s1, bulk->s2, line);
616*8e25f19bSMatthew Dillon 		}
617*8e25f19bSMatthew Dillon 		ptr[--len] = 0;
618*8e25f19bSMatthew Dillon 
619*8e25f19bSMatthew Dillon 		switch(line) {
620*8e25f19bSMatthew Dillon 		case 1:		/* PKGVERSION */
621*8e25f19bSMatthew Dillon 			asprintf(&pkg->version, "%s", ptr);
622*8e25f19bSMatthew Dillon 			break;
623*8e25f19bSMatthew Dillon 		case 2:		/* PKGFILE */
624*8e25f19bSMatthew Dillon 			asprintf(&pkg->pkgfile, "%s", ptr);
625*8e25f19bSMatthew Dillon 			break;
626*8e25f19bSMatthew Dillon 		case 3:		/* MAKE_JOBS_NUMBER */
627*8e25f19bSMatthew Dillon 			pkg->make_jobs_number = strtol(ptr, NULL, 0);
628*8e25f19bSMatthew Dillon 			break;
629*8e25f19bSMatthew Dillon 		case 4:		/* IGNORE */
630*8e25f19bSMatthew Dillon 			asprintf(&pkg->ignore, "%s", ptr);
631*8e25f19bSMatthew Dillon 			break;
632*8e25f19bSMatthew Dillon 		case 5:		/* FETCH_DEPENDS */
633*8e25f19bSMatthew Dillon 			asprintf(&pkg->fetch_deps, "%s", ptr);
634*8e25f19bSMatthew Dillon 			break;
635*8e25f19bSMatthew Dillon 		case 6:		/* EXTRACT_DEPENDS */
636*8e25f19bSMatthew Dillon 			asprintf(&pkg->ext_deps, "%s", ptr);
637*8e25f19bSMatthew Dillon 			break;
638*8e25f19bSMatthew Dillon 		case 7:		/* PATCH_DEPENDS */
639*8e25f19bSMatthew Dillon 			asprintf(&pkg->patch_deps, "%s", ptr);
640*8e25f19bSMatthew Dillon 			break;
641*8e25f19bSMatthew Dillon 		case 8:		/* BUILD_DEPENDS */
642*8e25f19bSMatthew Dillon 			asprintf(&pkg->build_deps, "%s", ptr);
643*8e25f19bSMatthew Dillon 			break;
644*8e25f19bSMatthew Dillon 		case 9:		/* LIB_DEPENDS */
645*8e25f19bSMatthew Dillon 			asprintf(&pkg->lib_deps, "%s", ptr);
646*8e25f19bSMatthew Dillon 			break;
647*8e25f19bSMatthew Dillon 		case 10:	/* RUN_DEPENDS */
648*8e25f19bSMatthew Dillon 			asprintf(&pkg->run_deps, "%s", ptr);
649*8e25f19bSMatthew Dillon 			break;
650*8e25f19bSMatthew Dillon 		case 11:	/* SELECTED_OPTIONS */
651*8e25f19bSMatthew Dillon 			asprintf(&pkg->pos_options, "%s", ptr);
652*8e25f19bSMatthew Dillon 			break;
653*8e25f19bSMatthew Dillon 		case 12:	/* DESELECTED_OPTIONS */
654*8e25f19bSMatthew Dillon 			asprintf(&pkg->neg_options, "%s", ptr);
655*8e25f19bSMatthew Dillon 			break;
656*8e25f19bSMatthew Dillon 		case 13:	/* USE_LINUX */
657*8e25f19bSMatthew Dillon 			if (ptr[0])
658*8e25f19bSMatthew Dillon 				pkg->use_linux = 1;
659*8e25f19bSMatthew Dillon 			break;
660*8e25f19bSMatthew Dillon 		case 14:	/* FLAVORS */
661*8e25f19bSMatthew Dillon 			asprintf(&pkg->flavors, "%s", ptr);
662*8e25f19bSMatthew Dillon 			break;
663*8e25f19bSMatthew Dillon 		default:
664*8e25f19bSMatthew Dillon 			printf("EXTRA LINE: %s\n", ptr);
665*8e25f19bSMatthew Dillon 			break;
666*8e25f19bSMatthew Dillon 		}
667*8e25f19bSMatthew Dillon 		++line;
668*8e25f19bSMatthew Dillon 	}
669*8e25f19bSMatthew Dillon 	if (line == 1) {
670*8e25f19bSMatthew Dillon 		printf("DPort not found: %s/%s\n", bulk->s1, bulk->s2);
671*8e25f19bSMatthew Dillon 		pkg->flags |= PKGF_NOTFOUND;
672*8e25f19bSMatthew Dillon 	} else if (line != 14 + 1) {
673*8e25f19bSMatthew Dillon 		printf("DPort corrupt: %s/%s\n", bulk->s1, bulk->s2);
674*8e25f19bSMatthew Dillon 		pkg->flags |= PKGF_CORRUPT;
675*8e25f19bSMatthew Dillon 	}
676*8e25f19bSMatthew Dillon 	pclose(fp);
677*8e25f19bSMatthew Dillon 	ddassert(bulk->s1);
678*8e25f19bSMatthew Dillon 
679*8e25f19bSMatthew Dillon 	/*
680*8e25f19bSMatthew Dillon 	 * Generate flavors
681*8e25f19bSMatthew Dillon 	 */
682*8e25f19bSMatthew Dillon 	if (flavor == NULL) {
683*8e25f19bSMatthew Dillon 		/*
684*8e25f19bSMatthew Dillon 		 * If there are flavors add the current unflavored pkg
685*8e25f19bSMatthew Dillon 		 * as a dummy node so dependencies can attach to it,
686*8e25f19bSMatthew Dillon 		 * then iterate the first flavor and loop.
687*8e25f19bSMatthew Dillon 		 *
688*8e25f19bSMatthew Dillon 		 * We must NULL out pkgfile because it will have the
689*8e25f19bSMatthew Dillon 		 * default flavor and conflict with the actual flavored
690*8e25f19bSMatthew Dillon 		 * pkg.
691*8e25f19bSMatthew Dillon 		 */
692*8e25f19bSMatthew Dillon 		if (pkg->flavors && pkg->flavors[0]) {
693*8e25f19bSMatthew Dillon 			dummy_node = pkg;
694*8e25f19bSMatthew Dillon 
695*8e25f19bSMatthew Dillon 			pkg->flags |= PKGF_DUMMY;
696*8e25f19bSMatthew Dillon 
697*8e25f19bSMatthew Dillon 			freestrp(&pkg->fetch_deps);
698*8e25f19bSMatthew Dillon 			freestrp(&pkg->ext_deps);
699*8e25f19bSMatthew Dillon 			freestrp(&pkg->patch_deps);
700*8e25f19bSMatthew Dillon 			freestrp(&pkg->build_deps);
701*8e25f19bSMatthew Dillon 			freestrp(&pkg->lib_deps);
702*8e25f19bSMatthew Dillon 			freestrp(&pkg->run_deps);
703*8e25f19bSMatthew Dillon 			pkg->fetch_deps = strdup("");
704*8e25f19bSMatthew Dillon 			pkg->ext_deps = strdup("");
705*8e25f19bSMatthew Dillon 			pkg->patch_deps = strdup("");
706*8e25f19bSMatthew Dillon 			pkg->build_deps = strdup("");
707*8e25f19bSMatthew Dillon 			pkg->lib_deps = strdup("");
708*8e25f19bSMatthew Dillon 			pkg->run_deps = strdup("");
709*8e25f19bSMatthew Dillon 
710*8e25f19bSMatthew Dillon 			freestrp(&pkg->pkgfile);
711*8e25f19bSMatthew Dillon 			*list_tail = pkg;
712*8e25f19bSMatthew Dillon 			while (*list_tail)
713*8e25f19bSMatthew Dillon 				list_tail = &(*list_tail)->bnext;
714*8e25f19bSMatthew Dillon 
715*8e25f19bSMatthew Dillon 			flavors_save = strdup(pkg->flavors);
716*8e25f19bSMatthew Dillon 			flavors = flavors_save;
717*8e25f19bSMatthew Dillon 			do {
718*8e25f19bSMatthew Dillon 				flavor = strsep(&flavors, " \t");
719*8e25f19bSMatthew Dillon 			} while (flavor && *flavor == 0);
720*8e25f19bSMatthew Dillon 			goto again;
721*8e25f19bSMatthew Dillon 		}
722*8e25f19bSMatthew Dillon 
723*8e25f19bSMatthew Dillon 		/*
724*8e25f19bSMatthew Dillon 		 * No flavors, add the current unflavored pkg as a real
725*8e25f19bSMatthew Dillon 		 * node.
726*8e25f19bSMatthew Dillon 		 */
727*8e25f19bSMatthew Dillon 		*list_tail = pkg;
728*8e25f19bSMatthew Dillon 		while (*list_tail)
729*8e25f19bSMatthew Dillon 			list_tail = &(*list_tail)->bnext;
730*8e25f19bSMatthew Dillon 	} else {
731*8e25f19bSMatthew Dillon 		/*
732*8e25f19bSMatthew Dillon 		 * Add flavored package and iterate.
733*8e25f19bSMatthew Dillon 		 */
734*8e25f19bSMatthew Dillon 		*list_tail = pkg;
735*8e25f19bSMatthew Dillon 		while (*list_tail)
736*8e25f19bSMatthew Dillon 			list_tail = &(*list_tail)->bnext;
737*8e25f19bSMatthew Dillon 
738*8e25f19bSMatthew Dillon 		/*
739*8e25f19bSMatthew Dillon 		 * Flavor iteration under dummy node, add dependency
740*8e25f19bSMatthew Dillon 		 */
741*8e25f19bSMatthew Dillon 		if (dummy_node) {
742*8e25f19bSMatthew Dillon 			pkglink_t *link;
743*8e25f19bSMatthew Dillon 
744*8e25f19bSMatthew Dillon 			ddprintf(0, "Add Dependency %s -> %s (flavor rollup)\n",
745*8e25f19bSMatthew Dillon 				dummy_node->portdir, pkg->portdir);
746*8e25f19bSMatthew Dillon 			link = calloc(1, sizeof(*link));
747*8e25f19bSMatthew Dillon 			link->pkg = pkg;
748*8e25f19bSMatthew Dillon 			link->next = &dummy_node->idepon_list;
749*8e25f19bSMatthew Dillon 			link->prev = dummy_node->idepon_list.prev;
750*8e25f19bSMatthew Dillon 			link->next->prev = link;
751*8e25f19bSMatthew Dillon 			link->prev->next = link;
752*8e25f19bSMatthew Dillon 
753*8e25f19bSMatthew Dillon 			link = calloc(1, sizeof(*link));
754*8e25f19bSMatthew Dillon 			link->pkg = dummy_node;
755*8e25f19bSMatthew Dillon 			link->next = &pkg->deponi_list;
756*8e25f19bSMatthew Dillon 			link->prev = pkg->deponi_list.prev;
757*8e25f19bSMatthew Dillon 			link->next->prev = link;
758*8e25f19bSMatthew Dillon 			link->prev->next = link;
759*8e25f19bSMatthew Dillon 			++pkg->depi_count;
760*8e25f19bSMatthew Dillon 		}
761*8e25f19bSMatthew Dillon 
762*8e25f19bSMatthew Dillon 		if (flavors) {
763*8e25f19bSMatthew Dillon 			do {
764*8e25f19bSMatthew Dillon 				flavor = strsep(&flavors, " \t");
765*8e25f19bSMatthew Dillon 			} while (flavor && *flavor == 0);
766*8e25f19bSMatthew Dillon 			if (flavor)
767*8e25f19bSMatthew Dillon 				goto again;
768*8e25f19bSMatthew Dillon 			free(flavors);
769*8e25f19bSMatthew Dillon 		}
770*8e25f19bSMatthew Dillon 	}
771*8e25f19bSMatthew Dillon }
772*8e25f19bSMatthew Dillon 
773*8e25f19bSMatthew Dillon /*
774*8e25f19bSMatthew Dillon  * Query the package (at least to make sure it hasn't been truncated)
775*8e25f19bSMatthew Dillon  * and mark it as PACKAGED if found.
776*8e25f19bSMatthew Dillon  *
777*8e25f19bSMatthew Dillon  * Threaded function
778*8e25f19bSMatthew Dillon  */
779*8e25f19bSMatthew Dillon static void
780*8e25f19bSMatthew Dillon childGetBinaryDistInfo(bulk_t *bulk)
781*8e25f19bSMatthew Dillon {
782*8e25f19bSMatthew Dillon 	char buf[1024];
783*8e25f19bSMatthew Dillon 	char *ptr;
784*8e25f19bSMatthew Dillon 	FILE *fp;
785*8e25f19bSMatthew Dillon 	size_t len;
786*8e25f19bSMatthew Dillon 	pkg_t *pkg;
787*8e25f19bSMatthew Dillon 
788*8e25f19bSMatthew Dillon 	snprintf(buf, sizeof(buf),
789*8e25f19bSMatthew Dillon 		 "exec %s query -F %s/%s %%n-%%v",
790*8e25f19bSMatthew Dillon 		 PKG_BINARY,
791*8e25f19bSMatthew Dillon 		 RepositoryPath, bulk->s1);
792*8e25f19bSMatthew Dillon 	fp = popen(buf, "r");
793*8e25f19bSMatthew Dillon 	while ((ptr = fgetln(fp, &len)) != NULL) {
794*8e25f19bSMatthew Dillon 		if (len == 0 || ptr[len-1] != '\n')
795*8e25f19bSMatthew Dillon 			continue;
796*8e25f19bSMatthew Dillon 		ptr[len-1] = 0;
797*8e25f19bSMatthew Dillon 		snprintf(buf, sizeof(buf), "%s.txz", ptr);
798*8e25f19bSMatthew Dillon 
799*8e25f19bSMatthew Dillon 		pkg = pkg_find(buf);
800*8e25f19bSMatthew Dillon 		if (pkg)
801*8e25f19bSMatthew Dillon 			pkg->flags |= PKGF_PACKAGED;
802*8e25f19bSMatthew Dillon 		else
803*8e25f19bSMatthew Dillon 			ddprintf(0, "Note: package scan, not in list, "
804*8e25f19bSMatthew Dillon 				    "skipping %s\n", buf);
805*8e25f19bSMatthew Dillon 	}
806*8e25f19bSMatthew Dillon 	pclose(fp);
807*8e25f19bSMatthew Dillon }
808*8e25f19bSMatthew Dillon 
809*8e25f19bSMatthew Dillon static int
810*8e25f19bSMatthew Dillon scan_and_queue_dir(const char *path, const char *level1, int level)
811*8e25f19bSMatthew Dillon {
812*8e25f19bSMatthew Dillon 	DIR *dir;
813*8e25f19bSMatthew Dillon 	char *s1;
814*8e25f19bSMatthew Dillon 	char *s2;
815*8e25f19bSMatthew Dillon 	struct dirent *den;
816*8e25f19bSMatthew Dillon 	struct stat st;
817*8e25f19bSMatthew Dillon 	int count = 0;
818*8e25f19bSMatthew Dillon 
819*8e25f19bSMatthew Dillon 	dir = opendir(path);
820*8e25f19bSMatthew Dillon 	dassert(dir, "Cannot open dports path \"%s\"", path);
821*8e25f19bSMatthew Dillon 
822*8e25f19bSMatthew Dillon 	while ((den = readdir(dir)) != NULL) {
823*8e25f19bSMatthew Dillon 		if (den->d_namlen == 1 && den->d_name[0] == '.')
824*8e25f19bSMatthew Dillon 			continue;
825*8e25f19bSMatthew Dillon 		if (den->d_namlen == 2 &&
826*8e25f19bSMatthew Dillon 		    den->d_name[0] == '.' && den->d_name[1] == '.')
827*8e25f19bSMatthew Dillon 			continue;
828*8e25f19bSMatthew Dillon 		asprintf(&s1, "%s/%s", path, den->d_name);
829*8e25f19bSMatthew Dillon 		if (lstat(s1, &st) < 0 || !S_ISDIR(st.st_mode)) {
830*8e25f19bSMatthew Dillon 			free(s1);
831*8e25f19bSMatthew Dillon 			continue;
832*8e25f19bSMatthew Dillon 		}
833*8e25f19bSMatthew Dillon 		if (level == 1) {
834*8e25f19bSMatthew Dillon 			count += scan_and_queue_dir(s1, den->d_name, 2);
835*8e25f19bSMatthew Dillon 			free(s1);
836*8e25f19bSMatthew Dillon 			continue;
837*8e25f19bSMatthew Dillon 		}
838*8e25f19bSMatthew Dillon 		asprintf(&s2, "%s/Makefile", s1);
839*8e25f19bSMatthew Dillon 		if (lstat(s2, &st) == 0) {
840*8e25f19bSMatthew Dillon 			queuebulk(level1, den->d_name, NULL, NULL);
841*8e25f19bSMatthew Dillon 			++count;
842*8e25f19bSMatthew Dillon 		}
843*8e25f19bSMatthew Dillon 		free(s1);
844*8e25f19bSMatthew Dillon 		free(s2);
845*8e25f19bSMatthew Dillon 	}
846*8e25f19bSMatthew Dillon 	closedir(dir);
847*8e25f19bSMatthew Dillon 
848*8e25f19bSMatthew Dillon 	return count;
849*8e25f19bSMatthew Dillon }
850*8e25f19bSMatthew Dillon 
851*8e25f19bSMatthew Dillon static int
852*8e25f19bSMatthew Dillon scan_binary_repo(const char *path)
853*8e25f19bSMatthew Dillon {
854*8e25f19bSMatthew Dillon 	DIR *dir;
855*8e25f19bSMatthew Dillon 	struct dirent *den;
856*8e25f19bSMatthew Dillon 	size_t len;
857*8e25f19bSMatthew Dillon 	int count;
858*8e25f19bSMatthew Dillon 
859*8e25f19bSMatthew Dillon 	count = 0;
860*8e25f19bSMatthew Dillon 	dir = opendir(path);
861*8e25f19bSMatthew Dillon 	dassert(dir, "Cannot open repository path \"%s\"", path);
862*8e25f19bSMatthew Dillon 
863*8e25f19bSMatthew Dillon 	while ((den = readdir(dir)) != NULL) {
864*8e25f19bSMatthew Dillon 		len = strlen(den->d_name);
865*8e25f19bSMatthew Dillon 		if (len > 4 && strcmp(den->d_name + len - 4, ".txz") == 0) {
866*8e25f19bSMatthew Dillon 			queuebulk(den->d_name, NULL, NULL, NULL);
867*8e25f19bSMatthew Dillon 			++count;
868*8e25f19bSMatthew Dillon 		}
869*8e25f19bSMatthew Dillon 	}
870*8e25f19bSMatthew Dillon 	closedir(dir);
871*8e25f19bSMatthew Dillon 
872*8e25f19bSMatthew Dillon 	return count;
873*8e25f19bSMatthew Dillon }
874*8e25f19bSMatthew Dillon 
875*8e25f19bSMatthew Dillon #if 0
876*8e25f19bSMatthew Dillon static void
877*8e25f19bSMatthew Dillon pkgfree(pkg_t *pkg)
878*8e25f19bSMatthew Dillon {
879*8e25f19bSMatthew Dillon 	freestrp(&pkg->portdir);
880*8e25f19bSMatthew Dillon 	freestrp(&pkg->version);
881*8e25f19bSMatthew Dillon 	freestrp(&pkg->pkgfile);
882*8e25f19bSMatthew Dillon 	freestrp(&pkg->ignore);
883*8e25f19bSMatthew Dillon 	freestrp(&pkg->fetch_deps);
884*8e25f19bSMatthew Dillon 	freestrp(&pkg->ext_deps);
885*8e25f19bSMatthew Dillon 	freestrp(&pkg->patch_deps);
886*8e25f19bSMatthew Dillon 	freestrp(&pkg->build_deps);
887*8e25f19bSMatthew Dillon 	freestrp(&pkg->lib_deps);
888*8e25f19bSMatthew Dillon 	freestrp(&pkg->run_deps);
889*8e25f19bSMatthew Dillon 	freestrp(&pkg->pos_options);
890*8e25f19bSMatthew Dillon 	freestrp(&pkg->neg_options);
891*8e25f19bSMatthew Dillon 	freestrp(&pkg->flavors);
892*8e25f19bSMatthew Dillon 	free(pkg);
893*8e25f19bSMatthew Dillon }
894*8e25f19bSMatthew Dillon #endif
895