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(©, " \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