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 43710838f7SMatthew Dillon static int parsepkglist_file(const char *path, int debugstop); 448e25f19bSMatthew Dillon static void childGetPackageInfo(bulk_t *bulk); 458e25f19bSMatthew Dillon static void childGetBinaryDistInfo(bulk_t *bulk); 46a67bf8dbSMatthew Dillon static void childOptimizeEnv(bulk_t *bulk); 478e25f19bSMatthew Dillon static pkg_t *resolveDeps(pkg_t *dep_list, pkg_t ***list_tailp, int gentopo); 4877ac77e7SMatthew Dillon static void resolveFlavors(pkg_t *pkg, char *flavors, int gentopo); 4963fcce5bSMatthew Dillon static void resolveDepString(pkg_t *pkg, char *depstr, 5063fcce5bSMatthew Dillon int gentopo, int dep_type); 518e25f19bSMatthew Dillon static pkg_t *processPackageListBulk(int total); 528e25f19bSMatthew Dillon static int scan_and_queue_dir(const char *path, const char *level1, int level); 538e25f19bSMatthew Dillon static int scan_binary_repo(const char *path); 548e25f19bSMatthew Dillon #if 0 558e25f19bSMatthew Dillon static void pkgfree(pkg_t *pkg); 568e25f19bSMatthew Dillon #endif 578e25f19bSMatthew Dillon 58eea2aa9aSMatthew Dillon static int PrepareSystemFlag; 59eea2aa9aSMatthew Dillon 60d50f9ae3SSascha Wildner static pkg_t *PkgHash1[PKG_HSIZE]; /* by portdir */ 61d50f9ae3SSascha Wildner static pkg_t *PkgHash2[PKG_HSIZE]; /* by pkgfile */ 628e25f19bSMatthew Dillon 638e25f19bSMatthew Dillon /* 648e25f19bSMatthew Dillon * Allocate a new pkg structure plus basic initialization. 658e25f19bSMatthew Dillon */ 668e25f19bSMatthew Dillon static __inline pkg_t * 678e25f19bSMatthew Dillon allocpkg(void) 688e25f19bSMatthew Dillon { 698e25f19bSMatthew Dillon pkg_t *pkg; 708e25f19bSMatthew Dillon 718e25f19bSMatthew Dillon pkg = calloc(1, sizeof(*pkg)); 728e25f19bSMatthew Dillon pkg->idepon_list.next = &pkg->idepon_list; 738e25f19bSMatthew Dillon pkg->idepon_list.prev = &pkg->idepon_list; 748e25f19bSMatthew Dillon pkg->deponi_list.next = &pkg->deponi_list; 758e25f19bSMatthew Dillon pkg->deponi_list.prev = &pkg->deponi_list; 768e25f19bSMatthew Dillon 778e25f19bSMatthew Dillon return pkg; 788e25f19bSMatthew Dillon } 798e25f19bSMatthew Dillon 808e25f19bSMatthew Dillon /* 818e25f19bSMatthew Dillon * Simple hash for lookups 828e25f19bSMatthew Dillon */ 838e25f19bSMatthew Dillon static __inline int 848e25f19bSMatthew Dillon pkghash(const char *str) 858e25f19bSMatthew Dillon { 868e25f19bSMatthew Dillon int hv = 0xABC32923; 878e25f19bSMatthew Dillon while (*str) { 888e25f19bSMatthew Dillon hv = (hv << 5) ^ *str; 898e25f19bSMatthew Dillon ++str; 908e25f19bSMatthew Dillon } 918e25f19bSMatthew Dillon hv = hv ^ (hv / PKG_HSIZE) ^ (hv / PKG_HSIZE / PKG_HSIZE); 928e25f19bSMatthew Dillon return (hv & PKG_HMASK); 938e25f19bSMatthew Dillon } 948e25f19bSMatthew Dillon 9593fe0327SMatthew Dillon static __inline const char * 9693fe0327SMatthew Dillon deptype2str(int dep_type) 9793fe0327SMatthew Dillon { 9893fe0327SMatthew Dillon switch (dep_type) { 9993fe0327SMatthew Dillon case DEP_TYPE_FETCH: 10093fe0327SMatthew Dillon return("FETCH_DEPENDS"); 10193fe0327SMatthew Dillon case DEP_TYPE_EXT: 10293fe0327SMatthew Dillon return("EXTRACT_DEPENDS"); 10393fe0327SMatthew Dillon case DEP_TYPE_PATCH: 10493fe0327SMatthew Dillon return("PATCH_DEPENDS"); 10593fe0327SMatthew Dillon case DEP_TYPE_BUILD: 10693fe0327SMatthew Dillon return("BUILD_DEPENDS"); 10793fe0327SMatthew Dillon case DEP_TYPE_LIB: 10893fe0327SMatthew Dillon return("LIB_DEPENDS"); 10993fe0327SMatthew Dillon case DEP_TYPE_RUN: 11093fe0327SMatthew Dillon return("RUN_DEPENDS"); 11193fe0327SMatthew Dillon default: 112bc91b54aSAlexandr Savca (chinarulezzz) return("UNKNOWN"); 11393fe0327SMatthew Dillon } 11493fe0327SMatthew Dillon } 11593fe0327SMatthew Dillon 1168e25f19bSMatthew Dillon static void 1178e25f19bSMatthew Dillon pkg_enter(pkg_t *pkg) 1188e25f19bSMatthew Dillon { 1198e25f19bSMatthew Dillon pkg_t **pkgp; 1208e25f19bSMatthew Dillon pkg_t *scan; 1218e25f19bSMatthew Dillon 1228e25f19bSMatthew Dillon if (pkg->portdir) { 1238e25f19bSMatthew Dillon pkgp = &PkgHash1[pkghash(pkg->portdir)]; 1248e25f19bSMatthew Dillon while ((scan = *pkgp) != NULL) { 1258e25f19bSMatthew Dillon if (strcmp(pkg->portdir, scan->portdir) == 0) 1268e25f19bSMatthew Dillon break; 1278e25f19bSMatthew Dillon pkgp = &scan->hnext1; 1288e25f19bSMatthew Dillon } 12977ac77e7SMatthew Dillon ddassert(scan == NULL || (scan->flags & PKGF_PLACEHOLD)); 1308e25f19bSMatthew Dillon if (scan && (scan->flags & PKGF_PLACEHOLD)) { 13177ac77e7SMatthew Dillon ddassert(scan->idepon_list.next == &scan->idepon_list); 13277ac77e7SMatthew Dillon ddassert(scan->deponi_list.next == &scan->deponi_list); 1338e25f19bSMatthew Dillon *pkgp = pkg; 1348e25f19bSMatthew Dillon pkg->hnext1 = scan->hnext1; 1358e25f19bSMatthew Dillon free(scan->portdir); 1368e25f19bSMatthew Dillon free(scan); 1378e25f19bSMatthew Dillon scan = NULL; 1388e25f19bSMatthew Dillon } 1398e25f19bSMatthew Dillon if (scan == NULL) 1408e25f19bSMatthew Dillon *pkgp = pkg; 1418e25f19bSMatthew Dillon } 1428e25f19bSMatthew Dillon 1438e25f19bSMatthew Dillon if (pkg->pkgfile) { 1448e25f19bSMatthew Dillon pkgp = &PkgHash2[pkghash(pkg->pkgfile)]; 1458e25f19bSMatthew Dillon while ((scan = *pkgp) != NULL) { 1468e25f19bSMatthew Dillon if (strcmp(pkg->pkgfile, scan->pkgfile) == 0) 1478e25f19bSMatthew Dillon break; 1488e25f19bSMatthew Dillon pkgp = &scan->hnext2; 1498e25f19bSMatthew Dillon } 1508e25f19bSMatthew Dillon if (scan == NULL) 1518e25f19bSMatthew Dillon *pkgp = pkg; 1528e25f19bSMatthew Dillon } 1538e25f19bSMatthew Dillon } 1548e25f19bSMatthew Dillon 1558e25f19bSMatthew Dillon static pkg_t * 1568e25f19bSMatthew Dillon pkg_find(const char *match) 1578e25f19bSMatthew Dillon { 1588e25f19bSMatthew Dillon pkg_t **pkgp; 1598e25f19bSMatthew Dillon pkg_t *pkg; 1608e25f19bSMatthew Dillon 1618e25f19bSMatthew Dillon pkgp = &PkgHash1[pkghash(match)]; 1628e25f19bSMatthew Dillon for (pkg = *pkgp; pkg; pkg = pkg->hnext1) { 1638e25f19bSMatthew Dillon if (strcmp(pkg->portdir, match) == 0) 1648e25f19bSMatthew Dillon return pkg; 1658e25f19bSMatthew Dillon } 1668e25f19bSMatthew Dillon pkgp = &PkgHash2[pkghash(match)]; 1678e25f19bSMatthew Dillon for (pkg = *pkgp; pkg; pkg = pkg->hnext2) { 1688e25f19bSMatthew Dillon if (strcmp(pkg->pkgfile, match) == 0) 1698e25f19bSMatthew Dillon return pkg; 1708e25f19bSMatthew Dillon } 1718e25f19bSMatthew Dillon return NULL; 1728e25f19bSMatthew Dillon } 1738e25f19bSMatthew Dillon 1748e25f19bSMatthew Dillon /* 1758e25f19bSMatthew Dillon * Parse a specific list of ports via origin name (portdir/subdir) 1768e25f19bSMatthew Dillon */ 1778e25f19bSMatthew Dillon pkg_t * 178710838f7SMatthew Dillon ParsePackageList(int n, char **ary, int debugstop) 1798e25f19bSMatthew Dillon { 1808e25f19bSMatthew Dillon pkg_t *list; 1818e25f19bSMatthew Dillon int total; 182310ce99fSMatthew Dillon int fail; 183310ce99fSMatthew Dillon int i; 1848e25f19bSMatthew Dillon 1858e25f19bSMatthew Dillon total = 0; 186310ce99fSMatthew Dillon fail = 0; 1878e25f19bSMatthew Dillon initbulk(childGetPackageInfo, MaxBulk); 1888e25f19bSMatthew Dillon 189f4094b20SMatthew Dillon /* 190710838f7SMatthew Dillon * Always include ports-mgmt/pkg. s4 is "x" meaning not a manual 191710838f7SMatthew Dillon * selection, "d" meaning DEBUGSTOP mode, or NULL. 192f4094b20SMatthew Dillon */ 193f4094b20SMatthew Dillon queuebulk("ports-mgmt", "pkg", NULL, "x"); 194f4094b20SMatthew Dillon 1958e25f19bSMatthew Dillon for (i = 0; i < n; ++i) { 1968e25f19bSMatthew Dillon char *l1; 1978e25f19bSMatthew Dillon char *l2; 19853c9b6f3SMatthew Dillon char *l3; 19953c9b6f3SMatthew Dillon struct stat st; 2008e25f19bSMatthew Dillon 2018e25f19bSMatthew Dillon l1 = strdup(ary[i]); 20253c9b6f3SMatthew Dillon if (stat(l1, &st) == 0 && S_ISREG(st.st_mode)) { 203710838f7SMatthew Dillon total += parsepkglist_file(l1, debugstop); 20453c9b6f3SMatthew Dillon continue; 2058e25f19bSMatthew Dillon } 20653c9b6f3SMatthew Dillon 20753c9b6f3SMatthew Dillon l2 = strchr(l1, '/'); 20853c9b6f3SMatthew Dillon if (l2 == NULL) { 20953c9b6f3SMatthew Dillon printf("Bad portdir specification: %s\n", l1); 21053c9b6f3SMatthew Dillon free(l1); 211310ce99fSMatthew Dillon fail = 1; 21253c9b6f3SMatthew Dillon continue; 21353c9b6f3SMatthew Dillon } 21453c9b6f3SMatthew Dillon *l2++ = 0; 21553c9b6f3SMatthew Dillon l3 = strchr(l2, '@'); 21653c9b6f3SMatthew Dillon if (l3) 21753c9b6f3SMatthew Dillon *l3++ = 0; 218416608a0SMatthew Dillon 219416608a0SMatthew Dillon /* 220416608a0SMatthew Dillon * Silently ignore any manually specified ports-mgmt/pkg, 221416608a0SMatthew Dillon * which we already auto-added. 222416608a0SMatthew Dillon */ 223416608a0SMatthew Dillon if (strcmp(l1, "ports-mgmt") != 0 || 224416608a0SMatthew Dillon strcmp(l2, "pkg") != 0) 225416608a0SMatthew Dillon { 226710838f7SMatthew Dillon queuebulk(l1, l2, l3, (debugstop ? "d" : NULL)); 227416608a0SMatthew Dillon } 22853c9b6f3SMatthew Dillon ++total; 2298e25f19bSMatthew Dillon free(l1); 2308e25f19bSMatthew Dillon } 2318e25f19bSMatthew Dillon printf("Processing %d ports\n", total); 2328e25f19bSMatthew Dillon 2338e25f19bSMatthew Dillon list = processPackageListBulk(total); 234310ce99fSMatthew Dillon if (fail) { 235310ce99fSMatthew Dillon dfatal("Bad specifications, exiting"); 236310ce99fSMatthew Dillon exit(1); 237310ce99fSMatthew Dillon } 2388e25f19bSMatthew Dillon 2398e25f19bSMatthew Dillon return list; 2408e25f19bSMatthew Dillon } 2418e25f19bSMatthew Dillon 24253c9b6f3SMatthew Dillon static 24353c9b6f3SMatthew Dillon int 244710838f7SMatthew Dillon parsepkglist_file(const char *path, int debugstop) 24553c9b6f3SMatthew Dillon { 24653c9b6f3SMatthew Dillon FILE *fp; 24753c9b6f3SMatthew Dillon char *base; 24853c9b6f3SMatthew Dillon char *l1; 24953c9b6f3SMatthew Dillon char *l2; 25053c9b6f3SMatthew Dillon char *l3; 25153c9b6f3SMatthew Dillon size_t len; 25253c9b6f3SMatthew Dillon int total; 25353c9b6f3SMatthew Dillon 25453c9b6f3SMatthew Dillon if ((fp = fopen(path, "r")) == NULL) { 25553c9b6f3SMatthew Dillon dpanic_errno("Cannot read %s\n", path); 25653c9b6f3SMatthew Dillon /* NOT REACHED */ 25753c9b6f3SMatthew Dillon return 0; 25853c9b6f3SMatthew Dillon } 25953c9b6f3SMatthew Dillon 26053c9b6f3SMatthew Dillon total = 0; 26153c9b6f3SMatthew Dillon 26253c9b6f3SMatthew Dillon while ((base = fgetln(fp, &len)) != NULL) { 26353c9b6f3SMatthew Dillon if (len == 0 || base[len-1] != '\n') 26453c9b6f3SMatthew Dillon continue; 26553c9b6f3SMatthew Dillon base[--len] = 0; 26653c9b6f3SMatthew Dillon l1 = strtok(base, " \t\r\n"); 26753c9b6f3SMatthew Dillon if (l1 == NULL) { 26853c9b6f3SMatthew Dillon printf("Badly formatted pkg info line: %s\n", base); 26953c9b6f3SMatthew Dillon continue; 27053c9b6f3SMatthew Dillon } 27153c9b6f3SMatthew Dillon l2 = strchr(l1, '/'); 27253c9b6f3SMatthew Dillon if (l2 == NULL) { 27353c9b6f3SMatthew Dillon printf("Badly formatted specification: %s\n", l1); 27453c9b6f3SMatthew Dillon continue; 27553c9b6f3SMatthew Dillon } 27653c9b6f3SMatthew Dillon *l2++ = 0; 27753c9b6f3SMatthew Dillon l3 = strchr(l2, '@'); 27853c9b6f3SMatthew Dillon if (l3) 27953c9b6f3SMatthew Dillon *l3++ = 0; 280710838f7SMatthew Dillon queuebulk(l1, l2, l3, (debugstop ? "d" : NULL)); 28153c9b6f3SMatthew Dillon ++total; 28253c9b6f3SMatthew Dillon } 28353c9b6f3SMatthew Dillon fclose(fp); 28453c9b6f3SMatthew Dillon 28553c9b6f3SMatthew Dillon return total; 28653c9b6f3SMatthew Dillon } 28753c9b6f3SMatthew Dillon 2888e25f19bSMatthew Dillon /* 2898e25f19bSMatthew Dillon * Parse packages from the list installed on the system. 2908e25f19bSMatthew Dillon */ 2918e25f19bSMatthew Dillon pkg_t * 2928e25f19bSMatthew Dillon GetLocalPackageList(void) 2938e25f19bSMatthew Dillon { 2948e25f19bSMatthew Dillon pkg_t *list; 2958e25f19bSMatthew Dillon FILE *fp; 2968e25f19bSMatthew Dillon char *base; 297eea2aa9aSMatthew Dillon char *data; 2988e25f19bSMatthew Dillon char *l1; 2998e25f19bSMatthew Dillon char *l2; 30053c9b6f3SMatthew Dillon char *l3; 3018e25f19bSMatthew Dillon int total; 302eea2aa9aSMatthew Dillon int state; 3038e25f19bSMatthew Dillon size_t len; 3048e25f19bSMatthew Dillon 305eea2aa9aSMatthew Dillon PrepareSystemFlag = 1; 3068e25f19bSMatthew Dillon initbulk(childGetPackageInfo, MaxBulk); 3078e25f19bSMatthew Dillon total = 0; 308eea2aa9aSMatthew Dillon state = 0; 309eea2aa9aSMatthew Dillon l1 = NULL; 310eea2aa9aSMatthew Dillon l2 = NULL; 311eea2aa9aSMatthew Dillon l3 = NULL; 3128e25f19bSMatthew Dillon 313eea2aa9aSMatthew Dillon fp = popen("pkg info -a -o -A", "r"); 3148e25f19bSMatthew Dillon 315f4094b20SMatthew Dillon /* 316710838f7SMatthew Dillon * Always include ports-mgmt/pkg. s4 is "x" meaning not a manual 317710838f7SMatthew Dillon * selection, "d" meaning DEBUGSTOP mode, or NULL. 318f4094b20SMatthew Dillon */ 319f4094b20SMatthew Dillon queuebulk("ports-mgmt", "pkg", NULL, "x"); 320f4094b20SMatthew Dillon 3218e25f19bSMatthew Dillon while ((base = fgetln(fp, &len)) != NULL) { 3228e25f19bSMatthew Dillon if (len == 0 || base[len-1] != '\n') 3238e25f19bSMatthew Dillon continue; 3248e25f19bSMatthew Dillon base[--len] = 0; 3258e25f19bSMatthew Dillon 326eea2aa9aSMatthew Dillon data = strchr(base, ':'); 327eea2aa9aSMatthew Dillon if (data == NULL) 32853c9b6f3SMatthew Dillon continue; 329eea2aa9aSMatthew Dillon *data++ = 0; 330eea2aa9aSMatthew Dillon 331eea2aa9aSMatthew Dillon base = strtok(base, " \t\r"); 332eea2aa9aSMatthew Dillon data = strtok(data, " \t\r"); 333eea2aa9aSMatthew Dillon 334eea2aa9aSMatthew Dillon if (base == NULL || data == NULL) 335eea2aa9aSMatthew Dillon continue; 336eea2aa9aSMatthew Dillon 337eea2aa9aSMatthew Dillon if (strcmp(base, "Origin") == 0) { 338eea2aa9aSMatthew Dillon if (state == 1) { 339eea2aa9aSMatthew Dillon queuebulk(l1, l2, NULL, NULL); 340eea2aa9aSMatthew Dillon state = 0; 34153c9b6f3SMatthew Dillon ++total; 3428e25f19bSMatthew Dillon } 343eea2aa9aSMatthew Dillon 344eea2aa9aSMatthew Dillon if (strchr(data, '/') == NULL) { 345eea2aa9aSMatthew Dillon printf("Badly formatted origin: %s\n", l1); 346eea2aa9aSMatthew Dillon } 347eea2aa9aSMatthew Dillon if (l1) 348eea2aa9aSMatthew Dillon free(l1); 349eea2aa9aSMatthew Dillon if (l3) 350eea2aa9aSMatthew Dillon free(l3); 351eea2aa9aSMatthew Dillon l1 = strdup(data); 352eea2aa9aSMatthew Dillon l2 = strchr(l1, '/'); 353eea2aa9aSMatthew Dillon *l2++ = 0; 354eea2aa9aSMatthew Dillon l3 = strchr(l2, '@'); /* typically NULL */ 355eea2aa9aSMatthew Dillon if (l3) { 356eea2aa9aSMatthew Dillon *l3++ = 0; 357eea2aa9aSMatthew Dillon l3 = strdup(l3); 358eea2aa9aSMatthew Dillon } 359eea2aa9aSMatthew Dillon 360eea2aa9aSMatthew Dillon /* 361eea2aa9aSMatthew Dillon * Don't queue ports-mgmt/pkg twice, we already 362eea2aa9aSMatthew Dillon * queued it manually. 363eea2aa9aSMatthew Dillon */ 364eea2aa9aSMatthew Dillon if (strcmp(l1, "ports-mgmt") != 0 || 365eea2aa9aSMatthew Dillon strcmp(l2, "pkg") != 0) { 366eea2aa9aSMatthew Dillon state = 1; 367eea2aa9aSMatthew Dillon } 368eea2aa9aSMatthew Dillon continue; 369eea2aa9aSMatthew Dillon } 370eea2aa9aSMatthew Dillon if (state == 1 && strcmp(base, "flavor") == 0) { 371eea2aa9aSMatthew Dillon queuebulk(l1, l2, data, NULL); 372eea2aa9aSMatthew Dillon state = 0; 373eea2aa9aSMatthew Dillon ++total; 374eea2aa9aSMatthew Dillon } 375eea2aa9aSMatthew Dillon } 376eea2aa9aSMatthew Dillon if (state == 1) { 377eea2aa9aSMatthew Dillon queuebulk(l1, l2, NULL, NULL); 378eea2aa9aSMatthew Dillon /*state = 0; not needed */ 379eea2aa9aSMatthew Dillon } 380eea2aa9aSMatthew Dillon if (l1) 381eea2aa9aSMatthew Dillon free(l1); 382eea2aa9aSMatthew Dillon if (l3) 383eea2aa9aSMatthew Dillon free(l3); 384eea2aa9aSMatthew Dillon 3858e25f19bSMatthew Dillon pclose(fp); 3868e25f19bSMatthew Dillon 3878e25f19bSMatthew Dillon printf("Processing %d ports\n", total); 3888e25f19bSMatthew Dillon 3898e25f19bSMatthew Dillon list = processPackageListBulk(total); 3908e25f19bSMatthew Dillon 3918e25f19bSMatthew Dillon return list; 3928e25f19bSMatthew Dillon } 3938e25f19bSMatthew Dillon 3948e25f19bSMatthew Dillon pkg_t * 3958e25f19bSMatthew Dillon GetFullPackageList(void) 3968e25f19bSMatthew Dillon { 3978e25f19bSMatthew Dillon int total; 3988e25f19bSMatthew Dillon 3998e25f19bSMatthew Dillon initbulk(childGetPackageInfo, MaxBulk); 4008e25f19bSMatthew Dillon total = scan_and_queue_dir(DPortsPath, NULL, 1); 4018e25f19bSMatthew Dillon printf("Scanning %d ports\n", total); 4028e25f19bSMatthew Dillon 4038e25f19bSMatthew Dillon return processPackageListBulk(total); 4048e25f19bSMatthew Dillon } 4058e25f19bSMatthew Dillon 4068e25f19bSMatthew Dillon /* 4078e25f19bSMatthew Dillon * Caller has queued the process list for bulk operation. We retrieve 4088e25f19bSMatthew Dillon * the results and clean up the bulk operation (we may have to do a second 4098e25f19bSMatthew Dillon * bulk operation so we have to be the ones to clean it up). 4108e25f19bSMatthew Dillon */ 4118e25f19bSMatthew Dillon static pkg_t * 4128e25f19bSMatthew Dillon processPackageListBulk(int total) 4138e25f19bSMatthew Dillon { 4148e25f19bSMatthew Dillon bulk_t *bulk; 4158e25f19bSMatthew Dillon pkg_t *scan; 4168e25f19bSMatthew Dillon pkg_t *list; 4178e25f19bSMatthew Dillon pkg_t *dep_list; 4188e25f19bSMatthew Dillon pkg_t **list_tail; 4198e25f19bSMatthew Dillon int count; 420927e4e3eSMatthew Dillon int stop_fail; 421eea2aa9aSMatthew Dillon int stop_base_list; 422eea2aa9aSMatthew Dillon int remove_corrupt; 4238e25f19bSMatthew Dillon 4248e25f19bSMatthew Dillon list = NULL; 4258e25f19bSMatthew Dillon list_tail = &list; 4268e25f19bSMatthew Dillon count = 0; 427eea2aa9aSMatthew Dillon remove_corrupt = 0; 4288e25f19bSMatthew Dillon 4298e25f19bSMatthew Dillon while ((bulk = getbulk()) != NULL) { 4308e25f19bSMatthew Dillon ++count; 4318e25f19bSMatthew Dillon if ((count & 255) == 0) { 4328e25f19bSMatthew Dillon printf("%6.2f%%\r", 4338e25f19bSMatthew Dillon (double)count * 100.0 / (double)total + 0.001); 4348e25f19bSMatthew Dillon fflush(stdout); 4358e25f19bSMatthew Dillon } 4368e25f19bSMatthew Dillon if (bulk->list) { 4378e25f19bSMatthew Dillon *list_tail = bulk->list; 4388e25f19bSMatthew Dillon bulk->list = NULL; 439f4094b20SMatthew Dillon while ((scan = *list_tail) != NULL) { 440710838f7SMatthew Dillon if (bulk->s4 == NULL || bulk->s4[0] != 'x') 441f4094b20SMatthew Dillon scan->flags |= PKGF_MANUALSEL; 442f4094b20SMatthew Dillon pkg_enter(scan); 443f4094b20SMatthew Dillon list_tail = &scan->bnext; 4448e25f19bSMatthew Dillon } 4458e25f19bSMatthew Dillon } 4468e25f19bSMatthew Dillon freebulk(bulk); 4478e25f19bSMatthew Dillon } 4481645cafeSMatthew Dillon printf("100.00%%\n"); 4498e25f19bSMatthew Dillon printf("\nTotal %d\n", count); 4508e25f19bSMatthew Dillon fflush(stdout); 4518e25f19bSMatthew Dillon 4528e25f19bSMatthew Dillon /* 4538e25f19bSMatthew Dillon * Resolve all dependencies for the related packages, potentially 4548e25f19bSMatthew Dillon * adding anything that could not be found to the list. This will 4558e25f19bSMatthew Dillon * continue to issue bulk operations and process the result until 4568e25f19bSMatthew Dillon * no dependencies are left. 4578e25f19bSMatthew Dillon */ 4588e25f19bSMatthew Dillon printf("Resolving dependencies..."); 4598e25f19bSMatthew Dillon fflush(stdout); 4608e25f19bSMatthew Dillon dep_list = list; 4618e25f19bSMatthew Dillon while (dep_list) { 4628e25f19bSMatthew Dillon dep_list = resolveDeps(dep_list, &list_tail, 0); 4638e25f19bSMatthew Dillon } 4648e25f19bSMatthew Dillon printf("done\n"); 4658e25f19bSMatthew Dillon 4668e25f19bSMatthew Dillon donebulk(); 4678e25f19bSMatthew Dillon 4688e25f19bSMatthew Dillon /* 4698e25f19bSMatthew Dillon * Generate the topology 4708e25f19bSMatthew Dillon */ 4718e25f19bSMatthew Dillon resolveDeps(list, NULL, 1); 4728e25f19bSMatthew Dillon 4738e25f19bSMatthew Dillon /* 4748e25f19bSMatthew Dillon * Do a final count, ignore place holders. 475927e4e3eSMatthew Dillon * 476927e4e3eSMatthew Dillon * Also set stop_fail if appropriate. Check for direct specifications 477927e4e3eSMatthew Dillon * which fail to probe and any direct dependencies of those 478927e4e3eSMatthew Dillon * specifications, but don't recurse (for now)... don't check indirect 479927e4e3eSMatthew Dillon * dependencies (i.e. A -> B -> C where A is directly specified, B 480927e4e3eSMatthew Dillon * is adirect dependency, and C fails to probe). 4818e25f19bSMatthew Dillon */ 4828e25f19bSMatthew Dillon count = 0; 483927e4e3eSMatthew Dillon stop_fail = 0; 484eea2aa9aSMatthew Dillon stop_base_list = 0; 4858e25f19bSMatthew Dillon for (scan = list; scan; scan = scan->bnext) { 4868e25f19bSMatthew Dillon if ((scan->flags & PKGF_ERROR) == 0) { 4878e25f19bSMatthew Dillon ++count; 4888e25f19bSMatthew Dillon } 489927e4e3eSMatthew Dillon if ((scan->flags & PKGF_MANUALSEL) && MaskProbeAbort == 0) { 490927e4e3eSMatthew Dillon pkglink_t *link; 491927e4e3eSMatthew Dillon 492927e4e3eSMatthew Dillon /* 493927e4e3eSMatthew Dillon * Directly specified package failed to probe 494927e4e3eSMatthew Dillon */ 495eea2aa9aSMatthew Dillon if (scan->flags & PKGF_CORRUPT) { 496927e4e3eSMatthew Dillon ++stop_fail; 497eea2aa9aSMatthew Dillon ++stop_base_list; 498eea2aa9aSMatthew Dillon } 499927e4e3eSMatthew Dillon 500927e4e3eSMatthew Dillon /* 501927e4e3eSMatthew Dillon * Directly specified package had a direct dependency 502927e4e3eSMatthew Dillon * that failed to probe (don't go further). 503927e4e3eSMatthew Dillon */ 504927e4e3eSMatthew Dillon PKGLIST_FOREACH(link, &scan->idepon_list) { 505927e4e3eSMatthew Dillon if (link->pkg && 506927e4e3eSMatthew Dillon (link->pkg->flags & PKGF_CORRUPT)) { 507927e4e3eSMatthew Dillon ++stop_fail; 508927e4e3eSMatthew Dillon } 509927e4e3eSMatthew Dillon } 510927e4e3eSMatthew Dillon } 5118e25f19bSMatthew Dillon } 5128e25f19bSMatthew Dillon printf("Total Returned %d\n", count); 5138e25f19bSMatthew Dillon 5148e25f19bSMatthew Dillon /* 515927e4e3eSMatthew Dillon * Check to see if any PKGF_MANUALSEL packages 516927e4e3eSMatthew Dillon */ 517927e4e3eSMatthew Dillon if (stop_fail) { 518eea2aa9aSMatthew Dillon printf("%d packages failed to probe\n", stop_fail); 519eea2aa9aSMatthew Dillon if (PrepareSystemFlag) { 520eea2aa9aSMatthew Dillon if (stop_fail == stop_base_list) { 521eea2aa9aSMatthew Dillon printf( 522eea2aa9aSMatthew Dillon "prepare-system: Some of your installed packages no longer exist in\n" 523eea2aa9aSMatthew Dillon "dports, do you wish to continue rebuilding what does exist?\n"); 524eea2aa9aSMatthew Dillon if (askyn("Continue anyway? ")) 525eea2aa9aSMatthew Dillon remove_corrupt = 1; 526eea2aa9aSMatthew Dillon } else { 527eea2aa9aSMatthew Dillon printf( 528eea2aa9aSMatthew Dillon "prepare-system: Some of your installed packages have dependencies\n" 529eea2aa9aSMatthew Dillon "which could not be found in dports, cannot continue, aborting\n"); 530eea2aa9aSMatthew Dillon } 531eea2aa9aSMatthew Dillon } else { 532eea2aa9aSMatthew Dillon printf("unable to continue, aborting\n"); 533eea2aa9aSMatthew Dillon } 534eea2aa9aSMatthew Dillon if (remove_corrupt == 0) 535927e4e3eSMatthew Dillon exit(1); 536927e4e3eSMatthew Dillon } 537927e4e3eSMatthew Dillon 538927e4e3eSMatthew Dillon /* 539eea2aa9aSMatthew Dillon * Remove corrupt packages before continuing 540eea2aa9aSMatthew Dillon */ 541eea2aa9aSMatthew Dillon if (remove_corrupt) { 542eea2aa9aSMatthew Dillon list_tail = &list; 543eea2aa9aSMatthew Dillon while ((scan = *list_tail) != NULL) { 544eea2aa9aSMatthew Dillon if (scan->flags & PKGF_CORRUPT) 545eea2aa9aSMatthew Dillon *list_tail = scan->bnext; 546eea2aa9aSMatthew Dillon else 547eea2aa9aSMatthew Dillon list_tail = &scan->bnext; 548eea2aa9aSMatthew Dillon } 549eea2aa9aSMatthew Dillon } 550eea2aa9aSMatthew Dillon 551eea2aa9aSMatthew Dillon /* 5528e25f19bSMatthew Dillon * Scan our binary distributions and related dependencies looking 5538e25f19bSMatthew Dillon * for any packages that have already been built. 5548e25f19bSMatthew Dillon */ 5558e25f19bSMatthew Dillon initbulk(childGetBinaryDistInfo, MaxBulk); 5568e25f19bSMatthew Dillon total = scan_binary_repo(RepositoryPath); 5578e25f19bSMatthew Dillon count = 0; 5588e25f19bSMatthew Dillon printf("Scanning %d packages\n", total); 5598e25f19bSMatthew Dillon 5608e25f19bSMatthew Dillon while ((bulk = getbulk()) != NULL) { 5618e25f19bSMatthew Dillon ++count; 5628e25f19bSMatthew Dillon if ((count & 255) == 0) { 5638e25f19bSMatthew Dillon printf("%6.2f%%\r", 5648e25f19bSMatthew Dillon (double)count * 100.0 / (double)total + 0.001); 5658e25f19bSMatthew Dillon fflush(stdout); 5668e25f19bSMatthew Dillon } 5678e25f19bSMatthew Dillon freebulk(bulk); 5688e25f19bSMatthew Dillon } 5691645cafeSMatthew Dillon printf("100.00%%\n"); 5708e25f19bSMatthew Dillon printf("\nTotal %d\n", count); 5718e25f19bSMatthew Dillon fflush(stdout); 5728e25f19bSMatthew Dillon donebulk(); 5738e25f19bSMatthew Dillon 5748e25f19bSMatthew Dillon printf("all done\n"); 5758e25f19bSMatthew Dillon 5768e25f19bSMatthew Dillon return list; 5778e25f19bSMatthew Dillon } 5788e25f19bSMatthew Dillon 5798e25f19bSMatthew Dillon pkg_t * 580549987f1SMatthew Dillon GetPkgPkg(pkg_t **listp) 5818e25f19bSMatthew Dillon { 5828e25f19bSMatthew Dillon bulk_t *bulk; 5838e25f19bSMatthew Dillon pkg_t *scan; 584549987f1SMatthew Dillon pkg_t *s2; 5858e25f19bSMatthew Dillon 586549987f1SMatthew Dillon for (scan = *listp; scan; scan = scan->bnext) { 5878e25f19bSMatthew Dillon if (strcmp(scan->portdir, "ports-mgmt/pkg") == 0) 5888e25f19bSMatthew Dillon return scan; 5898e25f19bSMatthew Dillon } 5908e25f19bSMatthew Dillon 591f4094b20SMatthew Dillon /* 592f4094b20SMatthew Dillon * This will force pkg to be built, but generally this code 593f4094b20SMatthew Dillon * is not reached because the package list processing code 594f4094b20SMatthew Dillon * adds ports-mgmt/pkg unconditionally. 595f4094b20SMatthew Dillon */ 5968e25f19bSMatthew Dillon initbulk(childGetPackageInfo, MaxBulk); 597f4094b20SMatthew Dillon queuebulk("ports-mgmt", "pkg", NULL, "x"); 5988e25f19bSMatthew Dillon bulk = getbulk(); 5998e25f19bSMatthew Dillon dassert(bulk, "Cannot find ports-mgmt/pkg"); 6008e25f19bSMatthew Dillon scan = bulk->list; 6018e25f19bSMatthew Dillon bulk->list = NULL; 6028e25f19bSMatthew Dillon freebulk(bulk); 6038e25f19bSMatthew Dillon donebulk(); 6048e25f19bSMatthew Dillon 605549987f1SMatthew Dillon 606549987f1SMatthew Dillon /* 607549987f1SMatthew Dillon * Include added packages to the total and add the initial bulk 608549987f1SMatthew Dillon * built packages to the list so they get counted. 609549987f1SMatthew Dillon */ 610549987f1SMatthew Dillon for (s2 = scan; s2->bnext; s2 = s2->bnext) 611549987f1SMatthew Dillon ++BuildTotal; 612549987f1SMatthew Dillon for (s2 = scan; s2->bnext; s2 = s2->bnext) 613549987f1SMatthew Dillon ; 614549987f1SMatthew Dillon s2->bnext = *listp; 615549987f1SMatthew Dillon *listp = scan; 616549987f1SMatthew Dillon ++BuildTotal; 617549987f1SMatthew Dillon 6188e25f19bSMatthew Dillon return scan; 6198e25f19bSMatthew Dillon } 6208e25f19bSMatthew Dillon 6218e25f19bSMatthew Dillon /* 622a67bf8dbSMatthew Dillon * Try to optimize the environment by supplying information that 623a67bf8dbSMatthew Dillon * the ports system would generally have to run stuff to get on 624a67bf8dbSMatthew Dillon * every package. 625a67bf8dbSMatthew Dillon * 626a67bf8dbSMatthew Dillon * See childOptimizeEnv() for the actual handling. We execute 627a67bf8dbSMatthew Dillon * a single make -V... -V... for ports-mgmt/pkg from within the 628a67bf8dbSMatthew Dillon * bulk system (which handles the environment and disables 629a67bf8dbSMatthew Dillon * /etc/make.conf), and we then call addbuildenv() as appropriate. 630a67bf8dbSMatthew Dillon * 631a67bf8dbSMatthew Dillon * _PERL5_FROM_BIN 632a67bf8dbSMatthew Dillon * add others... 633a67bf8dbSMatthew Dillon */ 634a67bf8dbSMatthew Dillon void 635a67bf8dbSMatthew Dillon OptimizeEnv(void) 636a67bf8dbSMatthew Dillon { 637a67bf8dbSMatthew Dillon bulk_t *bulk; 638a67bf8dbSMatthew Dillon 639a67bf8dbSMatthew Dillon initbulk(childOptimizeEnv, MaxBulk); 640a67bf8dbSMatthew Dillon queuebulk("ports-mgmt", "pkg", NULL, NULL); 641a67bf8dbSMatthew Dillon bulk = getbulk(); 642a67bf8dbSMatthew Dillon freebulk(bulk); 643a67bf8dbSMatthew Dillon donebulk(); 644a67bf8dbSMatthew Dillon } 645a67bf8dbSMatthew Dillon 646a67bf8dbSMatthew Dillon /* 6478e25f19bSMatthew Dillon * Run through the list resolving dependencies and constructing the topology 64877ac77e7SMatthew Dillon * linkages. This may append packages to the list. Dependencies to dummy 64977ac77e7SMatthew Dillon * nodes which do not specify a flavor do not need special handling, the 65077ac77e7SMatthew Dillon * search code in build.c will properly follow the first flavor. 6518e25f19bSMatthew Dillon */ 6528e25f19bSMatthew Dillon static pkg_t * 6538e25f19bSMatthew Dillon resolveDeps(pkg_t *list, pkg_t ***list_tailp, int gentopo) 6548e25f19bSMatthew Dillon { 6558e25f19bSMatthew Dillon pkg_t *ret_list = NULL; 65677ac77e7SMatthew Dillon pkg_t *scan; 65777ac77e7SMatthew Dillon pkg_t *use; 6588e25f19bSMatthew Dillon bulk_t *bulk; 6598e25f19bSMatthew Dillon 6608e25f19bSMatthew Dillon for (scan = list; scan; scan = scan->bnext) { 66177ac77e7SMatthew Dillon use = pkg_find(scan->portdir); 66277ac77e7SMatthew Dillon resolveFlavors(use, scan->flavors, gentopo); 66377ac77e7SMatthew Dillon resolveDepString(use, scan->fetch_deps, 66463fcce5bSMatthew Dillon gentopo, DEP_TYPE_FETCH); 66577ac77e7SMatthew Dillon resolveDepString(use, scan->ext_deps, 66663fcce5bSMatthew Dillon gentopo, DEP_TYPE_EXT); 66777ac77e7SMatthew Dillon resolveDepString(use, scan->patch_deps, 66863fcce5bSMatthew Dillon gentopo, DEP_TYPE_PATCH); 66977ac77e7SMatthew Dillon resolveDepString(use, scan->build_deps, 67063fcce5bSMatthew Dillon gentopo, DEP_TYPE_BUILD); 67177ac77e7SMatthew Dillon resolveDepString(use, scan->lib_deps, 67263fcce5bSMatthew Dillon gentopo, DEP_TYPE_LIB); 67377ac77e7SMatthew Dillon resolveDepString(use, scan->run_deps, 67463fcce5bSMatthew Dillon gentopo, DEP_TYPE_RUN); 6758e25f19bSMatthew Dillon } 6768e25f19bSMatthew Dillon 6778e25f19bSMatthew Dillon /* 6788e25f19bSMatthew Dillon * No bulk ops are queued when doing the final topology 6798e25f19bSMatthew Dillon * generation. 68077ac77e7SMatthew Dillon * 68177ac77e7SMatthew Dillon * Avoid entering duplicate results from the bulk ops. Duplicate 68277ac77e7SMatthew Dillon * results are mostly filtered out, but not always. A dummy node 68377ac77e7SMatthew Dillon * representing multiple flavors will parse-out the flavors 6848e25f19bSMatthew Dillon */ 6858e25f19bSMatthew Dillon if (gentopo) 6868e25f19bSMatthew Dillon return NULL; 6878e25f19bSMatthew Dillon while ((bulk = getbulk()) != NULL) { 6888e25f19bSMatthew Dillon if (bulk->list) { 6898e25f19bSMatthew Dillon if (ret_list == NULL) 6908e25f19bSMatthew Dillon ret_list = bulk->list; 6918e25f19bSMatthew Dillon **list_tailp = bulk->list; 6928e25f19bSMatthew Dillon bulk->list = NULL; 69377ac77e7SMatthew Dillon while ((scan = **list_tailp) != NULL) { 69477ac77e7SMatthew Dillon pkg_enter(scan); 69577ac77e7SMatthew Dillon *list_tailp = &scan->bnext; 6968e25f19bSMatthew Dillon } 6978e25f19bSMatthew Dillon } 6988e25f19bSMatthew Dillon freebulk(bulk); 6998e25f19bSMatthew Dillon } 7008e25f19bSMatthew Dillon return (ret_list); 7018e25f19bSMatthew Dillon } 7028e25f19bSMatthew Dillon 70377ac77e7SMatthew Dillon /* 70477ac77e7SMatthew Dillon * Resolve a generic node that has flavors, queue to retrieve info for 70577ac77e7SMatthew Dillon * each flavor and setup linkages as appropriate. 70677ac77e7SMatthew Dillon */ 70777ac77e7SMatthew Dillon static void 70877ac77e7SMatthew Dillon resolveFlavors(pkg_t *pkg, char *flavors, int gentopo) 70977ac77e7SMatthew Dillon { 71077ac77e7SMatthew Dillon char *flavor_base; 71177ac77e7SMatthew Dillon char *flavor_scan; 71277ac77e7SMatthew Dillon char *flavor; 71377ac77e7SMatthew Dillon char *portdir; 71477ac77e7SMatthew Dillon char *s1; 71577ac77e7SMatthew Dillon char *s2; 71677ac77e7SMatthew Dillon pkg_t *dpkg; 71777ac77e7SMatthew Dillon pkglink_t *link; 71877ac77e7SMatthew Dillon 71977ac77e7SMatthew Dillon if ((pkg->flags & PKGF_DUMMY) == 0) 72077ac77e7SMatthew Dillon return; 72177ac77e7SMatthew Dillon if (pkg->flavors == NULL || pkg->flavors[0] == 0) 72277ac77e7SMatthew Dillon return; 72377ac77e7SMatthew Dillon flavor_base = strdup(flavors); 72477ac77e7SMatthew Dillon flavor_scan = flavor_base; 72577ac77e7SMatthew Dillon 72677ac77e7SMatthew Dillon for (;;) { 72777ac77e7SMatthew Dillon do { 72877ac77e7SMatthew Dillon flavor = strsep(&flavor_scan, " \t"); 72977ac77e7SMatthew Dillon } while (flavor && *flavor == 0); 73077ac77e7SMatthew Dillon if (flavor == NULL) 73177ac77e7SMatthew Dillon break; 73277ac77e7SMatthew Dillon 73377ac77e7SMatthew Dillon /* 73477ac77e7SMatthew Dillon * Iterate each flavor generating "s1/s2@flavor". 73577ac77e7SMatthew Dillon * 73677ac77e7SMatthew Dillon * queuebulk() info for each flavor, and set-up the 73777ac77e7SMatthew Dillon * linkages in the topology generation pass. 73877ac77e7SMatthew Dillon */ 73977ac77e7SMatthew Dillon asprintf(&portdir, "%s@%s", pkg->portdir, flavor); 74077ac77e7SMatthew Dillon s1 = strdup(pkg->portdir); 74177ac77e7SMatthew Dillon s2 = strchr(s1, '/'); 74277ac77e7SMatthew Dillon *s2++ = 0; 74377ac77e7SMatthew Dillon 74477ac77e7SMatthew Dillon dpkg = pkg_find(portdir); 74577ac77e7SMatthew Dillon if (dpkg && gentopo) { 74677ac77e7SMatthew Dillon /* 74777ac77e7SMatthew Dillon * Setup linkages 74877ac77e7SMatthew Dillon */ 74977ac77e7SMatthew Dillon free(portdir); 75077ac77e7SMatthew Dillon 75177ac77e7SMatthew Dillon link = calloc(1, sizeof(*link)); 75277ac77e7SMatthew Dillon link->pkg = dpkg; 75377ac77e7SMatthew Dillon link->next = &pkg->idepon_list; 75477ac77e7SMatthew Dillon link->prev = pkg->idepon_list.prev; 75577ac77e7SMatthew Dillon link->next->prev = link; 75677ac77e7SMatthew Dillon link->prev->next = link; 75777ac77e7SMatthew Dillon link->dep_type = DEP_TYPE_BUILD; 75877ac77e7SMatthew Dillon 75977ac77e7SMatthew Dillon link = calloc(1, sizeof(*link)); 76077ac77e7SMatthew Dillon link->pkg = pkg; 76177ac77e7SMatthew Dillon link->next = &dpkg->deponi_list; 76277ac77e7SMatthew Dillon link->prev = dpkg->deponi_list.prev; 76377ac77e7SMatthew Dillon link->next->prev = link; 76477ac77e7SMatthew Dillon link->prev->next = link; 76577ac77e7SMatthew Dillon link->dep_type = DEP_TYPE_BUILD; 76677ac77e7SMatthew Dillon ++dpkg->depi_count; 76777ac77e7SMatthew Dillon } else if (gentopo == 0 && dpkg == NULL) { 76877ac77e7SMatthew Dillon /* 76977ac77e7SMatthew Dillon * Use a place-holder to prevent duplicate 77077ac77e7SMatthew Dillon * dependencies from being processed. The placeholder 77177ac77e7SMatthew Dillon * will be replaced by the actual dependency. 77277ac77e7SMatthew Dillon */ 77377ac77e7SMatthew Dillon dpkg = allocpkg(); 77477ac77e7SMatthew Dillon dpkg->portdir = portdir; 77577ac77e7SMatthew Dillon dpkg->flags = PKGF_PLACEHOLD; 77677ac77e7SMatthew Dillon pkg_enter(dpkg); 77777ac77e7SMatthew Dillon queuebulk(s1, s2, flavor, NULL); 77877ac77e7SMatthew Dillon } 77977ac77e7SMatthew Dillon free(s1); 78077ac77e7SMatthew Dillon } 78177ac77e7SMatthew Dillon free(flavor_base); 78277ac77e7SMatthew Dillon } 78377ac77e7SMatthew Dillon 7848e25f19bSMatthew Dillon static void 78563fcce5bSMatthew Dillon resolveDepString(pkg_t *pkg, char *depstr, int gentopo, int dep_type) 7868e25f19bSMatthew Dillon { 7878e25f19bSMatthew Dillon char *copy_base; 7888e25f19bSMatthew Dillon char *copy; 7898e25f19bSMatthew Dillon char *dep; 79024b60d12SMatthew Dillon char *log_component; 7918e25f19bSMatthew Dillon char *sep; 7928e25f19bSMatthew Dillon char *tag; 7938e25f19bSMatthew Dillon char *flavor; 7948e25f19bSMatthew Dillon pkg_t *dpkg; 7958e25f19bSMatthew Dillon 7968e25f19bSMatthew Dillon if (depstr == NULL || depstr[0] == 0) 7978e25f19bSMatthew Dillon return; 7988e25f19bSMatthew Dillon 7998e25f19bSMatthew Dillon copy_base = strdup(depstr); 8008e25f19bSMatthew Dillon copy = copy_base; 80124b60d12SMatthew Dillon log_component = copy; 8028e25f19bSMatthew Dillon 8038e25f19bSMatthew Dillon for (;;) { 8048e25f19bSMatthew Dillon do { 8058e25f19bSMatthew Dillon dep = strsep(©, " \t"); 8068e25f19bSMatthew Dillon } while (dep && *dep == 0); 8078e25f19bSMatthew Dillon if (dep == NULL) 8088e25f19bSMatthew Dillon break; 8096fd67931SMatthew Dillon 8106fd67931SMatthew Dillon /* 8116fd67931SMatthew Dillon * Ignore dependencies prefixed with ${NONEXISTENT} 8126fd67931SMatthew Dillon */ 8136fd67931SMatthew Dillon if (strncmp(dep, "/nonexistent:", 13) == 0) 8146fd67931SMatthew Dillon continue; 8156fd67931SMatthew Dillon 81624b60d12SMatthew Dillon log_component = dep; 8178e25f19bSMatthew Dillon dep = strchr(dep, ':'); 8188e25f19bSMatthew Dillon if (dep == NULL || *dep != ':') { 81993fe0327SMatthew Dillon printf("Error parsing %s dependency for " 82024b60d12SMatthew Dillon "%s: '%s' at index %zd '%s' " 82124b60d12SMatthew Dillon "(looking for ':')\n", 82293fe0327SMatthew Dillon deptype2str(dep_type), 823baf7c614SMatthew Dillon pkg->portdir, depstr, 82424b60d12SMatthew Dillon log_component - copy_base, 82524b60d12SMatthew Dillon log_component); 8268e25f19bSMatthew Dillon continue; 8278e25f19bSMatthew Dillon } 8288e25f19bSMatthew Dillon ++dep; 8298e25f19bSMatthew Dillon 8308e25f19bSMatthew Dillon /* 8318e25f19bSMatthew Dillon * Strip-off any DPortsPath prefix. EXTRACT_DEPENDS 8328e25f19bSMatthew Dillon * often (always?) generates this prefix. 8338e25f19bSMatthew Dillon */ 8348e25f19bSMatthew Dillon if (strncmp(dep, DPortsPath, strlen(DPortsPath)) == 0) { 8358e25f19bSMatthew Dillon dep += strlen(DPortsPath); 8368e25f19bSMatthew Dillon if (*dep == '/') 8378e25f19bSMatthew Dillon ++dep; 8388e25f19bSMatthew Dillon } 8398e25f19bSMatthew Dillon 8408e25f19bSMatthew Dillon /* 8418e25f19bSMatthew Dillon * Strip-off any tag (such as :patch). We don't try to 8428e25f19bSMatthew Dillon * organize dependencies at this fine a grain (for now). 8438e25f19bSMatthew Dillon */ 8448e25f19bSMatthew Dillon tag = strchr(dep, ':'); 8458e25f19bSMatthew Dillon if (tag) 8468e25f19bSMatthew Dillon *tag++ = 0; 84724b60d12SMatthew Dillon log_component = dep; 8488e25f19bSMatthew Dillon 8498e25f19bSMatthew Dillon /* 8508e25f19bSMatthew Dillon * Locate the dependency 8518e25f19bSMatthew Dillon */ 8528e25f19bSMatthew Dillon if ((dpkg = pkg_find(dep)) != NULL) { 8538e25f19bSMatthew Dillon if (gentopo) { 8548e25f19bSMatthew Dillon pkglink_t *link; 8558e25f19bSMatthew Dillon 8568e25f19bSMatthew Dillon /* 8578e25f19bSMatthew Dillon * NOTE: idep_count is calculated recursively 8588e25f19bSMatthew Dillon * at build-time 8598e25f19bSMatthew Dillon */ 8608e25f19bSMatthew Dillon ddprintf(0, "Add Dependency %s -> %s\n", 8618e25f19bSMatthew Dillon pkg->portdir, dpkg->portdir); 8628e25f19bSMatthew Dillon link = calloc(1, sizeof(*link)); 8638e25f19bSMatthew Dillon link->pkg = dpkg; 8648e25f19bSMatthew Dillon link->next = &pkg->idepon_list; 8658e25f19bSMatthew Dillon link->prev = pkg->idepon_list.prev; 8668e25f19bSMatthew Dillon link->next->prev = link; 8678e25f19bSMatthew Dillon link->prev->next = link; 86863fcce5bSMatthew Dillon link->dep_type = dep_type; 8698e25f19bSMatthew Dillon 8708e25f19bSMatthew Dillon link = calloc(1, sizeof(*link)); 8718e25f19bSMatthew Dillon link->pkg = pkg; 8728e25f19bSMatthew Dillon link->next = &dpkg->deponi_list; 8738e25f19bSMatthew Dillon link->prev = dpkg->deponi_list.prev; 8748e25f19bSMatthew Dillon link->next->prev = link; 8758e25f19bSMatthew Dillon link->prev->next = link; 87663fcce5bSMatthew Dillon link->dep_type = dep_type; 8778e25f19bSMatthew Dillon ++dpkg->depi_count; 8788e25f19bSMatthew Dillon } 8798e25f19bSMatthew Dillon continue; 8808e25f19bSMatthew Dillon } 8818e25f19bSMatthew Dillon 8828e25f19bSMatthew Dillon /* 8838e25f19bSMatthew Dillon * This shouldn't happen because we already took a first 8848e25f19bSMatthew Dillon * pass and should have generated the pkgs. 8858e25f19bSMatthew Dillon */ 8868e25f19bSMatthew Dillon if (gentopo) { 8878e25f19bSMatthew Dillon printf("Topology Generate failed for %s: %s\n", 8888e25f19bSMatthew Dillon pkg->portdir, copy_base); 8898e25f19bSMatthew Dillon continue; 8908e25f19bSMatthew Dillon } 8918e25f19bSMatthew Dillon 8928e25f19bSMatthew Dillon /* 8938e25f19bSMatthew Dillon * Separate out the two dports directory components and 8948e25f19bSMatthew Dillon * extract the optional '@flavor' specification. 8958e25f19bSMatthew Dillon */ 8968e25f19bSMatthew Dillon sep = strchr(dep, '/'); 8978e25f19bSMatthew Dillon if (sep == NULL) { 89893fe0327SMatthew Dillon printf("Error parsing %s dependency for " 89924b60d12SMatthew Dillon "%s: '%s' at index %zd '%s' " 90024b60d12SMatthew Dillon "(looking for '/')\n", 90193fe0327SMatthew Dillon deptype2str(dep_type), 902baf7c614SMatthew Dillon pkg->portdir, depstr, 90324b60d12SMatthew Dillon log_component - copy_base, 90424b60d12SMatthew Dillon log_component); 9058e25f19bSMatthew Dillon continue; 9068e25f19bSMatthew Dillon } 9078e25f19bSMatthew Dillon *sep++ = 0; 9088e25f19bSMatthew Dillon 90995f08ce8SMatthew Dillon /* 91095f08ce8SMatthew Dillon * The flavor hangs off the separator, not the tag 91195f08ce8SMatthew Dillon */ 91295f08ce8SMatthew Dillon flavor = strrchr(sep, '@'); 91395f08ce8SMatthew Dillon #if 0 9148e25f19bSMatthew Dillon if (tag) 9158e25f19bSMatthew Dillon flavor = strrchr(tag, '@'); 9168e25f19bSMatthew Dillon else 9178e25f19bSMatthew Dillon flavor = strrchr(sep, '@'); 91895f08ce8SMatthew Dillon #endif 9198e25f19bSMatthew Dillon if (flavor) 9208e25f19bSMatthew Dillon *flavor++ = 0; 9218e25f19bSMatthew Dillon 9228e25f19bSMatthew Dillon if (flavor) 9238e25f19bSMatthew Dillon ddprintf(0, "QUEUE DEPENDENCY FROM PKG %s: %s/%s@%s\n", 9248e25f19bSMatthew Dillon pkg->portdir, dep, sep, flavor); 9258e25f19bSMatthew Dillon else 9268e25f19bSMatthew Dillon ddprintf(0, "QUEUE DEPENDENCY FROM PKG %s: %s/%s\n", 9278e25f19bSMatthew Dillon pkg->portdir, dep, sep); 9288e25f19bSMatthew Dillon 9298e25f19bSMatthew Dillon /* 9308e25f19bSMatthew Dillon * Use a place-holder to prevent duplicate dependencies from 9318e25f19bSMatthew Dillon * being processed. The placeholder will be replaced by 9328e25f19bSMatthew Dillon * the actual dependency. 9338e25f19bSMatthew Dillon */ 9348e25f19bSMatthew Dillon dpkg = allocpkg(); 9358e25f19bSMatthew Dillon if (flavor) 9368e25f19bSMatthew Dillon asprintf(&dpkg->portdir, "%s/%s@%s", dep, sep, flavor); 9378e25f19bSMatthew Dillon else 9388e25f19bSMatthew Dillon asprintf(&dpkg->portdir, "%s/%s", dep, sep); 9398e25f19bSMatthew Dillon dpkg->flags = PKGF_PLACEHOLD; 9408e25f19bSMatthew Dillon pkg_enter(dpkg); 9418e25f19bSMatthew Dillon 9428e25f19bSMatthew Dillon queuebulk(dep, sep, flavor, NULL); 9438e25f19bSMatthew Dillon } 9448e25f19bSMatthew Dillon free(copy_base); 9458e25f19bSMatthew Dillon } 9468e25f19bSMatthew Dillon 9478e25f19bSMatthew Dillon void 9488e25f19bSMatthew Dillon FreePackageList(pkg_t *pkgs __unused) 9498e25f19bSMatthew Dillon { 9508e25f19bSMatthew Dillon dfatal("not implemented"); 9518e25f19bSMatthew Dillon } 9528e25f19bSMatthew Dillon 9538e25f19bSMatthew Dillon /* 9548e25f19bSMatthew Dillon * Scan some or all dports to allocate the related pkg structure. Dependencies 9558e25f19bSMatthew Dillon * are stored but not processed. 9568e25f19bSMatthew Dillon * 9578e25f19bSMatthew Dillon * Threaded function 9588e25f19bSMatthew Dillon */ 9598e25f19bSMatthew Dillon static void 9608e25f19bSMatthew Dillon childGetPackageInfo(bulk_t *bulk) 9618e25f19bSMatthew Dillon { 9628e25f19bSMatthew Dillon pkg_t *pkg; 9638e25f19bSMatthew Dillon char *flavor; 9648e25f19bSMatthew Dillon char *ptr; 9658e25f19bSMatthew Dillon FILE *fp; 9668e25f19bSMatthew Dillon int line; 9678e25f19bSMatthew Dillon size_t len; 9686fd67931SMatthew Dillon char *portpath; 9696fd67931SMatthew Dillon char *flavarg; 970*5d0718a8SMatthew Dillon char *localbase; 9716fd67931SMatthew Dillon const char *cav[MAXCAC]; 9726fd67931SMatthew Dillon pid_t pid; 9736fd67931SMatthew Dillon int cac; 9748e25f19bSMatthew Dillon 9758e25f19bSMatthew Dillon /* 9768e25f19bSMatthew Dillon * If the package has flavors we will loop on each one. If a flavor 9778e25f19bSMatthew Dillon * is not passed in s3 we will loop on all flavors, otherwise we will 9788e25f19bSMatthew Dillon * only process the passed-in flavor. 9798e25f19bSMatthew Dillon */ 9808e25f19bSMatthew Dillon flavor = bulk->s3; /* usually NULL */ 9818e25f19bSMatthew Dillon 9828e25f19bSMatthew Dillon bulk->list = NULL; 98377ac77e7SMatthew Dillon 9846fd67931SMatthew Dillon asprintf(&portpath, "%s/%s/%s", DPortsPath, bulk->s1, bulk->s2); 9856fd67931SMatthew Dillon if (flavor) 9866fd67931SMatthew Dillon asprintf(&flavarg, "FLAVOR=%s", flavor); 9876fd67931SMatthew Dillon else 9886fd67931SMatthew Dillon flavarg = NULL; 9896fd67931SMatthew Dillon 9906fd67931SMatthew Dillon cac = 0; 9916fd67931SMatthew Dillon cav[cac++] = MAKE_BINARY; 9926fd67931SMatthew Dillon cav[cac++] = "-C"; 9936fd67931SMatthew Dillon cav[cac++] = portpath; 9946fd67931SMatthew Dillon if (flavarg) 9956fd67931SMatthew Dillon cav[cac++] = flavarg; 996*5d0718a8SMatthew Dillon 997*5d0718a8SMatthew Dillon /* 998*5d0718a8SMatthew Dillon * Prevent postgresql, mysql, and other package Makefile tests 999*5d0718a8SMatthew Dillon * from accessing the host system's /usr/local by setting LOCALBASE 1000*5d0718a8SMatthew Dillon * to an empty directory. 1001*5d0718a8SMatthew Dillon */ 1002*5d0718a8SMatthew Dillon asprintf(&localbase, "LOCALBASE=%s/empty", BuildBase); 1003*5d0718a8SMatthew Dillon cav[cac++] = localbase; 1004*5d0718a8SMatthew Dillon 1005*5d0718a8SMatthew Dillon /* 1006*5d0718a8SMatthew Dillon * Variables we need to retrieve (order is specific to the switch 1007*5d0718a8SMatthew Dillon * below) 1008*5d0718a8SMatthew Dillon */ 10096fd67931SMatthew Dillon cav[cac++] = "-VPKGVERSION"; 10106fd67931SMatthew Dillon cav[cac++] = "-VPKGFILE:T"; 10116ec1f604SMatthew Dillon cav[cac++] = "-VALLFILES"; 10126fd67931SMatthew Dillon cav[cac++] = "-VDIST_SUBDIR"; 10136fd67931SMatthew Dillon cav[cac++] = "-VMAKE_JOBS_NUMBER"; 10146fd67931SMatthew Dillon cav[cac++] = "-VIGNORE"; 10156fd67931SMatthew Dillon cav[cac++] = "-VFETCH_DEPENDS"; 10166fd67931SMatthew Dillon cav[cac++] = "-VEXTRACT_DEPENDS"; 10176fd67931SMatthew Dillon cav[cac++] = "-VPATCH_DEPENDS"; 10186fd67931SMatthew Dillon cav[cac++] = "-VBUILD_DEPENDS"; 10196fd67931SMatthew Dillon cav[cac++] = "-VLIB_DEPENDS"; 10206fd67931SMatthew Dillon cav[cac++] = "-VRUN_DEPENDS"; 10216fd67931SMatthew Dillon cav[cac++] = "-VSELECTED_OPTIONS"; 10226fd67931SMatthew Dillon cav[cac++] = "-VDESELECTED_OPTIONS"; 10236fd67931SMatthew Dillon cav[cac++] = "-VUSE_LINUX"; 10246fd67931SMatthew Dillon cav[cac++] = "-VFLAVORS"; 1025f4094b20SMatthew Dillon cav[cac++] = "-VUSES"; 10266fd67931SMatthew Dillon 1027f9d29536SMatthew Dillon fp = dexec_open(portpath + strlen(DPortsPath) + 1, cav, cac, 1028f9d29536SMatthew Dillon &pid, NULL, 1, 1); 10296fd67931SMatthew Dillon freestrp(&flavarg); 1030*5d0718a8SMatthew Dillon freestrp(&localbase); 10318e25f19bSMatthew Dillon 10328e25f19bSMatthew Dillon pkg = allocpkg(); 10338e25f19bSMatthew Dillon if (flavor) 10348e25f19bSMatthew Dillon asprintf(&pkg->portdir, "%s/%s@%s", bulk->s1, bulk->s2, flavor); 10358e25f19bSMatthew Dillon else 10368e25f19bSMatthew Dillon asprintf(&pkg->portdir, "%s/%s", bulk->s1, bulk->s2); 10378e25f19bSMatthew Dillon 10386fd67931SMatthew Dillon line = 1; 10398e25f19bSMatthew Dillon while ((ptr = fgetln(fp, &len)) != NULL) { 10408e25f19bSMatthew Dillon if (len == 0 || ptr[len-1] != '\n') { 10418e25f19bSMatthew Dillon dfatal("Bad package info for %s/%s response line %d", 10428e25f19bSMatthew Dillon bulk->s1, bulk->s2, line); 10438e25f19bSMatthew Dillon } 10448e25f19bSMatthew Dillon ptr[--len] = 0; 10458e25f19bSMatthew Dillon 10468e25f19bSMatthew Dillon switch(line) { 10478e25f19bSMatthew Dillon case 1: /* PKGVERSION */ 10488e25f19bSMatthew Dillon asprintf(&pkg->version, "%s", ptr); 10498e25f19bSMatthew Dillon break; 10508e25f19bSMatthew Dillon case 2: /* PKGFILE */ 10518e25f19bSMatthew Dillon asprintf(&pkg->pkgfile, "%s", ptr); 10528e25f19bSMatthew Dillon break; 10536ec1f604SMatthew Dillon case 3: /* ALLFILES (aka DISTFILES + patch files) */ 10541645cafeSMatthew Dillon asprintf(&pkg->distfiles, "%s", ptr); 10551645cafeSMatthew Dillon break; 10561645cafeSMatthew Dillon case 4: /* DIST_SUBDIR */ 10574ea2ee4dSMatthew Dillon pkg->distsubdir = strdup_or_null(ptr); 10581645cafeSMatthew Dillon break; 10591645cafeSMatthew Dillon case 5: /* MAKE_JOBS_NUMBER */ 10608e25f19bSMatthew Dillon pkg->make_jobs_number = strtol(ptr, NULL, 0); 10618e25f19bSMatthew Dillon break; 10621645cafeSMatthew Dillon case 6: /* IGNORE */ 10634ea2ee4dSMatthew Dillon pkg->ignore = strdup_or_null(ptr); 10648e25f19bSMatthew Dillon break; 10651645cafeSMatthew Dillon case 7: /* FETCH_DEPENDS */ 10664ea2ee4dSMatthew Dillon pkg->fetch_deps = strdup_or_null(ptr); 10678e25f19bSMatthew Dillon break; 10681645cafeSMatthew Dillon case 8: /* EXTRACT_DEPENDS */ 10694ea2ee4dSMatthew Dillon pkg->ext_deps = strdup_or_null(ptr); 10708e25f19bSMatthew Dillon break; 10711645cafeSMatthew Dillon case 9: /* PATCH_DEPENDS */ 10724ea2ee4dSMatthew Dillon pkg->patch_deps = strdup_or_null(ptr); 10738e25f19bSMatthew Dillon break; 10741645cafeSMatthew Dillon case 10: /* BUILD_DEPENDS */ 10754ea2ee4dSMatthew Dillon pkg->build_deps = strdup_or_null(ptr); 10768e25f19bSMatthew Dillon break; 10771645cafeSMatthew Dillon case 11: /* LIB_DEPENDS */ 10784ea2ee4dSMatthew Dillon pkg->lib_deps = strdup_or_null(ptr); 10798e25f19bSMatthew Dillon break; 10801645cafeSMatthew Dillon case 12: /* RUN_DEPENDS */ 10814ea2ee4dSMatthew Dillon pkg->run_deps = strdup_or_null(ptr); 10828e25f19bSMatthew Dillon break; 10831645cafeSMatthew Dillon case 13: /* SELECTED_OPTIONS */ 10844ea2ee4dSMatthew Dillon pkg->pos_options = strdup_or_null(ptr); 10858e25f19bSMatthew Dillon break; 10861645cafeSMatthew Dillon case 14: /* DESELECTED_OPTIONS */ 10874ea2ee4dSMatthew Dillon pkg->neg_options = strdup_or_null(ptr); 10888e25f19bSMatthew Dillon break; 10891645cafeSMatthew Dillon case 15: /* USE_LINUX */ 10908e25f19bSMatthew Dillon if (ptr[0]) 10918e25f19bSMatthew Dillon pkg->use_linux = 1; 10928e25f19bSMatthew Dillon break; 10931645cafeSMatthew Dillon case 16: /* FLAVORS */ 10948e25f19bSMatthew Dillon asprintf(&pkg->flavors, "%s", ptr); 10958e25f19bSMatthew Dillon break; 1096f4094b20SMatthew Dillon case 17: /* USES */ 1097f4094b20SMatthew Dillon asprintf(&pkg->uses, "%s", ptr); 1098f4094b20SMatthew Dillon if (strstr(pkg->uses, "metaport")) 1099f4094b20SMatthew Dillon pkg->flags |= PKGF_META; 1100f4094b20SMatthew Dillon break; 11018e25f19bSMatthew Dillon default: 11028e25f19bSMatthew Dillon printf("EXTRA LINE: %s\n", ptr); 11038e25f19bSMatthew Dillon break; 11048e25f19bSMatthew Dillon } 11058e25f19bSMatthew Dillon ++line; 11068e25f19bSMatthew Dillon } 11078e25f19bSMatthew Dillon if (line == 1) { 11088e25f19bSMatthew Dillon printf("DPort not found: %s/%s\n", bulk->s1, bulk->s2); 11098e25f19bSMatthew Dillon pkg->flags |= PKGF_NOTFOUND; 1110f4094b20SMatthew Dillon } else if (line != 17 + 1) { 11118e25f19bSMatthew Dillon printf("DPort corrupt: %s/%s\n", bulk->s1, bulk->s2); 11128e25f19bSMatthew Dillon pkg->flags |= PKGF_CORRUPT; 11138e25f19bSMatthew Dillon } 11146fd67931SMatthew Dillon if (dexec_close(fp, pid)) { 11156fd67931SMatthew Dillon printf("make -V* command for %s/%s failed\n", 11166fd67931SMatthew Dillon bulk->s1, bulk->s2); 11176fd67931SMatthew Dillon pkg->flags |= PKGF_CORRUPT; 11186fd67931SMatthew Dillon } 11198e25f19bSMatthew Dillon ddassert(bulk->s1); 11208e25f19bSMatthew Dillon 11218e25f19bSMatthew Dillon /* 1122710838f7SMatthew Dillon * DEBUGSTOP mode 1123710838f7SMatthew Dillon */ 1124710838f7SMatthew Dillon if (bulk->s4 && bulk->s4[0] == 'd') 1125710838f7SMatthew Dillon pkg->flags |= PKGF_DEBUGSTOP; 1126710838f7SMatthew Dillon 1127710838f7SMatthew Dillon /* 112877ac77e7SMatthew Dillon * Mark as a dummy node, the front-end will iterate the flavors 112977ac77e7SMatthew Dillon * and create sub-nodes for us. 11308e25f19bSMatthew Dillon * 113177ac77e7SMatthew Dillon * Get rid of elements returned that are for the first flavor. 113277ac77e7SMatthew Dillon * We are creating a dummy node here, not the node for the first 113377ac77e7SMatthew Dillon * flavor. 11348e25f19bSMatthew Dillon */ 113577ac77e7SMatthew Dillon if (flavor == NULL && pkg->flavors && pkg->flavors[0]) { 11368e25f19bSMatthew Dillon pkg->flags |= PKGF_DUMMY; 11378e25f19bSMatthew Dillon freestrp(&pkg->fetch_deps); 11388e25f19bSMatthew Dillon freestrp(&pkg->ext_deps); 11398e25f19bSMatthew Dillon freestrp(&pkg->patch_deps); 11408e25f19bSMatthew Dillon freestrp(&pkg->build_deps); 11418e25f19bSMatthew Dillon freestrp(&pkg->lib_deps); 11428e25f19bSMatthew Dillon freestrp(&pkg->run_deps); 11438e25f19bSMatthew Dillon freestrp(&pkg->pkgfile); 11448e25f19bSMatthew Dillon } 11458e25f19bSMatthew Dillon 11468e25f19bSMatthew Dillon /* 1147b6bd007bSMatthew Dillon * Checksum the port directory tree. This just rollsup crcs of the 1148b6bd007bSMatthew Dillon * path names and a few stat fields (mtime, size) in order to detect 1149b6bd007bSMatthew Dillon * if any modification has been made to the port. 1150b6bd007bSMatthew Dillon */ 1151b6bd007bSMatthew Dillon pkg->crc32 = crcDirTree(portpath); 1152b6bd007bSMatthew Dillon 1153b6bd007bSMatthew Dillon /* 115477ac77e7SMatthew Dillon * Only one pkg is put on the return list now. This code no 115577ac77e7SMatthew Dillon * longer creates pseudo-nodes for flavors (the frontend requests 115677ac77e7SMatthew Dillon * each flavor instead). 11578e25f19bSMatthew Dillon */ 115877ac77e7SMatthew Dillon bulk->list = pkg; 1159b6bd007bSMatthew Dillon free(portpath); 11608e25f19bSMatthew Dillon } 11618e25f19bSMatthew Dillon 11628e25f19bSMatthew Dillon /* 11638e25f19bSMatthew Dillon * Query the package (at least to make sure it hasn't been truncated) 11648e25f19bSMatthew Dillon * and mark it as PACKAGED if found. 11658e25f19bSMatthew Dillon * 1166753e4c44SMatthew Dillon * This is a pre-req prior to doing builds, so we cannot assume that 1167753e4c44SMatthew Dillon * the template has its pkg-static binary yet. 1168753e4c44SMatthew Dillon * 11698e25f19bSMatthew Dillon * Threaded function 11708e25f19bSMatthew Dillon */ 11718e25f19bSMatthew Dillon static void 11728e25f19bSMatthew Dillon childGetBinaryDistInfo(bulk_t *bulk) 11738e25f19bSMatthew Dillon { 11748e25f19bSMatthew Dillon char *ptr; 11758e25f19bSMatthew Dillon FILE *fp; 11768e25f19bSMatthew Dillon size_t len; 11778e25f19bSMatthew Dillon pkg_t *pkg; 11786fd67931SMatthew Dillon const char *cav[MAXCAC]; 11796fd67931SMatthew Dillon char *repopath; 11806fd67931SMatthew Dillon char buf[1024]; 11816fd67931SMatthew Dillon pid_t pid; 11826fd67931SMatthew Dillon int cac; 1183dc46751bSMatthew Dillon int deleteme; 11848e25f19bSMatthew Dillon 11856fd67931SMatthew Dillon asprintf(&repopath, "%s/%s", RepositoryPath, bulk->s1); 11866fd67931SMatthew Dillon 11876fd67931SMatthew Dillon cac = 0; 11886fd67931SMatthew Dillon cav[cac++] = PKG_BINARY; 11896fd67931SMatthew Dillon cav[cac++] = "query"; 11906fd67931SMatthew Dillon cav[cac++] = "-F"; 11916fd67931SMatthew Dillon cav[cac++] = repopath; 11926fd67931SMatthew Dillon cav[cac++] = "%n-%v"; 11936fd67931SMatthew Dillon 1194f9d29536SMatthew Dillon fp = dexec_open(NULL, cav, cac, &pid, NULL, 1, 0); 1195dc46751bSMatthew Dillon deleteme = DeleteObsoletePkgs; 11966fd67931SMatthew Dillon 11978e25f19bSMatthew Dillon while ((ptr = fgetln(fp, &len)) != NULL) { 11988e25f19bSMatthew Dillon if (len == 0 || ptr[len-1] != '\n') 11998e25f19bSMatthew Dillon continue; 12008e25f19bSMatthew Dillon ptr[len-1] = 0; 12018e25f19bSMatthew Dillon 1202753e4c44SMatthew Dillon /* 1203753e4c44SMatthew Dillon * As of pkg 1.17 the binary dist files use a .pkg suffix 1204753e4c44SMatthew Dillon * regardless of the compression format, so always check 1205753e4c44SMatthew Dillon * those. 1206753e4c44SMatthew Dillon */ 1207753e4c44SMatthew Dillon snprintf(buf, sizeof(buf), "%s%s", ptr, ".pkg"); 12088e25f19bSMatthew Dillon pkg = pkg_find(buf); 1209753e4c44SMatthew Dillon if (pkg == NULL) { 1210753e4c44SMatthew Dillon snprintf(buf, sizeof(buf), "%s%s", ptr, UsePkgSufx); 1211753e4c44SMatthew Dillon pkg = pkg_find(buf); 1212753e4c44SMatthew Dillon } 12138d9409b8SMatthew Dillon if (pkg) { 1214325ef124SMatthew Dillon if (FetchOnlyOpt) { 1215325ef124SMatthew Dillon ddprintf(0, "Note: Package is already packaged, ignore for -f: %s\n", ptr); 1216325ef124SMatthew Dillon deleteme = 0; 1217325ef124SMatthew Dillon } else { 12188e25f19bSMatthew Dillon pkg->flags |= PKGF_PACKAGED; 1219dc46751bSMatthew Dillon deleteme = 0; 1220325ef124SMatthew Dillon } 12218d9409b8SMatthew Dillon } else { 12228e25f19bSMatthew Dillon ddprintf(0, "Note: package scan, not in list, " 1223753e4c44SMatthew Dillon "skipping %s{.%s,.pkg}\n", ptr, UsePkgSufx); 12248e25f19bSMatthew Dillon } 12258d9409b8SMatthew Dillon } 12266fd67931SMatthew Dillon if (dexec_close(fp, pid)) { 12276fd67931SMatthew Dillon printf("pkg query command failed for %s\n", repopath); 12286fd67931SMatthew Dillon } 1229dc46751bSMatthew Dillon if (deleteme) { 1230dc46751bSMatthew Dillon dlog(DLOG_ALL | DLOG_STDOUT, 1231dc46751bSMatthew Dillon "Deleting obsolete package %s\n", repopath); 1232dc46751bSMatthew Dillon remove(repopath); 1233dc46751bSMatthew Dillon } 12346fd67931SMatthew Dillon free(repopath); 12358e25f19bSMatthew Dillon } 12368e25f19bSMatthew Dillon 1237a67bf8dbSMatthew Dillon static void 1238a67bf8dbSMatthew Dillon childOptimizeEnv(bulk_t *bulk) 1239a67bf8dbSMatthew Dillon { 1240a67bf8dbSMatthew Dillon char *portpath; 1241*5d0718a8SMatthew Dillon char *localbase; 1242a67bf8dbSMatthew Dillon char *ptr; 1243a67bf8dbSMatthew Dillon FILE *fp; 1244a67bf8dbSMatthew Dillon int line; 1245a67bf8dbSMatthew Dillon size_t len; 1246a67bf8dbSMatthew Dillon const char *cav[MAXCAC]; 1247a67bf8dbSMatthew Dillon pid_t pid; 1248a67bf8dbSMatthew Dillon int cac; 1249a67bf8dbSMatthew Dillon 1250a67bf8dbSMatthew Dillon asprintf(&portpath, "%s/%s/%s", DPortsPath, bulk->s1, bulk->s2); 1251a67bf8dbSMatthew Dillon 1252*5d0718a8SMatthew Dillon /* 1253*5d0718a8SMatthew Dillon * Prevent postgresql, mysql, and other package Makefile tests 1254*5d0718a8SMatthew Dillon * from accessing the host system's /usr/local by setting LOCALBASE 1255*5d0718a8SMatthew Dillon * to an empty directory. 1256*5d0718a8SMatthew Dillon */ 1257*5d0718a8SMatthew Dillon asprintf(&localbase, "LOCALBASE=%s/empty", BuildBase); 1258*5d0718a8SMatthew Dillon 1259a67bf8dbSMatthew Dillon cac = 0; 1260a67bf8dbSMatthew Dillon cav[cac++] = MAKE_BINARY; 1261a67bf8dbSMatthew Dillon cav[cac++] = "-C"; 1262a67bf8dbSMatthew Dillon cav[cac++] = portpath; 1263*5d0718a8SMatthew Dillon cav[cac++] = localbase; 1264a67bf8dbSMatthew Dillon cav[cac++] = "-V_PERL5_FROM_BIN"; 1265a67bf8dbSMatthew Dillon 1266f9d29536SMatthew Dillon fp = dexec_open(portpath + strlen(DPortsPath) + 1, cav, cac, 1267f9d29536SMatthew Dillon &pid, NULL, 1, 1); 1268*5d0718a8SMatthew Dillon free(localbase); 1269a67bf8dbSMatthew Dillon free(portpath); 1270a67bf8dbSMatthew Dillon 1271a67bf8dbSMatthew Dillon line = 1; 1272a67bf8dbSMatthew Dillon while ((ptr = fgetln(fp, &len)) != NULL) { 1273a67bf8dbSMatthew Dillon if (len == 0 || ptr[len-1] != '\n') { 1274a67bf8dbSMatthew Dillon dfatal("Bad package info for %s/%s response line %d", 1275a67bf8dbSMatthew Dillon bulk->s1, bulk->s2, line); 1276a67bf8dbSMatthew Dillon } 1277a67bf8dbSMatthew Dillon ptr[--len] = 0; 1278a67bf8dbSMatthew Dillon 1279a67bf8dbSMatthew Dillon switch(line) { 1280a67bf8dbSMatthew Dillon case 1: /* _PERL5_FROM_BIN */ 1281a67bf8dbSMatthew Dillon addbuildenv("_PERL5_FROM_BIN", ptr, BENV_ENVIRONMENT); 1282a67bf8dbSMatthew Dillon break; 1283a67bf8dbSMatthew Dillon default: 1284a67bf8dbSMatthew Dillon printf("childOptimizeEnv: EXTRA LINE: %s\n", ptr); 1285a67bf8dbSMatthew Dillon break; 1286a67bf8dbSMatthew Dillon } 1287a67bf8dbSMatthew Dillon ++line; 1288a67bf8dbSMatthew Dillon } 1289a67bf8dbSMatthew Dillon if (line == 1) { 1290a67bf8dbSMatthew Dillon printf("DPort not found: %s/%s\n", bulk->s1, bulk->s2); 1291a67bf8dbSMatthew Dillon } else if (line != 1 + 1) { 1292a67bf8dbSMatthew Dillon printf("DPort corrupt: %s/%s\n", bulk->s1, bulk->s2); 1293a67bf8dbSMatthew Dillon } 1294a67bf8dbSMatthew Dillon if (dexec_close(fp, pid)) { 1295a67bf8dbSMatthew Dillon printf("childOptimizeEnv() failed\n"); 1296a67bf8dbSMatthew Dillon } 1297a67bf8dbSMatthew Dillon } 1298a67bf8dbSMatthew Dillon 12998e25f19bSMatthew Dillon static int 13008e25f19bSMatthew Dillon scan_and_queue_dir(const char *path, const char *level1, int level) 13018e25f19bSMatthew Dillon { 13028e25f19bSMatthew Dillon DIR *dir; 13038e25f19bSMatthew Dillon char *s1; 13048e25f19bSMatthew Dillon char *s2; 13058e25f19bSMatthew Dillon struct dirent *den; 13068e25f19bSMatthew Dillon struct stat st; 13078e25f19bSMatthew Dillon int count = 0; 13088e25f19bSMatthew Dillon 13098e25f19bSMatthew Dillon dir = opendir(path); 13108e25f19bSMatthew Dillon dassert(dir, "Cannot open dports path \"%s\"", path); 13118e25f19bSMatthew Dillon 13128e25f19bSMatthew Dillon while ((den = readdir(dir)) != NULL) { 13138e25f19bSMatthew Dillon if (den->d_namlen == 1 && den->d_name[0] == '.') 13148e25f19bSMatthew Dillon continue; 13158e25f19bSMatthew Dillon if (den->d_namlen == 2 && 13168e25f19bSMatthew Dillon den->d_name[0] == '.' && den->d_name[1] == '.') 13178e25f19bSMatthew Dillon continue; 13188e25f19bSMatthew Dillon asprintf(&s1, "%s/%s", path, den->d_name); 13198e25f19bSMatthew Dillon if (lstat(s1, &st) < 0 || !S_ISDIR(st.st_mode)) { 13208e25f19bSMatthew Dillon free(s1); 13218e25f19bSMatthew Dillon continue; 13228e25f19bSMatthew Dillon } 13238e25f19bSMatthew Dillon if (level == 1) { 13248e25f19bSMatthew Dillon count += scan_and_queue_dir(s1, den->d_name, 2); 13258e25f19bSMatthew Dillon free(s1); 13268e25f19bSMatthew Dillon continue; 13278e25f19bSMatthew Dillon } 13288e25f19bSMatthew Dillon asprintf(&s2, "%s/Makefile", s1); 13298e25f19bSMatthew Dillon if (lstat(s2, &st) == 0) { 13308e25f19bSMatthew Dillon queuebulk(level1, den->d_name, NULL, NULL); 13318e25f19bSMatthew Dillon ++count; 13328e25f19bSMatthew Dillon } 13338e25f19bSMatthew Dillon free(s1); 13348e25f19bSMatthew Dillon free(s2); 13358e25f19bSMatthew Dillon } 13368e25f19bSMatthew Dillon closedir(dir); 13378e25f19bSMatthew Dillon 13388e25f19bSMatthew Dillon return count; 13398e25f19bSMatthew Dillon } 13408e25f19bSMatthew Dillon 13418e25f19bSMatthew Dillon static int 13428e25f19bSMatthew Dillon scan_binary_repo(const char *path) 13438e25f19bSMatthew Dillon { 13448e25f19bSMatthew Dillon DIR *dir; 13458e25f19bSMatthew Dillon struct dirent *den; 13468e25f19bSMatthew Dillon int count; 13478e25f19bSMatthew Dillon 13488e25f19bSMatthew Dillon count = 0; 13498e25f19bSMatthew Dillon dir = opendir(path); 13508e25f19bSMatthew Dillon dassert(dir, "Cannot open repository path \"%s\"", path); 13518e25f19bSMatthew Dillon 13528d9409b8SMatthew Dillon /* 13538d9409b8SMatthew Dillon * NOTE: Test includes the '.' in the suffix. 13548d9409b8SMatthew Dillon */ 13558e25f19bSMatthew Dillon while ((den = readdir(dir)) != NULL) { 13568d6cd058SMatthew Dillon const char *suffix; 13578d6cd058SMatthew Dillon 13588d6cd058SMatthew Dillon suffix = strrchr(den->d_name, '.'); 13598d6cd058SMatthew Dillon if (suffix && suffix != den->d_name && 1360753e4c44SMatthew Dillon strcmp(suffix, UsePkgSufx) == 0) 1361753e4c44SMatthew Dillon { 1362753e4c44SMatthew Dillon queuebulk(den->d_name, NULL, NULL, NULL); 1363753e4c44SMatthew Dillon ++count; 1364753e4c44SMatthew Dillon } 1365753e4c44SMatthew Dillon 1366753e4c44SMatthew Dillon /* 1367753e4c44SMatthew Dillon * As of 1.17, pkg generates .pkg files. 1368753e4c44SMatthew Dillon */ 1369753e4c44SMatthew Dillon if (suffix && suffix != den->d_name && 1370753e4c44SMatthew Dillon strcmp(suffix, ".pkg") == 0) 1371753e4c44SMatthew Dillon { 13728e25f19bSMatthew Dillon queuebulk(den->d_name, NULL, NULL, NULL); 13738e25f19bSMatthew Dillon ++count; 13748e25f19bSMatthew Dillon } 13758e25f19bSMatthew Dillon } 13768e25f19bSMatthew Dillon closedir(dir); 13778e25f19bSMatthew Dillon 13788e25f19bSMatthew Dillon return count; 13798e25f19bSMatthew Dillon } 13808e25f19bSMatthew Dillon 13818e25f19bSMatthew Dillon #if 0 13828e25f19bSMatthew Dillon static void 13838e25f19bSMatthew Dillon pkgfree(pkg_t *pkg) 13848e25f19bSMatthew Dillon { 13858e25f19bSMatthew Dillon freestrp(&pkg->portdir); 13868e25f19bSMatthew Dillon freestrp(&pkg->version); 13878e25f19bSMatthew Dillon freestrp(&pkg->pkgfile); 13888e25f19bSMatthew Dillon freestrp(&pkg->ignore); 13898e25f19bSMatthew Dillon freestrp(&pkg->fetch_deps); 13908e25f19bSMatthew Dillon freestrp(&pkg->ext_deps); 13918e25f19bSMatthew Dillon freestrp(&pkg->patch_deps); 13928e25f19bSMatthew Dillon freestrp(&pkg->build_deps); 13938e25f19bSMatthew Dillon freestrp(&pkg->lib_deps); 13948e25f19bSMatthew Dillon freestrp(&pkg->run_deps); 13958e25f19bSMatthew Dillon freestrp(&pkg->pos_options); 13968e25f19bSMatthew Dillon freestrp(&pkg->neg_options); 13978e25f19bSMatthew Dillon freestrp(&pkg->flavors); 13988e25f19bSMatthew Dillon free(pkg); 13998e25f19bSMatthew Dillon } 14008e25f19bSMatthew Dillon #endif 1401