xref: /dflybsd-src/usr.bin/dsynth/pkglist.c (revision 63fcce5bf99b6bb6f247a2857592ddc5f212304c)
18e25f19bSMatthew Dillon /*
28e25f19bSMatthew Dillon  * Copyright (c) 2019 The DragonFly Project.  All rights reserved.
38e25f19bSMatthew Dillon  *
48e25f19bSMatthew Dillon  * This code is derived from software contributed to The DragonFly Project
58e25f19bSMatthew Dillon  * by Matthew Dillon <dillon@backplane.com>
68e25f19bSMatthew Dillon  *
78e25f19bSMatthew Dillon  * This code uses concepts and configuration based on 'synth', by
88e25f19bSMatthew Dillon  * John R. Marino <draco@marino.st>, which was written in ada.
98e25f19bSMatthew Dillon  *
108e25f19bSMatthew Dillon  * Redistribution and use in source and binary forms, with or without
118e25f19bSMatthew Dillon  * modification, are permitted provided that the following conditions
128e25f19bSMatthew Dillon  * are met:
138e25f19bSMatthew Dillon  *
148e25f19bSMatthew Dillon  * 1. Redistributions of source code must retain the above copyright
158e25f19bSMatthew Dillon  *    notice, this list of conditions and the following disclaimer.
168e25f19bSMatthew Dillon  * 2. Redistributions in binary form must reproduce the above copyright
178e25f19bSMatthew Dillon  *    notice, this list of conditions and the following disclaimer in
188e25f19bSMatthew Dillon  *    the documentation and/or other materials provided with the
198e25f19bSMatthew Dillon  *    distribution.
208e25f19bSMatthew Dillon  * 3. Neither the name of The DragonFly Project nor the names of its
218e25f19bSMatthew Dillon  *    contributors may be used to endorse or promote products derived
228e25f19bSMatthew Dillon  *    from this software without specific, prior written permission.
238e25f19bSMatthew Dillon  *
248e25f19bSMatthew Dillon  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
258e25f19bSMatthew Dillon  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
268e25f19bSMatthew Dillon  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
278e25f19bSMatthew Dillon  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
288e25f19bSMatthew Dillon  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
298e25f19bSMatthew Dillon  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
308e25f19bSMatthew Dillon  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
318e25f19bSMatthew Dillon  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
328e25f19bSMatthew Dillon  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
338e25f19bSMatthew Dillon  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
348e25f19bSMatthew Dillon  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
358e25f19bSMatthew Dillon  * SUCH DAMAGE.
368e25f19bSMatthew Dillon  */
378e25f19bSMatthew Dillon 
388e25f19bSMatthew Dillon #include "dsynth.h"
398e25f19bSMatthew Dillon 
408e25f19bSMatthew Dillon #define PKG_HSIZE	32768
418e25f19bSMatthew Dillon #define PKG_HMASK	32767
428e25f19bSMatthew Dillon 
438e25f19bSMatthew Dillon static void childGetPackageInfo(bulk_t *bulk);
448e25f19bSMatthew Dillon static void childGetBinaryDistInfo(bulk_t *bulk);
458e25f19bSMatthew Dillon static pkg_t *resolveDeps(pkg_t *dep_list, pkg_t ***list_tailp, int gentopo);
46*63fcce5bSMatthew Dillon static void resolveDepString(pkg_t *pkg, char *depstr,
47*63fcce5bSMatthew Dillon 			int gentopo, int dep_type);
488e25f19bSMatthew Dillon static pkg_t *processPackageListBulk(int total);
498e25f19bSMatthew Dillon static int scan_and_queue_dir(const char *path, const char *level1, int level);
508e25f19bSMatthew Dillon static int scan_binary_repo(const char *path);
518e25f19bSMatthew Dillon #if 0
528e25f19bSMatthew Dillon static void pkgfree(pkg_t *pkg);
538e25f19bSMatthew Dillon #endif
548e25f19bSMatthew Dillon 
558e25f19bSMatthew Dillon pkg_t *PkgHash1[PKG_HSIZE];	/* by portdir */
568e25f19bSMatthew Dillon pkg_t *PkgHash2[PKG_HSIZE];	/* by pkgfile */
578e25f19bSMatthew Dillon 
588e25f19bSMatthew Dillon /*
598e25f19bSMatthew Dillon  * Allocate a new pkg structure plus basic initialization.
608e25f19bSMatthew Dillon  */
618e25f19bSMatthew Dillon static __inline pkg_t *
628e25f19bSMatthew Dillon allocpkg(void)
638e25f19bSMatthew Dillon {
648e25f19bSMatthew Dillon 	pkg_t *pkg;
658e25f19bSMatthew Dillon 
668e25f19bSMatthew Dillon 	pkg = calloc(1, sizeof(*pkg));
678e25f19bSMatthew Dillon 	pkg->idepon_list.next = &pkg->idepon_list;
688e25f19bSMatthew Dillon 	pkg->idepon_list.prev = &pkg->idepon_list;
698e25f19bSMatthew Dillon 	pkg->deponi_list.next = &pkg->deponi_list;
708e25f19bSMatthew Dillon 	pkg->deponi_list.prev = &pkg->deponi_list;
718e25f19bSMatthew Dillon 
728e25f19bSMatthew Dillon 	return pkg;
738e25f19bSMatthew Dillon }
748e25f19bSMatthew Dillon 
758e25f19bSMatthew Dillon /*
768e25f19bSMatthew Dillon  * Simple hash for lookups
778e25f19bSMatthew Dillon  */
788e25f19bSMatthew Dillon static __inline int
798e25f19bSMatthew Dillon pkghash(const char *str)
808e25f19bSMatthew Dillon {
818e25f19bSMatthew Dillon 	int hv = 0xABC32923;
828e25f19bSMatthew Dillon 	while (*str) {
838e25f19bSMatthew Dillon 		hv = (hv << 5) ^ *str;
848e25f19bSMatthew Dillon 		++str;
858e25f19bSMatthew Dillon 	}
868e25f19bSMatthew Dillon 	hv = hv ^ (hv / PKG_HSIZE) ^ (hv / PKG_HSIZE / PKG_HSIZE);
878e25f19bSMatthew Dillon 	return (hv & PKG_HMASK);
888e25f19bSMatthew Dillon }
898e25f19bSMatthew Dillon 
908e25f19bSMatthew Dillon static void
918e25f19bSMatthew Dillon pkg_enter(pkg_t *pkg)
928e25f19bSMatthew Dillon {
938e25f19bSMatthew Dillon 	pkg_t **pkgp;
948e25f19bSMatthew Dillon 	pkg_t *scan;
958e25f19bSMatthew Dillon 
968e25f19bSMatthew Dillon 	if (pkg->portdir) {
978e25f19bSMatthew Dillon 		pkgp = &PkgHash1[pkghash(pkg->portdir)];
988e25f19bSMatthew Dillon 		while ((scan = *pkgp) != NULL) {
998e25f19bSMatthew Dillon 			if (strcmp(pkg->portdir, scan->portdir) == 0)
1008e25f19bSMatthew Dillon 				break;
1018e25f19bSMatthew Dillon 			pkgp = &scan->hnext1;
1028e25f19bSMatthew Dillon 		}
1038e25f19bSMatthew Dillon 		if (scan && (scan->flags & PKGF_PLACEHOLD)) {
1048e25f19bSMatthew Dillon 			*pkgp = pkg;
1058e25f19bSMatthew Dillon 			pkg->hnext1 = scan->hnext1;
1068e25f19bSMatthew Dillon 			free(scan->portdir);
1078e25f19bSMatthew Dillon 			free(scan);
1088e25f19bSMatthew Dillon 			scan = NULL;
1098e25f19bSMatthew Dillon 		}
1108e25f19bSMatthew Dillon 		if (scan == NULL)
1118e25f19bSMatthew Dillon 			*pkgp = pkg;
1128e25f19bSMatthew Dillon 	}
1138e25f19bSMatthew Dillon 
1148e25f19bSMatthew Dillon 	if (pkg->pkgfile) {
1158e25f19bSMatthew Dillon 		pkgp = &PkgHash2[pkghash(pkg->pkgfile)];
1168e25f19bSMatthew Dillon 		while ((scan = *pkgp) != NULL) {
1178e25f19bSMatthew Dillon 			if (strcmp(pkg->pkgfile, scan->pkgfile) == 0)
1188e25f19bSMatthew Dillon 				break;
1198e25f19bSMatthew Dillon 			pkgp = &scan->hnext2;
1208e25f19bSMatthew Dillon 		}
1218e25f19bSMatthew Dillon 		if (scan == NULL)
1228e25f19bSMatthew Dillon 			*pkgp = pkg;
1238e25f19bSMatthew Dillon 	}
1248e25f19bSMatthew Dillon }
1258e25f19bSMatthew Dillon 
1268e25f19bSMatthew Dillon static pkg_t *
1278e25f19bSMatthew Dillon pkg_find(const char *match)
1288e25f19bSMatthew Dillon {
1298e25f19bSMatthew Dillon 	pkg_t **pkgp;
1308e25f19bSMatthew Dillon 	pkg_t *pkg;
1318e25f19bSMatthew Dillon 
1328e25f19bSMatthew Dillon 	pkgp = &PkgHash1[pkghash(match)];
1338e25f19bSMatthew Dillon 	for (pkg = *pkgp; pkg; pkg = pkg->hnext1) {
1348e25f19bSMatthew Dillon 		if (strcmp(pkg->portdir, match) == 0)
1358e25f19bSMatthew Dillon 			return pkg;
1368e25f19bSMatthew Dillon 	}
1378e25f19bSMatthew Dillon 	pkgp = &PkgHash2[pkghash(match)];
1388e25f19bSMatthew Dillon 	for (pkg = *pkgp; pkg; pkg = pkg->hnext2) {
1398e25f19bSMatthew Dillon 		if (strcmp(pkg->pkgfile, match) == 0)
1408e25f19bSMatthew Dillon 			return pkg;
1418e25f19bSMatthew Dillon 	}
1428e25f19bSMatthew Dillon 	return NULL;
1438e25f19bSMatthew Dillon }
1448e25f19bSMatthew Dillon 
1458e25f19bSMatthew Dillon /*
1468e25f19bSMatthew Dillon  * Parse a specific list of ports via origin name (portdir/subdir)
1478e25f19bSMatthew Dillon  */
1488e25f19bSMatthew Dillon pkg_t *
1498e25f19bSMatthew Dillon ParsePackageList(int n, char **ary)
1508e25f19bSMatthew Dillon {
1518e25f19bSMatthew Dillon 	pkg_t *list;
1528e25f19bSMatthew Dillon 	int i;
1538e25f19bSMatthew Dillon 	int total;
1548e25f19bSMatthew Dillon 
1558e25f19bSMatthew Dillon 	total = 0;
1568e25f19bSMatthew Dillon 	initbulk(childGetPackageInfo, MaxBulk);
1578e25f19bSMatthew Dillon 
1588e25f19bSMatthew Dillon 	queuebulk("ports-mgmt", "pkg", NULL, NULL);
1598e25f19bSMatthew Dillon 	for (i = 0; i < n; ++i) {
1608e25f19bSMatthew Dillon 		char *l1;
1618e25f19bSMatthew Dillon 		char *l2;
1628e25f19bSMatthew Dillon 
1638e25f19bSMatthew Dillon 		l1 = strdup(ary[i]);
1648e25f19bSMatthew Dillon 		l2 = strchr(l1, '/');
1658e25f19bSMatthew Dillon 		if (l2) {
1668e25f19bSMatthew Dillon 			*l2++ = 0;
1678e25f19bSMatthew Dillon 			queuebulk(l1, l2, NULL, NULL);
1688e25f19bSMatthew Dillon 			++total;
1698e25f19bSMatthew Dillon 		} else {
1708e25f19bSMatthew Dillon 			printf("Bad portdir specification: %s\n", l1);
1718e25f19bSMatthew Dillon 		}
1728e25f19bSMatthew Dillon 		free(l1);
1738e25f19bSMatthew Dillon 	}
1748e25f19bSMatthew Dillon 	printf("Processing %d ports\n", total);
1758e25f19bSMatthew Dillon 
1768e25f19bSMatthew Dillon 	list = processPackageListBulk(total);
1778e25f19bSMatthew Dillon 
1788e25f19bSMatthew Dillon 	return list;
1798e25f19bSMatthew Dillon }
1808e25f19bSMatthew Dillon 
1818e25f19bSMatthew Dillon /*
1828e25f19bSMatthew Dillon  * Parse packages from the list installed on the system.
1838e25f19bSMatthew Dillon  */
1848e25f19bSMatthew Dillon pkg_t *
1858e25f19bSMatthew Dillon GetLocalPackageList(void)
1868e25f19bSMatthew Dillon {
1878e25f19bSMatthew Dillon 	pkg_t *list;
1888e25f19bSMatthew Dillon 	FILE *fp;
1898e25f19bSMatthew Dillon 	char *base;
1908e25f19bSMatthew Dillon 	char *l1;
1918e25f19bSMatthew Dillon 	char *l2;
1928e25f19bSMatthew Dillon 	int total;
1938e25f19bSMatthew Dillon 	size_t len;
1948e25f19bSMatthew Dillon 
1958e25f19bSMatthew Dillon 	initbulk(childGetPackageInfo, MaxBulk);
1968e25f19bSMatthew Dillon 	total = 0;
1978e25f19bSMatthew Dillon 
1988e25f19bSMatthew Dillon 	fp = popen("pkg info -a -o", "r");
1998e25f19bSMatthew Dillon 
2008e25f19bSMatthew Dillon 	queuebulk("ports-mgmt", "pkg", NULL, NULL);
2018e25f19bSMatthew Dillon 	while ((base = fgetln(fp, &len)) != NULL) {
2028e25f19bSMatthew Dillon 		if (len == 0 || base[len-1] != '\n')
2038e25f19bSMatthew Dillon 			continue;
2048e25f19bSMatthew Dillon 		base[--len] = 0;
2058e25f19bSMatthew Dillon 		if (strtok(base, " \t") == NULL) {
2068e25f19bSMatthew Dillon 			printf("Badly formatted pkg info line: %s\n", base);
2078e25f19bSMatthew Dillon 			continue;
2088e25f19bSMatthew Dillon 		}
2098e25f19bSMatthew Dillon 		l1 = strtok(NULL, " \t");
2108e25f19bSMatthew Dillon 		if (l1 == NULL) {
2118e25f19bSMatthew Dillon 			printf("Badly formatted pkg info line: %s\n", base);
2128e25f19bSMatthew Dillon 			continue;
2138e25f19bSMatthew Dillon 		}
2148e25f19bSMatthew Dillon 
2158e25f19bSMatthew Dillon 		l2 = strchr(l1, '/');
2168e25f19bSMatthew Dillon 		if (l2) {
2178e25f19bSMatthew Dillon 			*l2++ = 0;
2188e25f19bSMatthew Dillon 			queuebulk(l1, l2, NULL, NULL);
2198e25f19bSMatthew Dillon 			++total;
2208e25f19bSMatthew Dillon 		} else {
2218e25f19bSMatthew Dillon 			printf("Badly formatted specification: %s\n", l1);
2228e25f19bSMatthew Dillon 		}
2238e25f19bSMatthew Dillon 	}
2248e25f19bSMatthew Dillon 	pclose(fp);
2258e25f19bSMatthew Dillon 
2268e25f19bSMatthew Dillon 	printf("Processing %d ports\n", total);
2278e25f19bSMatthew Dillon 
2288e25f19bSMatthew Dillon 	list = processPackageListBulk(total);
2298e25f19bSMatthew Dillon 
2308e25f19bSMatthew Dillon 	return list;
2318e25f19bSMatthew Dillon }
2328e25f19bSMatthew Dillon 
2338e25f19bSMatthew Dillon pkg_t *
2348e25f19bSMatthew Dillon GetFullPackageList(void)
2358e25f19bSMatthew Dillon {
2368e25f19bSMatthew Dillon 	int total;
2378e25f19bSMatthew Dillon 
2388e25f19bSMatthew Dillon 	initbulk(childGetPackageInfo, MaxBulk);
2398e25f19bSMatthew Dillon 
2408e25f19bSMatthew Dillon 	total = scan_and_queue_dir(DPortsPath, NULL, 1);
2418e25f19bSMatthew Dillon 	printf("Scanning %d ports\n", total);
2428e25f19bSMatthew Dillon 
2438e25f19bSMatthew Dillon 	return processPackageListBulk(total);
2448e25f19bSMatthew Dillon }
2458e25f19bSMatthew Dillon 
2468e25f19bSMatthew Dillon /*
2478e25f19bSMatthew Dillon  * Caller has queued the process list for bulk operation.  We retrieve
2488e25f19bSMatthew Dillon  * the results and clean up the bulk operation (we may have to do a second
2498e25f19bSMatthew Dillon  * bulk operation so we have to be the ones to clean it up).
2508e25f19bSMatthew Dillon  */
2518e25f19bSMatthew Dillon static pkg_t *
2528e25f19bSMatthew Dillon processPackageListBulk(int total)
2538e25f19bSMatthew Dillon {
2548e25f19bSMatthew Dillon 	bulk_t *bulk;
2558e25f19bSMatthew Dillon 	pkg_t *scan;
2568e25f19bSMatthew Dillon 	pkg_t *list;
2578e25f19bSMatthew Dillon 	pkg_t *dep_list;
2588e25f19bSMatthew Dillon 	pkg_t **list_tail;
2598e25f19bSMatthew Dillon 	int count;
2608e25f19bSMatthew Dillon 
2618e25f19bSMatthew Dillon 	list = NULL;
2628e25f19bSMatthew Dillon 	list_tail = &list;
2638e25f19bSMatthew Dillon 	count = 0;
2648e25f19bSMatthew Dillon 
2658e25f19bSMatthew Dillon 	while ((bulk = getbulk()) != NULL) {
2668e25f19bSMatthew Dillon 		++count;
2678e25f19bSMatthew Dillon 		if ((count & 255) == 0) {
2688e25f19bSMatthew Dillon 			printf("%6.2f%%\r",
2698e25f19bSMatthew Dillon 				(double)count * 100.0 / (double)total + 0.001);
2708e25f19bSMatthew Dillon 			fflush(stdout);
2718e25f19bSMatthew Dillon 		}
2728e25f19bSMatthew Dillon 		if (bulk->list) {
2738e25f19bSMatthew Dillon 			*list_tail = bulk->list;
2748e25f19bSMatthew Dillon 			bulk->list = NULL;
2758e25f19bSMatthew Dillon 			while (*list_tail) {
2768e25f19bSMatthew Dillon 				pkg_enter(*list_tail);
2778e25f19bSMatthew Dillon 				list_tail = &(*list_tail)->bnext;
2788e25f19bSMatthew Dillon 			}
2798e25f19bSMatthew Dillon 		}
2808e25f19bSMatthew Dillon 		freebulk(bulk);
2818e25f19bSMatthew Dillon 	}
2821645cafeSMatthew Dillon 	printf("100.00%%\n");
2838e25f19bSMatthew Dillon 	printf("\nTotal %d\n", count);
2848e25f19bSMatthew Dillon 	fflush(stdout);
2858e25f19bSMatthew Dillon 
2868e25f19bSMatthew Dillon 	/*
2878e25f19bSMatthew Dillon 	 * Resolve all dependencies for the related packages, potentially
2888e25f19bSMatthew Dillon 	 * adding anything that could not be found to the list.  This will
2898e25f19bSMatthew Dillon 	 * continue to issue bulk operations and process the result until
2908e25f19bSMatthew Dillon 	 * no dependencies are left.
2918e25f19bSMatthew Dillon 	 */
2928e25f19bSMatthew Dillon 	printf("Resolving dependencies...");
2938e25f19bSMatthew Dillon 	fflush(stdout);
2948e25f19bSMatthew Dillon 	dep_list = list;
2958e25f19bSMatthew Dillon 	while (dep_list) {
2968e25f19bSMatthew Dillon 		dep_list = resolveDeps(dep_list, &list_tail, 0);
2978e25f19bSMatthew Dillon 	}
2988e25f19bSMatthew Dillon 	printf("done\n");
2998e25f19bSMatthew Dillon 
3008e25f19bSMatthew Dillon 	donebulk();
3018e25f19bSMatthew Dillon 
3028e25f19bSMatthew Dillon 	/*
3038e25f19bSMatthew Dillon 	 * Generate the topology
3048e25f19bSMatthew Dillon 	 */
3058e25f19bSMatthew Dillon 	resolveDeps(list, NULL, 1);
3068e25f19bSMatthew Dillon 
3078e25f19bSMatthew Dillon 	/*
3088e25f19bSMatthew Dillon 	 * Do a final count, ignore place holders.
3098e25f19bSMatthew Dillon 	 */
3108e25f19bSMatthew Dillon 	count = 0;
3118e25f19bSMatthew Dillon 	for (scan = list; scan; scan = scan->bnext) {
3128e25f19bSMatthew Dillon 		if ((scan->flags & PKGF_ERROR) == 0) {
3138e25f19bSMatthew Dillon 			++count;
3148e25f19bSMatthew Dillon 		}
3158e25f19bSMatthew Dillon 	}
3168e25f19bSMatthew Dillon 	printf("Total Returned %d\n", count);
3178e25f19bSMatthew Dillon 
3188e25f19bSMatthew Dillon 	/*
3198e25f19bSMatthew Dillon 	 * Scan our binary distributions and related dependencies looking
3208e25f19bSMatthew Dillon 	 * for any packages that have already been built.
3218e25f19bSMatthew Dillon 	 */
3228e25f19bSMatthew Dillon 	initbulk(childGetBinaryDistInfo, MaxBulk);
3238e25f19bSMatthew Dillon 	total = scan_binary_repo(RepositoryPath);
3248e25f19bSMatthew Dillon 	count = 0;
3258e25f19bSMatthew Dillon 	printf("Scanning %d packages\n", total);
3268e25f19bSMatthew Dillon 
3278e25f19bSMatthew Dillon 	while ((bulk = getbulk()) != NULL) {
3288e25f19bSMatthew Dillon 		++count;
3298e25f19bSMatthew Dillon 		if ((count & 255) == 0) {
3308e25f19bSMatthew Dillon 			printf("%6.2f%%\r",
3318e25f19bSMatthew Dillon 				(double)count * 100.0 / (double)total + 0.001);
3328e25f19bSMatthew Dillon 			fflush(stdout);
3338e25f19bSMatthew Dillon 		}
3348e25f19bSMatthew Dillon 		freebulk(bulk);
3358e25f19bSMatthew Dillon 	}
3361645cafeSMatthew Dillon 	printf("100.00%%\n");
3378e25f19bSMatthew Dillon 	printf("\nTotal %d\n", count);
3388e25f19bSMatthew Dillon 	fflush(stdout);
3398e25f19bSMatthew Dillon 	donebulk();
3408e25f19bSMatthew Dillon 
3418e25f19bSMatthew Dillon 	printf("all done\n");
3428e25f19bSMatthew Dillon 
3438e25f19bSMatthew Dillon 	return list;
3448e25f19bSMatthew Dillon }
3458e25f19bSMatthew Dillon 
3468e25f19bSMatthew Dillon pkg_t *
3478e25f19bSMatthew Dillon GetPkgPkg(pkg_t *list)
3488e25f19bSMatthew Dillon {
3498e25f19bSMatthew Dillon 	bulk_t *bulk;
3508e25f19bSMatthew Dillon 	pkg_t *scan;
3518e25f19bSMatthew Dillon 
3528e25f19bSMatthew Dillon 	for (scan = list; scan; scan = scan->bnext) {
3538e25f19bSMatthew Dillon 		if (strcmp(scan->portdir, "ports-mgmt/pkg") == 0)
3548e25f19bSMatthew Dillon 			return scan;
3558e25f19bSMatthew Dillon 	}
3568e25f19bSMatthew Dillon 
3578e25f19bSMatthew Dillon 	initbulk(childGetPackageInfo, MaxBulk);
3588e25f19bSMatthew Dillon 	queuebulk("ports-mgmt", "pkg", NULL, NULL);
3598e25f19bSMatthew Dillon 	bulk = getbulk();
3608e25f19bSMatthew Dillon 	dassert(bulk, "Cannot find ports-mgmt/pkg");
3618e25f19bSMatthew Dillon 	scan = bulk->list;
3628e25f19bSMatthew Dillon 	bulk->list = NULL;
3638e25f19bSMatthew Dillon 	freebulk(bulk);
3648e25f19bSMatthew Dillon 	donebulk();
3658e25f19bSMatthew Dillon 
3668e25f19bSMatthew Dillon 	return scan;
3678e25f19bSMatthew Dillon }
3688e25f19bSMatthew Dillon 
3698e25f19bSMatthew Dillon /*
3708e25f19bSMatthew Dillon  * Run through the list resolving dependencies and constructing the topology
3718e25f19bSMatthew Dillon  * linkages.   This may append packages to the list.
3728e25f19bSMatthew Dillon  */
3738e25f19bSMatthew Dillon static pkg_t *
3748e25f19bSMatthew Dillon resolveDeps(pkg_t *list, pkg_t ***list_tailp, int gentopo)
3758e25f19bSMatthew Dillon {
3768e25f19bSMatthew Dillon 	pkg_t *scan;
3778e25f19bSMatthew Dillon 	pkg_t *ret_list = NULL;
3788e25f19bSMatthew Dillon 	bulk_t *bulk;
3798e25f19bSMatthew Dillon 
3808e25f19bSMatthew Dillon 	for (scan = list; scan; scan = scan->bnext) {
381*63fcce5bSMatthew Dillon 		resolveDepString(scan, scan->fetch_deps,
382*63fcce5bSMatthew Dillon 				 gentopo, DEP_TYPE_FETCH);
383*63fcce5bSMatthew Dillon 		resolveDepString(scan, scan->ext_deps,
384*63fcce5bSMatthew Dillon 				 gentopo, DEP_TYPE_EXT);
385*63fcce5bSMatthew Dillon 		resolveDepString(scan, scan->patch_deps,
386*63fcce5bSMatthew Dillon 				 gentopo, DEP_TYPE_PATCH);
387*63fcce5bSMatthew Dillon 		resolveDepString(scan, scan->build_deps,
388*63fcce5bSMatthew Dillon 				 gentopo, DEP_TYPE_BUILD);
389*63fcce5bSMatthew Dillon 		resolveDepString(scan, scan->lib_deps,
390*63fcce5bSMatthew Dillon 				 gentopo, DEP_TYPE_LIB);
391*63fcce5bSMatthew Dillon 		resolveDepString(scan, scan->run_deps,
392*63fcce5bSMatthew Dillon 				 gentopo, DEP_TYPE_RUN);
3938e25f19bSMatthew Dillon 	}
3948e25f19bSMatthew Dillon 
3958e25f19bSMatthew Dillon 	/*
3968e25f19bSMatthew Dillon 	 * No bulk ops are queued when doing the final topology
3978e25f19bSMatthew Dillon 	 * generation.
3988e25f19bSMatthew Dillon 	 */
3998e25f19bSMatthew Dillon 	if (gentopo)
4008e25f19bSMatthew Dillon 		return NULL;
4018e25f19bSMatthew Dillon 	while ((bulk = getbulk()) != NULL) {
4028e25f19bSMatthew Dillon 		if (bulk->list) {
4038e25f19bSMatthew Dillon 			if (ret_list == NULL)
4048e25f19bSMatthew Dillon 				ret_list = bulk->list;
4058e25f19bSMatthew Dillon 			**list_tailp = bulk->list;
4068e25f19bSMatthew Dillon 			bulk->list = NULL;
4078e25f19bSMatthew Dillon 			while (**list_tailp) {
4088e25f19bSMatthew Dillon 				pkg_enter(**list_tailp);
4098e25f19bSMatthew Dillon 				*list_tailp = &(**list_tailp)->bnext;
4108e25f19bSMatthew Dillon 			}
4118e25f19bSMatthew Dillon 		}
4128e25f19bSMatthew Dillon 		freebulk(bulk);
4138e25f19bSMatthew Dillon 	}
4148e25f19bSMatthew Dillon 	return (ret_list);
4158e25f19bSMatthew Dillon }
4168e25f19bSMatthew Dillon 
4178e25f19bSMatthew Dillon static void
418*63fcce5bSMatthew Dillon resolveDepString(pkg_t *pkg, char *depstr, int gentopo, int dep_type)
4198e25f19bSMatthew Dillon {
4208e25f19bSMatthew Dillon 	char *copy_base;
4218e25f19bSMatthew Dillon 	char *copy;
4228e25f19bSMatthew Dillon 	char *dep;
4238e25f19bSMatthew Dillon 	char *sep;
4248e25f19bSMatthew Dillon 	char *tag;
4258e25f19bSMatthew Dillon 	char *flavor;
4268e25f19bSMatthew Dillon 	pkg_t *dpkg;
4278e25f19bSMatthew Dillon 
4288e25f19bSMatthew Dillon 	if (depstr == NULL || depstr[0] == 0)
4298e25f19bSMatthew Dillon 		return;
4308e25f19bSMatthew Dillon 
4318e25f19bSMatthew Dillon 	copy_base = strdup(depstr);
4328e25f19bSMatthew Dillon 	copy = copy_base;
4338e25f19bSMatthew Dillon 
4348e25f19bSMatthew Dillon 	for (;;) {
4358e25f19bSMatthew Dillon 		do {
4368e25f19bSMatthew Dillon 			dep = strsep(&copy, " \t");
4378e25f19bSMatthew Dillon 		} while (dep && *dep == 0);
4388e25f19bSMatthew Dillon 		if (dep == NULL)
4398e25f19bSMatthew Dillon 			break;
4406fd67931SMatthew Dillon 
4416fd67931SMatthew Dillon 		/*
4426fd67931SMatthew Dillon 		 * Ignore dependencies prefixed with ${NONEXISTENT}
4436fd67931SMatthew Dillon 		 */
4446fd67931SMatthew Dillon 		if (strncmp(dep, "/nonexistent:", 13) == 0)
4456fd67931SMatthew Dillon 			continue;
4466fd67931SMatthew Dillon 
4478e25f19bSMatthew Dillon 		dep = strchr(dep, ':');
4488e25f19bSMatthew Dillon 		if (dep == NULL || *dep != ':') {
4498e25f19bSMatthew Dillon 			printf("Error parsing dependency for %s: %s\n",
4508e25f19bSMatthew Dillon 			       pkg->portdir, copy_base);
4518e25f19bSMatthew Dillon 			continue;
4528e25f19bSMatthew Dillon 		}
4538e25f19bSMatthew Dillon 		++dep;
4548e25f19bSMatthew Dillon 
4558e25f19bSMatthew Dillon 		/*
4568e25f19bSMatthew Dillon 		 * Strip-off any DPortsPath prefix.  EXTRACT_DEPENDS
4578e25f19bSMatthew Dillon 		 * often (always?) generates this prefix.
4588e25f19bSMatthew Dillon 		 */
4598e25f19bSMatthew Dillon 		if (strncmp(dep, DPortsPath, strlen(DPortsPath)) == 0) {
4608e25f19bSMatthew Dillon 			dep += strlen(DPortsPath);
4618e25f19bSMatthew Dillon 			if (*dep == '/')
4628e25f19bSMatthew Dillon 				++dep;
4638e25f19bSMatthew Dillon 		}
4648e25f19bSMatthew Dillon 
4658e25f19bSMatthew Dillon 		/*
4668e25f19bSMatthew Dillon 		 * Strip-off any tag (such as :patch).  We don't try to
4678e25f19bSMatthew Dillon 		 * organize dependencies at this fine a grain (for now).
4688e25f19bSMatthew Dillon 		 */
4698e25f19bSMatthew Dillon 		tag = strchr(dep, ':');
4708e25f19bSMatthew Dillon 		if (tag)
4718e25f19bSMatthew Dillon 			*tag++ = 0;
4728e25f19bSMatthew Dillon 
4738e25f19bSMatthew Dillon 		/*
4748e25f19bSMatthew Dillon 		 * Locate the dependency
4758e25f19bSMatthew Dillon 		 */
4768e25f19bSMatthew Dillon 		if ((dpkg = pkg_find(dep)) != NULL) {
4778e25f19bSMatthew Dillon 			if (gentopo) {
4788e25f19bSMatthew Dillon 				pkglink_t *link;
4798e25f19bSMatthew Dillon 
4808e25f19bSMatthew Dillon 				/*
4818e25f19bSMatthew Dillon 				 * NOTE: idep_count is calculated recursively
4828e25f19bSMatthew Dillon 				 *	 at build-time
4838e25f19bSMatthew Dillon 				 */
4848e25f19bSMatthew Dillon 				ddprintf(0, "Add Dependency %s -> %s\n",
4858e25f19bSMatthew Dillon 					pkg->portdir, dpkg->portdir);
4868e25f19bSMatthew Dillon 				link = calloc(1, sizeof(*link));
4878e25f19bSMatthew Dillon 				link->pkg = dpkg;
4888e25f19bSMatthew Dillon 				link->next = &pkg->idepon_list;
4898e25f19bSMatthew Dillon 				link->prev = pkg->idepon_list.prev;
4908e25f19bSMatthew Dillon 				link->next->prev = link;
4918e25f19bSMatthew Dillon 				link->prev->next = link;
492*63fcce5bSMatthew Dillon 				link->dep_type = dep_type;
4938e25f19bSMatthew Dillon 
4948e25f19bSMatthew Dillon 				link = calloc(1, sizeof(*link));
4958e25f19bSMatthew Dillon 				link->pkg = pkg;
4968e25f19bSMatthew Dillon 				link->next = &dpkg->deponi_list;
4978e25f19bSMatthew Dillon 				link->prev = dpkg->deponi_list.prev;
4988e25f19bSMatthew Dillon 				link->next->prev = link;
4998e25f19bSMatthew Dillon 				link->prev->next = link;
500*63fcce5bSMatthew Dillon 				link->dep_type = dep_type;
5018e25f19bSMatthew Dillon 				++dpkg->depi_count;
5028e25f19bSMatthew Dillon 			}
5038e25f19bSMatthew Dillon 			continue;
5048e25f19bSMatthew Dillon 		}
5058e25f19bSMatthew Dillon 
5068e25f19bSMatthew Dillon 		/*
5078e25f19bSMatthew Dillon 		 * This shouldn't happen because we already took a first
5088e25f19bSMatthew Dillon 		 * pass and should have generated the pkgs.
5098e25f19bSMatthew Dillon 		 */
5108e25f19bSMatthew Dillon 		if (gentopo) {
5118e25f19bSMatthew Dillon 			printf("Topology Generate failed for %s: %s\n",
5128e25f19bSMatthew Dillon 				pkg->portdir, copy_base);
5138e25f19bSMatthew Dillon 			continue;
5148e25f19bSMatthew Dillon 		}
5158e25f19bSMatthew Dillon 
5168e25f19bSMatthew Dillon 		/*
5178e25f19bSMatthew Dillon 		 * Separate out the two dports directory components and
5188e25f19bSMatthew Dillon 		 * extract the optional '@flavor' specification.
5198e25f19bSMatthew Dillon 		 */
5208e25f19bSMatthew Dillon 		sep = strchr(dep, '/');
5218e25f19bSMatthew Dillon 		if (sep == NULL) {
5228e25f19bSMatthew Dillon 			printf("Error parsing dependency for %s: %s\n",
5238e25f19bSMatthew Dillon 			       pkg->portdir, copy_base);
5248e25f19bSMatthew Dillon 			continue;
5258e25f19bSMatthew Dillon 		}
5268e25f19bSMatthew Dillon 		*sep++ = 0;
5278e25f19bSMatthew Dillon 
5288e25f19bSMatthew Dillon 		if (tag)
5298e25f19bSMatthew Dillon 			flavor = strrchr(tag, '@');
5308e25f19bSMatthew Dillon 		else
5318e25f19bSMatthew Dillon 			flavor = strrchr(sep, '@');
5328e25f19bSMatthew Dillon 
5338e25f19bSMatthew Dillon 		if (flavor)
5348e25f19bSMatthew Dillon 			*flavor++ = 0;
5358e25f19bSMatthew Dillon 
5368e25f19bSMatthew Dillon 		if (flavor)
5378e25f19bSMatthew Dillon 			ddprintf(0, "QUEUE DEPENDENCY FROM PKG %s: %s/%s@%s\n",
5388e25f19bSMatthew Dillon 			       pkg->portdir, dep, sep, flavor);
5398e25f19bSMatthew Dillon 		else
5408e25f19bSMatthew Dillon 			ddprintf(0, "QUEUE DEPENDENCY FROM PKG %s: %s/%s\n",
5418e25f19bSMatthew Dillon 			       pkg->portdir, dep, sep);
5428e25f19bSMatthew Dillon 
5438e25f19bSMatthew Dillon 		/*
5448e25f19bSMatthew Dillon 		 * Use a place-holder to prevent duplicate dependencies from
5458e25f19bSMatthew Dillon 		 * being processed.  The placeholder will be replaced by
5468e25f19bSMatthew Dillon 		 * the actual dependency.
5478e25f19bSMatthew Dillon 		 */
5488e25f19bSMatthew Dillon 		dpkg = allocpkg();
5498e25f19bSMatthew Dillon 		if (flavor)
5508e25f19bSMatthew Dillon 			asprintf(&dpkg->portdir, "%s/%s@%s", dep, sep, flavor);
5518e25f19bSMatthew Dillon 		else
5528e25f19bSMatthew Dillon 			asprintf(&dpkg->portdir, "%s/%s", dep, sep);
5538e25f19bSMatthew Dillon 		dpkg->flags = PKGF_PLACEHOLD;
5548e25f19bSMatthew Dillon 		pkg_enter(dpkg);
5558e25f19bSMatthew Dillon 
5568e25f19bSMatthew Dillon 		queuebulk(dep, sep, flavor, NULL);
5578e25f19bSMatthew Dillon 	}
5588e25f19bSMatthew Dillon 	free(copy_base);
5598e25f19bSMatthew Dillon }
5608e25f19bSMatthew Dillon 
5618e25f19bSMatthew Dillon void
5628e25f19bSMatthew Dillon FreePackageList(pkg_t *pkgs __unused)
5638e25f19bSMatthew Dillon {
5648e25f19bSMatthew Dillon 	dfatal("not implemented");
5658e25f19bSMatthew Dillon }
5668e25f19bSMatthew Dillon 
5678e25f19bSMatthew Dillon /*
5688e25f19bSMatthew Dillon  * Scan some or all dports to allocate the related pkg structure.  Dependencies
5698e25f19bSMatthew Dillon  * are stored but not processed.
5708e25f19bSMatthew Dillon  *
5718e25f19bSMatthew Dillon  * Threaded function
5728e25f19bSMatthew Dillon  */
5738e25f19bSMatthew Dillon static void
5748e25f19bSMatthew Dillon childGetPackageInfo(bulk_t *bulk)
5758e25f19bSMatthew Dillon {
5768e25f19bSMatthew Dillon 	pkg_t *pkg;
5778e25f19bSMatthew Dillon 	pkg_t *dummy_node;
5788e25f19bSMatthew Dillon 	pkg_t **list_tail;
5798e25f19bSMatthew Dillon 	char *flavors_save;
5808e25f19bSMatthew Dillon 	char *flavors;
5818e25f19bSMatthew Dillon 	char *flavor;
5828e25f19bSMatthew Dillon 	char *ptr;
5838e25f19bSMatthew Dillon 	FILE *fp;
5848e25f19bSMatthew Dillon 	int line;
5858e25f19bSMatthew Dillon 	size_t len;
5866fd67931SMatthew Dillon 	char *portpath;
5876fd67931SMatthew Dillon 	char *flavarg;
5886fd67931SMatthew Dillon 	const char *cav[MAXCAC];
5896fd67931SMatthew Dillon 	pid_t pid;
5906fd67931SMatthew Dillon 	int cac;
5918e25f19bSMatthew Dillon 
5928e25f19bSMatthew Dillon 	/*
5938e25f19bSMatthew Dillon 	 * If the package has flavors we will loop on each one.  If a flavor
5948e25f19bSMatthew Dillon 	 * is not passed in s3 we will loop on all flavors, otherwise we will
5958e25f19bSMatthew Dillon 	 * only process the passed-in flavor.
5968e25f19bSMatthew Dillon 	 */
5978e25f19bSMatthew Dillon 	flavor = bulk->s3;	/* usually NULL */
5988e25f19bSMatthew Dillon 	flavors = NULL;
5998e25f19bSMatthew Dillon 	flavors_save = NULL;
6008e25f19bSMatthew Dillon 	dummy_node = NULL;
6018e25f19bSMatthew Dillon 
6028e25f19bSMatthew Dillon 	bulk->list = NULL;
6038e25f19bSMatthew Dillon 	list_tail = &bulk->list;
6048e25f19bSMatthew Dillon again:
6056fd67931SMatthew Dillon 	asprintf(&portpath, "%s/%s/%s", DPortsPath, bulk->s1, bulk->s2);
6066fd67931SMatthew Dillon 	if (flavor)
6076fd67931SMatthew Dillon 		asprintf(&flavarg, "FLAVOR=%s", flavor);
6086fd67931SMatthew Dillon 	else
6096fd67931SMatthew Dillon 		flavarg = NULL;
6106fd67931SMatthew Dillon 
6116fd67931SMatthew Dillon 	cac = 0;
6126fd67931SMatthew Dillon 	cav[cac++] = MAKE_BINARY;
6136fd67931SMatthew Dillon 	cav[cac++] = "-C";
6146fd67931SMatthew Dillon 	cav[cac++] = portpath;
6156fd67931SMatthew Dillon 	if (flavarg)
6166fd67931SMatthew Dillon 		cav[cac++] = flavarg;
6176fd67931SMatthew Dillon 	cav[cac++] = "-VPKGVERSION";
6186fd67931SMatthew Dillon 	cav[cac++] = "-VPKGFILE:T";
6196fd67931SMatthew Dillon 	cav[cac++] = "-VDISTFILES";
6206fd67931SMatthew Dillon 	cav[cac++] = "-VDIST_SUBDIR";
6216fd67931SMatthew Dillon 	cav[cac++] = "-VMAKE_JOBS_NUMBER";
6226fd67931SMatthew Dillon 	cav[cac++] = "-VIGNORE";
6236fd67931SMatthew Dillon 	cav[cac++] = "-VFETCH_DEPENDS";
6246fd67931SMatthew Dillon 	cav[cac++] = "-VEXTRACT_DEPENDS";
6256fd67931SMatthew Dillon 	cav[cac++] = "-VPATCH_DEPENDS";
6266fd67931SMatthew Dillon 	cav[cac++] = "-VBUILD_DEPENDS";
6276fd67931SMatthew Dillon 	cav[cac++] = "-VLIB_DEPENDS";
6286fd67931SMatthew Dillon 	cav[cac++] = "-VRUN_DEPENDS";
6296fd67931SMatthew Dillon 	cav[cac++] = "-VSELECTED_OPTIONS";
6306fd67931SMatthew Dillon 	cav[cac++] = "-VDESELECTED_OPTIONS";
6316fd67931SMatthew Dillon 	cav[cac++] = "-VUSE_LINUX";
6326fd67931SMatthew Dillon 	cav[cac++] = "-VFLAVORS";
6336fd67931SMatthew Dillon 
6346fd67931SMatthew Dillon 	fp = dexec_open(cav, cac, &pid, 1, 1);
6356fd67931SMatthew Dillon 	free(portpath);
6366fd67931SMatthew Dillon 	freestrp(&flavarg);
6378e25f19bSMatthew Dillon 
6388e25f19bSMatthew Dillon 	pkg = allocpkg();
6398e25f19bSMatthew Dillon 	if (flavor)
6408e25f19bSMatthew Dillon 		asprintf(&pkg->portdir, "%s/%s@%s", bulk->s1, bulk->s2, flavor);
6418e25f19bSMatthew Dillon 	else
6428e25f19bSMatthew Dillon 		asprintf(&pkg->portdir, "%s/%s", bulk->s1, bulk->s2);
6438e25f19bSMatthew Dillon 
6446fd67931SMatthew Dillon 	line = 1;
6458e25f19bSMatthew Dillon 	while ((ptr = fgetln(fp, &len)) != NULL) {
6468e25f19bSMatthew Dillon 		if (len == 0 || ptr[len-1] != '\n') {
6478e25f19bSMatthew Dillon 			dfatal("Bad package info for %s/%s response line %d",
6488e25f19bSMatthew Dillon 			       bulk->s1, bulk->s2, line);
6498e25f19bSMatthew Dillon 		}
6508e25f19bSMatthew Dillon 		ptr[--len] = 0;
6518e25f19bSMatthew Dillon 
6528e25f19bSMatthew Dillon 		switch(line) {
6538e25f19bSMatthew Dillon 		case 1:		/* PKGVERSION */
6548e25f19bSMatthew Dillon 			asprintf(&pkg->version, "%s", ptr);
6558e25f19bSMatthew Dillon 			break;
6568e25f19bSMatthew Dillon 		case 2:		/* PKGFILE */
6578e25f19bSMatthew Dillon 			asprintf(&pkg->pkgfile, "%s", ptr);
6588e25f19bSMatthew Dillon 			break;
6591645cafeSMatthew Dillon 		case 3:		/* DISTFILES */
6601645cafeSMatthew Dillon 			asprintf(&pkg->distfiles, "%s", ptr);
6611645cafeSMatthew Dillon 			break;
6621645cafeSMatthew Dillon 		case 4:		/* DIST_SUBDIR */
6634ea2ee4dSMatthew Dillon 			pkg->distsubdir = strdup_or_null(ptr);
6641645cafeSMatthew Dillon 			break;
6651645cafeSMatthew Dillon 		case 5:		/* MAKE_JOBS_NUMBER */
6668e25f19bSMatthew Dillon 			pkg->make_jobs_number = strtol(ptr, NULL, 0);
6678e25f19bSMatthew Dillon 			break;
6681645cafeSMatthew Dillon 		case 6:		/* IGNORE */
6694ea2ee4dSMatthew Dillon 			pkg->ignore = strdup_or_null(ptr);
6708e25f19bSMatthew Dillon 			break;
6711645cafeSMatthew Dillon 		case 7:		/* FETCH_DEPENDS */
6724ea2ee4dSMatthew Dillon 			pkg->fetch_deps = strdup_or_null(ptr);
6738e25f19bSMatthew Dillon 			break;
6741645cafeSMatthew Dillon 		case 8:		/* EXTRACT_DEPENDS */
6754ea2ee4dSMatthew Dillon 			pkg->ext_deps = strdup_or_null(ptr);
6768e25f19bSMatthew Dillon 			break;
6771645cafeSMatthew Dillon 		case 9:		/* PATCH_DEPENDS */
6784ea2ee4dSMatthew Dillon 			pkg->patch_deps = strdup_or_null(ptr);
6798e25f19bSMatthew Dillon 			break;
6801645cafeSMatthew Dillon 		case 10:	/* BUILD_DEPENDS */
6814ea2ee4dSMatthew Dillon 			pkg->build_deps = strdup_or_null(ptr);
6828e25f19bSMatthew Dillon 			break;
6831645cafeSMatthew Dillon 		case 11:	/* LIB_DEPENDS */
6844ea2ee4dSMatthew Dillon 			pkg->lib_deps = strdup_or_null(ptr);
6858e25f19bSMatthew Dillon 			break;
6861645cafeSMatthew Dillon 		case 12:	/* RUN_DEPENDS */
6874ea2ee4dSMatthew Dillon 			pkg->run_deps = strdup_or_null(ptr);
6888e25f19bSMatthew Dillon 			break;
6891645cafeSMatthew Dillon 		case 13:	/* SELECTED_OPTIONS */
6904ea2ee4dSMatthew Dillon 			pkg->pos_options = strdup_or_null(ptr);
6918e25f19bSMatthew Dillon 			break;
6921645cafeSMatthew Dillon 		case 14:	/* DESELECTED_OPTIONS */
6934ea2ee4dSMatthew Dillon 			pkg->neg_options = strdup_or_null(ptr);
6948e25f19bSMatthew Dillon 			break;
6951645cafeSMatthew Dillon 		case 15:	/* USE_LINUX */
6968e25f19bSMatthew Dillon 			if (ptr[0])
6978e25f19bSMatthew Dillon 				pkg->use_linux = 1;
6988e25f19bSMatthew Dillon 			break;
6991645cafeSMatthew Dillon 		case 16:	/* FLAVORS */
7008e25f19bSMatthew Dillon 			asprintf(&pkg->flavors, "%s", ptr);
7018e25f19bSMatthew Dillon 			break;
7028e25f19bSMatthew Dillon 		default:
7038e25f19bSMatthew Dillon 			printf("EXTRA LINE: %s\n", ptr);
7048e25f19bSMatthew Dillon 			break;
7058e25f19bSMatthew Dillon 		}
7068e25f19bSMatthew Dillon 		++line;
7078e25f19bSMatthew Dillon 	}
7088e25f19bSMatthew Dillon 	if (line == 1) {
7098e25f19bSMatthew Dillon 		printf("DPort not found: %s/%s\n", bulk->s1, bulk->s2);
7108e25f19bSMatthew Dillon 		pkg->flags |= PKGF_NOTFOUND;
7111645cafeSMatthew Dillon 	} else if (line != 16 + 1) {
7128e25f19bSMatthew Dillon 		printf("DPort corrupt: %s/%s\n", bulk->s1, bulk->s2);
7138e25f19bSMatthew Dillon 		pkg->flags |= PKGF_CORRUPT;
7148e25f19bSMatthew Dillon 	}
7156fd67931SMatthew Dillon 	if (dexec_close(fp, pid)) {
7166fd67931SMatthew Dillon 		printf("make -V* command for %s/%s failed\n",
7176fd67931SMatthew Dillon 			bulk->s1, bulk->s2);
7186fd67931SMatthew Dillon 		pkg->flags |= PKGF_CORRUPT;
7196fd67931SMatthew Dillon 	}
7208e25f19bSMatthew Dillon 	ddassert(bulk->s1);
7218e25f19bSMatthew Dillon 
7228e25f19bSMatthew Dillon 	/*
7238e25f19bSMatthew Dillon 	 * Generate flavors
7248e25f19bSMatthew Dillon 	 */
7258e25f19bSMatthew Dillon 	if (flavor == NULL) {
7268e25f19bSMatthew Dillon 		/*
7278e25f19bSMatthew Dillon 		 * If there are flavors add the current unflavored pkg
7288e25f19bSMatthew Dillon 		 * as a dummy node so dependencies can attach to it,
7298e25f19bSMatthew Dillon 		 * then iterate the first flavor and loop.
7308e25f19bSMatthew Dillon 		 *
7318e25f19bSMatthew Dillon 		 * We must NULL out pkgfile because it will have the
7328e25f19bSMatthew Dillon 		 * default flavor and conflict with the actual flavored
7338e25f19bSMatthew Dillon 		 * pkg.
7348e25f19bSMatthew Dillon 		 */
7358e25f19bSMatthew Dillon 		if (pkg->flavors && pkg->flavors[0]) {
7368e25f19bSMatthew Dillon 			dummy_node = pkg;
7378e25f19bSMatthew Dillon 
7388e25f19bSMatthew Dillon 			pkg->flags |= PKGF_DUMMY;
7398e25f19bSMatthew Dillon 
7408e25f19bSMatthew Dillon 			freestrp(&pkg->fetch_deps);
7418e25f19bSMatthew Dillon 			freestrp(&pkg->ext_deps);
7428e25f19bSMatthew Dillon 			freestrp(&pkg->patch_deps);
7438e25f19bSMatthew Dillon 			freestrp(&pkg->build_deps);
7448e25f19bSMatthew Dillon 			freestrp(&pkg->lib_deps);
7458e25f19bSMatthew Dillon 			freestrp(&pkg->run_deps);
7468e25f19bSMatthew Dillon 
7478e25f19bSMatthew Dillon 			freestrp(&pkg->pkgfile);
7488e25f19bSMatthew Dillon 			*list_tail = pkg;
7498e25f19bSMatthew Dillon 			while (*list_tail)
7508e25f19bSMatthew Dillon 				list_tail = &(*list_tail)->bnext;
7518e25f19bSMatthew Dillon 
7528e25f19bSMatthew Dillon 			flavors_save = strdup(pkg->flavors);
7538e25f19bSMatthew Dillon 			flavors = flavors_save;
7548e25f19bSMatthew Dillon 			do {
7558e25f19bSMatthew Dillon 				flavor = strsep(&flavors, " \t");
7568e25f19bSMatthew Dillon 			} while (flavor && *flavor == 0);
7578e25f19bSMatthew Dillon 			goto again;
7588e25f19bSMatthew Dillon 		}
7598e25f19bSMatthew Dillon 
7608e25f19bSMatthew Dillon 		/*
7618e25f19bSMatthew Dillon 		 * No flavors, add the current unflavored pkg as a real
7628e25f19bSMatthew Dillon 		 * node.
7638e25f19bSMatthew Dillon 		 */
7648e25f19bSMatthew Dillon 		*list_tail = pkg;
7658e25f19bSMatthew Dillon 		while (*list_tail)
7668e25f19bSMatthew Dillon 			list_tail = &(*list_tail)->bnext;
7678e25f19bSMatthew Dillon 	} else {
7688e25f19bSMatthew Dillon 		/*
7698e25f19bSMatthew Dillon 		 * Add flavored package and iterate.
7708e25f19bSMatthew Dillon 		 */
7718e25f19bSMatthew Dillon 		*list_tail = pkg;
7728e25f19bSMatthew Dillon 		while (*list_tail)
7738e25f19bSMatthew Dillon 			list_tail = &(*list_tail)->bnext;
7748e25f19bSMatthew Dillon 
7758e25f19bSMatthew Dillon 		/*
7768e25f19bSMatthew Dillon 		 * Flavor iteration under dummy node, add dependency
7778e25f19bSMatthew Dillon 		 */
7788e25f19bSMatthew Dillon 		if (dummy_node) {
7798e25f19bSMatthew Dillon 			pkglink_t *link;
7808e25f19bSMatthew Dillon 
7818e25f19bSMatthew Dillon 			ddprintf(0, "Add Dependency %s -> %s (flavor rollup)\n",
7828e25f19bSMatthew Dillon 				dummy_node->portdir, pkg->portdir);
7838e25f19bSMatthew Dillon 			link = calloc(1, sizeof(*link));
7848e25f19bSMatthew Dillon 			link->pkg = pkg;
7858e25f19bSMatthew Dillon 			link->next = &dummy_node->idepon_list;
7868e25f19bSMatthew Dillon 			link->prev = dummy_node->idepon_list.prev;
7878e25f19bSMatthew Dillon 			link->next->prev = link;
7888e25f19bSMatthew Dillon 			link->prev->next = link;
789*63fcce5bSMatthew Dillon 			link->dep_type = DEP_TYPE_BUILD;
7908e25f19bSMatthew Dillon 
7918e25f19bSMatthew Dillon 			link = calloc(1, sizeof(*link));
7928e25f19bSMatthew Dillon 			link->pkg = dummy_node;
7938e25f19bSMatthew Dillon 			link->next = &pkg->deponi_list;
7948e25f19bSMatthew Dillon 			link->prev = pkg->deponi_list.prev;
7958e25f19bSMatthew Dillon 			link->next->prev = link;
7968e25f19bSMatthew Dillon 			link->prev->next = link;
797*63fcce5bSMatthew Dillon 			link->dep_type = DEP_TYPE_BUILD;
7988e25f19bSMatthew Dillon 			++pkg->depi_count;
7998e25f19bSMatthew Dillon 		}
8008e25f19bSMatthew Dillon 
8018e25f19bSMatthew Dillon 		if (flavors) {
8028e25f19bSMatthew Dillon 			do {
8038e25f19bSMatthew Dillon 				flavor = strsep(&flavors, " \t");
8048e25f19bSMatthew Dillon 			} while (flavor && *flavor == 0);
8058e25f19bSMatthew Dillon 			if (flavor)
8068e25f19bSMatthew Dillon 				goto again;
8078e25f19bSMatthew Dillon 			free(flavors);
8088e25f19bSMatthew Dillon 		}
8098e25f19bSMatthew Dillon 	}
8108e25f19bSMatthew Dillon }
8118e25f19bSMatthew Dillon 
8128e25f19bSMatthew Dillon /*
8138e25f19bSMatthew Dillon  * Query the package (at least to make sure it hasn't been truncated)
8148e25f19bSMatthew Dillon  * and mark it as PACKAGED if found.
8158e25f19bSMatthew Dillon  *
8168e25f19bSMatthew Dillon  * Threaded function
8178e25f19bSMatthew Dillon  */
8188e25f19bSMatthew Dillon static void
8198e25f19bSMatthew Dillon childGetBinaryDistInfo(bulk_t *bulk)
8208e25f19bSMatthew Dillon {
8218e25f19bSMatthew Dillon 	char *ptr;
8228e25f19bSMatthew Dillon 	FILE *fp;
8238e25f19bSMatthew Dillon 	size_t len;
8248e25f19bSMatthew Dillon 	pkg_t *pkg;
8256fd67931SMatthew Dillon 	const char *cav[MAXCAC];
8266fd67931SMatthew Dillon 	char *repopath;
8276fd67931SMatthew Dillon 	char buf[1024];
8286fd67931SMatthew Dillon 	pid_t pid;
8296fd67931SMatthew Dillon 	int cac;
8308e25f19bSMatthew Dillon 
8316fd67931SMatthew Dillon 	asprintf(&repopath, "%s/%s", RepositoryPath, bulk->s1);
8326fd67931SMatthew Dillon 
8336fd67931SMatthew Dillon 	cac = 0;
8346fd67931SMatthew Dillon 	cav[cac++] = PKG_BINARY;
8356fd67931SMatthew Dillon 	cav[cac++] = "query";
8366fd67931SMatthew Dillon 	cav[cac++] = "-F";
8376fd67931SMatthew Dillon 	cav[cac++] = repopath;
8386fd67931SMatthew Dillon 	cav[cac++] = "%n-%v";
8396fd67931SMatthew Dillon 
8406fd67931SMatthew Dillon 	fp = dexec_open(cav, cac, &pid, 1, 0);
8416fd67931SMatthew Dillon 
8428e25f19bSMatthew Dillon 	while ((ptr = fgetln(fp, &len)) != NULL) {
8438e25f19bSMatthew Dillon 		if (len == 0 || ptr[len-1] != '\n')
8448e25f19bSMatthew Dillon 			continue;
8458e25f19bSMatthew Dillon 		ptr[len-1] = 0;
8468d9409b8SMatthew Dillon 		snprintf(buf, sizeof(buf), "%s%s", ptr, USE_PKG_SUFX);
8478e25f19bSMatthew Dillon 
8488e25f19bSMatthew Dillon 		pkg = pkg_find(buf);
8498d9409b8SMatthew Dillon 		if (pkg) {
8508e25f19bSMatthew Dillon 			pkg->flags |= PKGF_PACKAGED;
8518d9409b8SMatthew Dillon 		} else {
8528e25f19bSMatthew Dillon 			ddprintf(0, "Note: package scan, not in list, "
8538e25f19bSMatthew Dillon 				    "skipping %s\n", buf);
8548e25f19bSMatthew Dillon 		}
8558d9409b8SMatthew Dillon 	}
8566fd67931SMatthew Dillon 	if (dexec_close(fp, pid)) {
8576fd67931SMatthew Dillon 		printf("pkg query command failed for %s\n", repopath);
8586fd67931SMatthew Dillon 	}
8596fd67931SMatthew Dillon 	free(repopath);
8608e25f19bSMatthew Dillon }
8618e25f19bSMatthew Dillon 
8628e25f19bSMatthew Dillon static int
8638e25f19bSMatthew Dillon scan_and_queue_dir(const char *path, const char *level1, int level)
8648e25f19bSMatthew Dillon {
8658e25f19bSMatthew Dillon 	DIR *dir;
8668e25f19bSMatthew Dillon 	char *s1;
8678e25f19bSMatthew Dillon 	char *s2;
8688e25f19bSMatthew Dillon 	struct dirent *den;
8698e25f19bSMatthew Dillon 	struct stat st;
8708e25f19bSMatthew Dillon 	int count = 0;
8718e25f19bSMatthew Dillon 
8728e25f19bSMatthew Dillon 	dir = opendir(path);
8738e25f19bSMatthew Dillon 	dassert(dir, "Cannot open dports path \"%s\"", path);
8748e25f19bSMatthew Dillon 
8758e25f19bSMatthew Dillon 	while ((den = readdir(dir)) != NULL) {
8768e25f19bSMatthew Dillon 		if (den->d_namlen == 1 && den->d_name[0] == '.')
8778e25f19bSMatthew Dillon 			continue;
8788e25f19bSMatthew Dillon 		if (den->d_namlen == 2 &&
8798e25f19bSMatthew Dillon 		    den->d_name[0] == '.' && den->d_name[1] == '.')
8808e25f19bSMatthew Dillon 			continue;
8818e25f19bSMatthew Dillon 		asprintf(&s1, "%s/%s", path, den->d_name);
8828e25f19bSMatthew Dillon 		if (lstat(s1, &st) < 0 || !S_ISDIR(st.st_mode)) {
8838e25f19bSMatthew Dillon 			free(s1);
8848e25f19bSMatthew Dillon 			continue;
8858e25f19bSMatthew Dillon 		}
8868e25f19bSMatthew Dillon 		if (level == 1) {
8878e25f19bSMatthew Dillon 			count += scan_and_queue_dir(s1, den->d_name, 2);
8888e25f19bSMatthew Dillon 			free(s1);
8898e25f19bSMatthew Dillon 			continue;
8908e25f19bSMatthew Dillon 		}
8918e25f19bSMatthew Dillon 		asprintf(&s2, "%s/Makefile", s1);
8928e25f19bSMatthew Dillon 		if (lstat(s2, &st) == 0) {
8938e25f19bSMatthew Dillon 			queuebulk(level1, den->d_name, NULL, NULL);
8948e25f19bSMatthew Dillon 			++count;
8958e25f19bSMatthew Dillon 		}
8968e25f19bSMatthew Dillon 		free(s1);
8978e25f19bSMatthew Dillon 		free(s2);
8988e25f19bSMatthew Dillon 	}
8998e25f19bSMatthew Dillon 	closedir(dir);
9008e25f19bSMatthew Dillon 
9018e25f19bSMatthew Dillon 	return count;
9028e25f19bSMatthew Dillon }
9038e25f19bSMatthew Dillon 
9048e25f19bSMatthew Dillon static int
9058e25f19bSMatthew Dillon scan_binary_repo(const char *path)
9068e25f19bSMatthew Dillon {
9078e25f19bSMatthew Dillon 	DIR *dir;
9088e25f19bSMatthew Dillon 	struct dirent *den;
9098e25f19bSMatthew Dillon 	size_t len;
9108e25f19bSMatthew Dillon 	int count;
9118e25f19bSMatthew Dillon 
9128e25f19bSMatthew Dillon 	count = 0;
9138e25f19bSMatthew Dillon 	dir = opendir(path);
9148e25f19bSMatthew Dillon 	dassert(dir, "Cannot open repository path \"%s\"", path);
9158e25f19bSMatthew Dillon 
9168d9409b8SMatthew Dillon 	/*
9178d9409b8SMatthew Dillon 	 * NOTE: Test includes the '.' in the suffix.
9188d9409b8SMatthew Dillon 	 */
9198e25f19bSMatthew Dillon 	while ((den = readdir(dir)) != NULL) {
9208e25f19bSMatthew Dillon 		len = strlen(den->d_name);
921667fb2cbSMatthew Dillon 		if (len > 4 &&
922667fb2cbSMatthew Dillon 		    strcmp(den->d_name + len - 4, USE_PKG_SUFX) == 0) {
9238e25f19bSMatthew Dillon 			queuebulk(den->d_name, NULL, NULL, NULL);
9248e25f19bSMatthew Dillon 			++count;
9258e25f19bSMatthew Dillon 		}
9268e25f19bSMatthew Dillon 	}
9278e25f19bSMatthew Dillon 	closedir(dir);
9288e25f19bSMatthew Dillon 
9298e25f19bSMatthew Dillon 	return count;
9308e25f19bSMatthew Dillon }
9318e25f19bSMatthew Dillon 
9328e25f19bSMatthew Dillon #if 0
9338e25f19bSMatthew Dillon static void
9348e25f19bSMatthew Dillon pkgfree(pkg_t *pkg)
9358e25f19bSMatthew Dillon {
9368e25f19bSMatthew Dillon 	freestrp(&pkg->portdir);
9378e25f19bSMatthew Dillon 	freestrp(&pkg->version);
9388e25f19bSMatthew Dillon 	freestrp(&pkg->pkgfile);
9398e25f19bSMatthew Dillon 	freestrp(&pkg->ignore);
9408e25f19bSMatthew Dillon 	freestrp(&pkg->fetch_deps);
9418e25f19bSMatthew Dillon 	freestrp(&pkg->ext_deps);
9428e25f19bSMatthew Dillon 	freestrp(&pkg->patch_deps);
9438e25f19bSMatthew Dillon 	freestrp(&pkg->build_deps);
9448e25f19bSMatthew Dillon 	freestrp(&pkg->lib_deps);
9458e25f19bSMatthew Dillon 	freestrp(&pkg->run_deps);
9468e25f19bSMatthew Dillon 	freestrp(&pkg->pos_options);
9478e25f19bSMatthew Dillon 	freestrp(&pkg->neg_options);
9488e25f19bSMatthew Dillon 	freestrp(&pkg->flavors);
9498e25f19bSMatthew Dillon 	free(pkg);
9508e25f19bSMatthew Dillon }
9518e25f19bSMatthew Dillon #endif
952