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 *
allocpkg(void)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
pkghash(const char * str)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 *
deptype2str(int dep_type)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
pkg_enter(pkg_t * pkg)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 *
pkg_find(const char * match)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 *
ParsePackageList(int n,char ** ary,int debugstop)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
parsepkglist_file(const char * path,int debugstop)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 *
GetLocalPackageList(void)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 *
GetFullPackageList(void)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 *
processPackageListBulk(int total)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 {
532*2c5f241eSMatthew Dillon if (ForceOpt) {
533*2c5f241eSMatthew Dillon remove_corrupt = 1;
534*2c5f241eSMatthew Dillon printf("continuing despite pkglist "
535*2c5f241eSMatthew Dillon "errors (-f)\n");
536*2c5f241eSMatthew Dillon } else {
537eea2aa9aSMatthew Dillon printf("unable to continue, aborting\n");
538eea2aa9aSMatthew Dillon }
539*2c5f241eSMatthew Dillon }
540eea2aa9aSMatthew Dillon if (remove_corrupt == 0)
541927e4e3eSMatthew Dillon exit(1);
542927e4e3eSMatthew Dillon }
543927e4e3eSMatthew Dillon
544927e4e3eSMatthew Dillon /*
545eea2aa9aSMatthew Dillon * Remove corrupt packages before continuing
546eea2aa9aSMatthew Dillon */
547eea2aa9aSMatthew Dillon if (remove_corrupt) {
548eea2aa9aSMatthew Dillon list_tail = &list;
549eea2aa9aSMatthew Dillon while ((scan = *list_tail) != NULL) {
550eea2aa9aSMatthew Dillon if (scan->flags & PKGF_CORRUPT)
551eea2aa9aSMatthew Dillon *list_tail = scan->bnext;
552eea2aa9aSMatthew Dillon else
553eea2aa9aSMatthew Dillon list_tail = &scan->bnext;
554eea2aa9aSMatthew Dillon }
555eea2aa9aSMatthew Dillon }
556eea2aa9aSMatthew Dillon
557eea2aa9aSMatthew Dillon /*
5588e25f19bSMatthew Dillon * Scan our binary distributions and related dependencies looking
5598e25f19bSMatthew Dillon * for any packages that have already been built.
5608e25f19bSMatthew Dillon */
5618e25f19bSMatthew Dillon initbulk(childGetBinaryDistInfo, MaxBulk);
5628e25f19bSMatthew Dillon total = scan_binary_repo(RepositoryPath);
5638e25f19bSMatthew Dillon count = 0;
5648e25f19bSMatthew Dillon printf("Scanning %d packages\n", total);
5658e25f19bSMatthew Dillon
5668e25f19bSMatthew Dillon while ((bulk = getbulk()) != NULL) {
5678e25f19bSMatthew Dillon ++count;
5688e25f19bSMatthew Dillon if ((count & 255) == 0) {
5698e25f19bSMatthew Dillon printf("%6.2f%%\r",
5708e25f19bSMatthew Dillon (double)count * 100.0 / (double)total + 0.001);
5718e25f19bSMatthew Dillon fflush(stdout);
5728e25f19bSMatthew Dillon }
5738e25f19bSMatthew Dillon freebulk(bulk);
5748e25f19bSMatthew Dillon }
5751645cafeSMatthew Dillon printf("100.00%%\n");
5768e25f19bSMatthew Dillon printf("\nTotal %d\n", count);
5778e25f19bSMatthew Dillon fflush(stdout);
5788e25f19bSMatthew Dillon donebulk();
5798e25f19bSMatthew Dillon
5808e25f19bSMatthew Dillon printf("all done\n");
5818e25f19bSMatthew Dillon
5828e25f19bSMatthew Dillon return list;
5838e25f19bSMatthew Dillon }
5848e25f19bSMatthew Dillon
5858e25f19bSMatthew Dillon pkg_t *
GetPkgPkg(pkg_t ** listp)586549987f1SMatthew Dillon GetPkgPkg(pkg_t **listp)
5878e25f19bSMatthew Dillon {
5888e25f19bSMatthew Dillon bulk_t *bulk;
5898e25f19bSMatthew Dillon pkg_t *scan;
590549987f1SMatthew Dillon pkg_t *s2;
5918e25f19bSMatthew Dillon
592549987f1SMatthew Dillon for (scan = *listp; scan; scan = scan->bnext) {
5938e25f19bSMatthew Dillon if (strcmp(scan->portdir, "ports-mgmt/pkg") == 0)
5948e25f19bSMatthew Dillon return scan;
5958e25f19bSMatthew Dillon }
5968e25f19bSMatthew Dillon
597f4094b20SMatthew Dillon /*
598f4094b20SMatthew Dillon * This will force pkg to be built, but generally this code
599f4094b20SMatthew Dillon * is not reached because the package list processing code
600f4094b20SMatthew Dillon * adds ports-mgmt/pkg unconditionally.
601f4094b20SMatthew Dillon */
6028e25f19bSMatthew Dillon initbulk(childGetPackageInfo, MaxBulk);
603f4094b20SMatthew Dillon queuebulk("ports-mgmt", "pkg", NULL, "x");
6048e25f19bSMatthew Dillon bulk = getbulk();
6058e25f19bSMatthew Dillon dassert(bulk, "Cannot find ports-mgmt/pkg");
6068e25f19bSMatthew Dillon scan = bulk->list;
6078e25f19bSMatthew Dillon bulk->list = NULL;
6088e25f19bSMatthew Dillon freebulk(bulk);
6098e25f19bSMatthew Dillon donebulk();
6108e25f19bSMatthew Dillon
611549987f1SMatthew Dillon
612549987f1SMatthew Dillon /*
613549987f1SMatthew Dillon * Include added packages to the total and add the initial bulk
614549987f1SMatthew Dillon * built packages to the list so they get counted.
615549987f1SMatthew Dillon */
616549987f1SMatthew Dillon for (s2 = scan; s2->bnext; s2 = s2->bnext)
617549987f1SMatthew Dillon ++BuildTotal;
618549987f1SMatthew Dillon for (s2 = scan; s2->bnext; s2 = s2->bnext)
619549987f1SMatthew Dillon ;
620549987f1SMatthew Dillon s2->bnext = *listp;
621549987f1SMatthew Dillon *listp = scan;
622549987f1SMatthew Dillon ++BuildTotal;
623549987f1SMatthew Dillon
6248e25f19bSMatthew Dillon return scan;
6258e25f19bSMatthew Dillon }
6268e25f19bSMatthew Dillon
6278e25f19bSMatthew Dillon /*
628a67bf8dbSMatthew Dillon * Try to optimize the environment by supplying information that
629a67bf8dbSMatthew Dillon * the ports system would generally have to run stuff to get on
630a67bf8dbSMatthew Dillon * every package.
631a67bf8dbSMatthew Dillon *
632a67bf8dbSMatthew Dillon * See childOptimizeEnv() for the actual handling. We execute
633a67bf8dbSMatthew Dillon * a single make -V... -V... for ports-mgmt/pkg from within the
634a67bf8dbSMatthew Dillon * bulk system (which handles the environment and disables
635a67bf8dbSMatthew Dillon * /etc/make.conf), and we then call addbuildenv() as appropriate.
636a67bf8dbSMatthew Dillon *
637a67bf8dbSMatthew Dillon * _PERL5_FROM_BIN
638a67bf8dbSMatthew Dillon * add others...
639a67bf8dbSMatthew Dillon */
640a67bf8dbSMatthew Dillon void
OptimizeEnv(void)641a67bf8dbSMatthew Dillon OptimizeEnv(void)
642a67bf8dbSMatthew Dillon {
643a67bf8dbSMatthew Dillon bulk_t *bulk;
644a67bf8dbSMatthew Dillon
645a67bf8dbSMatthew Dillon initbulk(childOptimizeEnv, MaxBulk);
646a67bf8dbSMatthew Dillon queuebulk("ports-mgmt", "pkg", NULL, NULL);
647a67bf8dbSMatthew Dillon bulk = getbulk();
648a67bf8dbSMatthew Dillon freebulk(bulk);
649a67bf8dbSMatthew Dillon donebulk();
650a67bf8dbSMatthew Dillon }
651a67bf8dbSMatthew Dillon
652a67bf8dbSMatthew Dillon /*
6538e25f19bSMatthew Dillon * Run through the list resolving dependencies and constructing the topology
65477ac77e7SMatthew Dillon * linkages. This may append packages to the list. Dependencies to dummy
65577ac77e7SMatthew Dillon * nodes which do not specify a flavor do not need special handling, the
65677ac77e7SMatthew Dillon * search code in build.c will properly follow the first flavor.
6578e25f19bSMatthew Dillon */
6588e25f19bSMatthew Dillon static pkg_t *
resolveDeps(pkg_t * list,pkg_t *** list_tailp,int gentopo)6598e25f19bSMatthew Dillon resolveDeps(pkg_t *list, pkg_t ***list_tailp, int gentopo)
6608e25f19bSMatthew Dillon {
6618e25f19bSMatthew Dillon pkg_t *ret_list = NULL;
66277ac77e7SMatthew Dillon pkg_t *scan;
66377ac77e7SMatthew Dillon pkg_t *use;
6648e25f19bSMatthew Dillon bulk_t *bulk;
6658e25f19bSMatthew Dillon
6668e25f19bSMatthew Dillon for (scan = list; scan; scan = scan->bnext) {
66777ac77e7SMatthew Dillon use = pkg_find(scan->portdir);
66877ac77e7SMatthew Dillon resolveFlavors(use, scan->flavors, gentopo);
66977ac77e7SMatthew Dillon resolveDepString(use, scan->fetch_deps,
67063fcce5bSMatthew Dillon gentopo, DEP_TYPE_FETCH);
67177ac77e7SMatthew Dillon resolveDepString(use, scan->ext_deps,
67263fcce5bSMatthew Dillon gentopo, DEP_TYPE_EXT);
67377ac77e7SMatthew Dillon resolveDepString(use, scan->patch_deps,
67463fcce5bSMatthew Dillon gentopo, DEP_TYPE_PATCH);
67577ac77e7SMatthew Dillon resolveDepString(use, scan->build_deps,
67663fcce5bSMatthew Dillon gentopo, DEP_TYPE_BUILD);
67777ac77e7SMatthew Dillon resolveDepString(use, scan->lib_deps,
67863fcce5bSMatthew Dillon gentopo, DEP_TYPE_LIB);
67977ac77e7SMatthew Dillon resolveDepString(use, scan->run_deps,
68063fcce5bSMatthew Dillon gentopo, DEP_TYPE_RUN);
6818e25f19bSMatthew Dillon }
6828e25f19bSMatthew Dillon
6838e25f19bSMatthew Dillon /*
6848e25f19bSMatthew Dillon * No bulk ops are queued when doing the final topology
6858e25f19bSMatthew Dillon * generation.
68677ac77e7SMatthew Dillon *
68777ac77e7SMatthew Dillon * Avoid entering duplicate results from the bulk ops. Duplicate
68877ac77e7SMatthew Dillon * results are mostly filtered out, but not always. A dummy node
68977ac77e7SMatthew Dillon * representing multiple flavors will parse-out the flavors
6908e25f19bSMatthew Dillon */
6918e25f19bSMatthew Dillon if (gentopo)
6928e25f19bSMatthew Dillon return NULL;
6938e25f19bSMatthew Dillon while ((bulk = getbulk()) != NULL) {
6948e25f19bSMatthew Dillon if (bulk->list) {
6958e25f19bSMatthew Dillon if (ret_list == NULL)
6968e25f19bSMatthew Dillon ret_list = bulk->list;
6978e25f19bSMatthew Dillon **list_tailp = bulk->list;
6988e25f19bSMatthew Dillon bulk->list = NULL;
69977ac77e7SMatthew Dillon while ((scan = **list_tailp) != NULL) {
70077ac77e7SMatthew Dillon pkg_enter(scan);
70177ac77e7SMatthew Dillon *list_tailp = &scan->bnext;
7028e25f19bSMatthew Dillon }
7038e25f19bSMatthew Dillon }
7048e25f19bSMatthew Dillon freebulk(bulk);
7058e25f19bSMatthew Dillon }
7068e25f19bSMatthew Dillon return (ret_list);
7078e25f19bSMatthew Dillon }
7088e25f19bSMatthew Dillon
70977ac77e7SMatthew Dillon /*
71077ac77e7SMatthew Dillon * Resolve a generic node that has flavors, queue to retrieve info for
71177ac77e7SMatthew Dillon * each flavor and setup linkages as appropriate.
71277ac77e7SMatthew Dillon */
71377ac77e7SMatthew Dillon static void
resolveFlavors(pkg_t * pkg,char * flavors,int gentopo)71477ac77e7SMatthew Dillon resolveFlavors(pkg_t *pkg, char *flavors, int gentopo)
71577ac77e7SMatthew Dillon {
71677ac77e7SMatthew Dillon char *flavor_base;
71777ac77e7SMatthew Dillon char *flavor_scan;
71877ac77e7SMatthew Dillon char *flavor;
71977ac77e7SMatthew Dillon char *portdir;
72077ac77e7SMatthew Dillon char *s1;
72177ac77e7SMatthew Dillon char *s2;
72277ac77e7SMatthew Dillon pkg_t *dpkg;
72377ac77e7SMatthew Dillon pkglink_t *link;
72477ac77e7SMatthew Dillon
72577ac77e7SMatthew Dillon if ((pkg->flags & PKGF_DUMMY) == 0)
72677ac77e7SMatthew Dillon return;
72777ac77e7SMatthew Dillon if (pkg->flavors == NULL || pkg->flavors[0] == 0)
72877ac77e7SMatthew Dillon return;
72977ac77e7SMatthew Dillon flavor_base = strdup(flavors);
73077ac77e7SMatthew Dillon flavor_scan = flavor_base;
73177ac77e7SMatthew Dillon
73277ac77e7SMatthew Dillon for (;;) {
73377ac77e7SMatthew Dillon do {
73477ac77e7SMatthew Dillon flavor = strsep(&flavor_scan, " \t");
73577ac77e7SMatthew Dillon } while (flavor && *flavor == 0);
73677ac77e7SMatthew Dillon if (flavor == NULL)
73777ac77e7SMatthew Dillon break;
73877ac77e7SMatthew Dillon
73977ac77e7SMatthew Dillon /*
74077ac77e7SMatthew Dillon * Iterate each flavor generating "s1/s2@flavor".
74177ac77e7SMatthew Dillon *
74277ac77e7SMatthew Dillon * queuebulk() info for each flavor, and set-up the
74377ac77e7SMatthew Dillon * linkages in the topology generation pass.
74477ac77e7SMatthew Dillon */
74577ac77e7SMatthew Dillon asprintf(&portdir, "%s@%s", pkg->portdir, flavor);
74677ac77e7SMatthew Dillon s1 = strdup(pkg->portdir);
74777ac77e7SMatthew Dillon s2 = strchr(s1, '/');
74877ac77e7SMatthew Dillon *s2++ = 0;
74977ac77e7SMatthew Dillon
75077ac77e7SMatthew Dillon dpkg = pkg_find(portdir);
75177ac77e7SMatthew Dillon if (dpkg && gentopo) {
75277ac77e7SMatthew Dillon /*
75377ac77e7SMatthew Dillon * Setup linkages
75477ac77e7SMatthew Dillon */
75577ac77e7SMatthew Dillon free(portdir);
75677ac77e7SMatthew Dillon
75777ac77e7SMatthew Dillon link = calloc(1, sizeof(*link));
75877ac77e7SMatthew Dillon link->pkg = dpkg;
75977ac77e7SMatthew Dillon link->next = &pkg->idepon_list;
76077ac77e7SMatthew Dillon link->prev = pkg->idepon_list.prev;
76177ac77e7SMatthew Dillon link->next->prev = link;
76277ac77e7SMatthew Dillon link->prev->next = link;
76377ac77e7SMatthew Dillon link->dep_type = DEP_TYPE_BUILD;
76477ac77e7SMatthew Dillon
76577ac77e7SMatthew Dillon link = calloc(1, sizeof(*link));
76677ac77e7SMatthew Dillon link->pkg = pkg;
76777ac77e7SMatthew Dillon link->next = &dpkg->deponi_list;
76877ac77e7SMatthew Dillon link->prev = dpkg->deponi_list.prev;
76977ac77e7SMatthew Dillon link->next->prev = link;
77077ac77e7SMatthew Dillon link->prev->next = link;
77177ac77e7SMatthew Dillon link->dep_type = DEP_TYPE_BUILD;
77277ac77e7SMatthew Dillon ++dpkg->depi_count;
77377ac77e7SMatthew Dillon } else if (gentopo == 0 && dpkg == NULL) {
77477ac77e7SMatthew Dillon /*
77577ac77e7SMatthew Dillon * Use a place-holder to prevent duplicate
77677ac77e7SMatthew Dillon * dependencies from being processed. The placeholder
77777ac77e7SMatthew Dillon * will be replaced by the actual dependency.
77877ac77e7SMatthew Dillon */
77977ac77e7SMatthew Dillon dpkg = allocpkg();
78077ac77e7SMatthew Dillon dpkg->portdir = portdir;
78177ac77e7SMatthew Dillon dpkg->flags = PKGF_PLACEHOLD;
78277ac77e7SMatthew Dillon pkg_enter(dpkg);
78377ac77e7SMatthew Dillon queuebulk(s1, s2, flavor, NULL);
78477ac77e7SMatthew Dillon }
78577ac77e7SMatthew Dillon free(s1);
78677ac77e7SMatthew Dillon }
78777ac77e7SMatthew Dillon free(flavor_base);
78877ac77e7SMatthew Dillon }
78977ac77e7SMatthew Dillon
7908e25f19bSMatthew Dillon static void
resolveDepString(pkg_t * pkg,char * depstr,int gentopo,int dep_type)79163fcce5bSMatthew Dillon resolveDepString(pkg_t *pkg, char *depstr, int gentopo, int dep_type)
7928e25f19bSMatthew Dillon {
7938e25f19bSMatthew Dillon char *copy_base;
7948e25f19bSMatthew Dillon char *copy;
7958e25f19bSMatthew Dillon char *dep;
79624b60d12SMatthew Dillon char *log_component;
7978e25f19bSMatthew Dillon char *sep;
7988e25f19bSMatthew Dillon char *tag;
7998e25f19bSMatthew Dillon char *flavor;
8008e25f19bSMatthew Dillon pkg_t *dpkg;
8018e25f19bSMatthew Dillon
8028e25f19bSMatthew Dillon if (depstr == NULL || depstr[0] == 0)
8038e25f19bSMatthew Dillon return;
8048e25f19bSMatthew Dillon
8058e25f19bSMatthew Dillon copy_base = strdup(depstr);
8068e25f19bSMatthew Dillon copy = copy_base;
80724b60d12SMatthew Dillon log_component = copy;
8088e25f19bSMatthew Dillon
8098e25f19bSMatthew Dillon for (;;) {
8108e25f19bSMatthew Dillon do {
8118e25f19bSMatthew Dillon dep = strsep(©, " \t");
8128e25f19bSMatthew Dillon } while (dep && *dep == 0);
8138e25f19bSMatthew Dillon if (dep == NULL)
8148e25f19bSMatthew Dillon break;
8156fd67931SMatthew Dillon
8166fd67931SMatthew Dillon /*
8176fd67931SMatthew Dillon * Ignore dependencies prefixed with ${NONEXISTENT}
8186fd67931SMatthew Dillon */
8196fd67931SMatthew Dillon if (strncmp(dep, "/nonexistent:", 13) == 0)
8206fd67931SMatthew Dillon continue;
8216fd67931SMatthew Dillon
82224b60d12SMatthew Dillon log_component = dep;
8238e25f19bSMatthew Dillon dep = strchr(dep, ':');
8248e25f19bSMatthew Dillon if (dep == NULL || *dep != ':') {
82593fe0327SMatthew Dillon printf("Error parsing %s dependency for "
82624b60d12SMatthew Dillon "%s: '%s' at index %zd '%s' "
82724b60d12SMatthew Dillon "(looking for ':')\n",
82893fe0327SMatthew Dillon deptype2str(dep_type),
829baf7c614SMatthew Dillon pkg->portdir, depstr,
83024b60d12SMatthew Dillon log_component - copy_base,
83124b60d12SMatthew Dillon log_component);
8328e25f19bSMatthew Dillon continue;
8338e25f19bSMatthew Dillon }
8348e25f19bSMatthew Dillon ++dep;
8358e25f19bSMatthew Dillon
8368e25f19bSMatthew Dillon /*
8378e25f19bSMatthew Dillon * Strip-off any DPortsPath prefix. EXTRACT_DEPENDS
8388e25f19bSMatthew Dillon * often (always?) generates this prefix.
8398e25f19bSMatthew Dillon */
8408e25f19bSMatthew Dillon if (strncmp(dep, DPortsPath, strlen(DPortsPath)) == 0) {
8418e25f19bSMatthew Dillon dep += strlen(DPortsPath);
8428e25f19bSMatthew Dillon if (*dep == '/')
8438e25f19bSMatthew Dillon ++dep;
8448e25f19bSMatthew Dillon }
8458e25f19bSMatthew Dillon
8468e25f19bSMatthew Dillon /*
8478e25f19bSMatthew Dillon * Strip-off any tag (such as :patch). We don't try to
8488e25f19bSMatthew Dillon * organize dependencies at this fine a grain (for now).
8498e25f19bSMatthew Dillon */
8508e25f19bSMatthew Dillon tag = strchr(dep, ':');
8518e25f19bSMatthew Dillon if (tag)
8528e25f19bSMatthew Dillon *tag++ = 0;
85324b60d12SMatthew Dillon log_component = dep;
8548e25f19bSMatthew Dillon
8558e25f19bSMatthew Dillon /*
8568e25f19bSMatthew Dillon * Locate the dependency
8578e25f19bSMatthew Dillon */
8588e25f19bSMatthew Dillon if ((dpkg = pkg_find(dep)) != NULL) {
8598e25f19bSMatthew Dillon if (gentopo) {
8608e25f19bSMatthew Dillon pkglink_t *link;
8618e25f19bSMatthew Dillon
8628e25f19bSMatthew Dillon /*
8638e25f19bSMatthew Dillon * NOTE: idep_count is calculated recursively
8648e25f19bSMatthew Dillon * at build-time
8658e25f19bSMatthew Dillon */
8668e25f19bSMatthew Dillon ddprintf(0, "Add Dependency %s -> %s\n",
8678e25f19bSMatthew Dillon pkg->portdir, dpkg->portdir);
8688e25f19bSMatthew Dillon link = calloc(1, sizeof(*link));
8698e25f19bSMatthew Dillon link->pkg = dpkg;
8708e25f19bSMatthew Dillon link->next = &pkg->idepon_list;
8718e25f19bSMatthew Dillon link->prev = pkg->idepon_list.prev;
8728e25f19bSMatthew Dillon link->next->prev = link;
8738e25f19bSMatthew Dillon link->prev->next = link;
87463fcce5bSMatthew Dillon link->dep_type = dep_type;
8758e25f19bSMatthew Dillon
8768e25f19bSMatthew Dillon link = calloc(1, sizeof(*link));
8778e25f19bSMatthew Dillon link->pkg = pkg;
8788e25f19bSMatthew Dillon link->next = &dpkg->deponi_list;
8798e25f19bSMatthew Dillon link->prev = dpkg->deponi_list.prev;
8808e25f19bSMatthew Dillon link->next->prev = link;
8818e25f19bSMatthew Dillon link->prev->next = link;
88263fcce5bSMatthew Dillon link->dep_type = dep_type;
8838e25f19bSMatthew Dillon ++dpkg->depi_count;
8848e25f19bSMatthew Dillon }
8858e25f19bSMatthew Dillon continue;
8868e25f19bSMatthew Dillon }
8878e25f19bSMatthew Dillon
8888e25f19bSMatthew Dillon /*
8898e25f19bSMatthew Dillon * This shouldn't happen because we already took a first
8908e25f19bSMatthew Dillon * pass and should have generated the pkgs.
8918e25f19bSMatthew Dillon */
8928e25f19bSMatthew Dillon if (gentopo) {
8938e25f19bSMatthew Dillon printf("Topology Generate failed for %s: %s\n",
8948e25f19bSMatthew Dillon pkg->portdir, copy_base);
8958e25f19bSMatthew Dillon continue;
8968e25f19bSMatthew Dillon }
8978e25f19bSMatthew Dillon
8988e25f19bSMatthew Dillon /*
8998e25f19bSMatthew Dillon * Separate out the two dports directory components and
9008e25f19bSMatthew Dillon * extract the optional '@flavor' specification.
9018e25f19bSMatthew Dillon */
9028e25f19bSMatthew Dillon sep = strchr(dep, '/');
9038e25f19bSMatthew Dillon if (sep == NULL) {
90493fe0327SMatthew Dillon printf("Error parsing %s dependency for "
90524b60d12SMatthew Dillon "%s: '%s' at index %zd '%s' "
90624b60d12SMatthew Dillon "(looking for '/')\n",
90793fe0327SMatthew Dillon deptype2str(dep_type),
908baf7c614SMatthew Dillon pkg->portdir, depstr,
90924b60d12SMatthew Dillon log_component - copy_base,
91024b60d12SMatthew Dillon log_component);
9118e25f19bSMatthew Dillon continue;
9128e25f19bSMatthew Dillon }
9138e25f19bSMatthew Dillon *sep++ = 0;
9148e25f19bSMatthew Dillon
91595f08ce8SMatthew Dillon /*
91695f08ce8SMatthew Dillon * The flavor hangs off the separator, not the tag
91795f08ce8SMatthew Dillon */
91895f08ce8SMatthew Dillon flavor = strrchr(sep, '@');
91995f08ce8SMatthew Dillon #if 0
9208e25f19bSMatthew Dillon if (tag)
9218e25f19bSMatthew Dillon flavor = strrchr(tag, '@');
9228e25f19bSMatthew Dillon else
9238e25f19bSMatthew Dillon flavor = strrchr(sep, '@');
92495f08ce8SMatthew Dillon #endif
9258e25f19bSMatthew Dillon if (flavor)
9268e25f19bSMatthew Dillon *flavor++ = 0;
9278e25f19bSMatthew Dillon
9288e25f19bSMatthew Dillon if (flavor)
9298e25f19bSMatthew Dillon ddprintf(0, "QUEUE DEPENDENCY FROM PKG %s: %s/%s@%s\n",
9308e25f19bSMatthew Dillon pkg->portdir, dep, sep, flavor);
9318e25f19bSMatthew Dillon else
9328e25f19bSMatthew Dillon ddprintf(0, "QUEUE DEPENDENCY FROM PKG %s: %s/%s\n",
9338e25f19bSMatthew Dillon pkg->portdir, dep, sep);
9348e25f19bSMatthew Dillon
9358e25f19bSMatthew Dillon /*
9368e25f19bSMatthew Dillon * Use a place-holder to prevent duplicate dependencies from
9378e25f19bSMatthew Dillon * being processed. The placeholder will be replaced by
9388e25f19bSMatthew Dillon * the actual dependency.
9398e25f19bSMatthew Dillon */
9408e25f19bSMatthew Dillon dpkg = allocpkg();
9418e25f19bSMatthew Dillon if (flavor)
9428e25f19bSMatthew Dillon asprintf(&dpkg->portdir, "%s/%s@%s", dep, sep, flavor);
9438e25f19bSMatthew Dillon else
9448e25f19bSMatthew Dillon asprintf(&dpkg->portdir, "%s/%s", dep, sep);
9458e25f19bSMatthew Dillon dpkg->flags = PKGF_PLACEHOLD;
9468e25f19bSMatthew Dillon pkg_enter(dpkg);
9478e25f19bSMatthew Dillon
9488e25f19bSMatthew Dillon queuebulk(dep, sep, flavor, NULL);
9498e25f19bSMatthew Dillon }
9508e25f19bSMatthew Dillon free(copy_base);
9518e25f19bSMatthew Dillon }
9528e25f19bSMatthew Dillon
9538e25f19bSMatthew Dillon void
FreePackageList(pkg_t * pkgs __unused)9548e25f19bSMatthew Dillon FreePackageList(pkg_t *pkgs __unused)
9558e25f19bSMatthew Dillon {
9568e25f19bSMatthew Dillon dfatal("not implemented");
9578e25f19bSMatthew Dillon }
9588e25f19bSMatthew Dillon
9598e25f19bSMatthew Dillon /*
9608e25f19bSMatthew Dillon * Scan some or all dports to allocate the related pkg structure. Dependencies
9618e25f19bSMatthew Dillon * are stored but not processed.
9628e25f19bSMatthew Dillon *
9638e25f19bSMatthew Dillon * Threaded function
9648e25f19bSMatthew Dillon */
9658e25f19bSMatthew Dillon static void
childGetPackageInfo(bulk_t * bulk)9668e25f19bSMatthew Dillon childGetPackageInfo(bulk_t *bulk)
9678e25f19bSMatthew Dillon {
9688e25f19bSMatthew Dillon pkg_t *pkg;
9698e25f19bSMatthew Dillon char *flavor;
9708e25f19bSMatthew Dillon char *ptr;
9718e25f19bSMatthew Dillon FILE *fp;
9728e25f19bSMatthew Dillon int line;
9738e25f19bSMatthew Dillon size_t len;
9746fd67931SMatthew Dillon char *portpath;
9756fd67931SMatthew Dillon char *flavarg;
9765d0718a8SMatthew Dillon char *localbase;
9776fd67931SMatthew Dillon const char *cav[MAXCAC];
9786fd67931SMatthew Dillon pid_t pid;
9796fd67931SMatthew Dillon int cac;
9808e25f19bSMatthew Dillon
9818e25f19bSMatthew Dillon /*
9828e25f19bSMatthew Dillon * If the package has flavors we will loop on each one. If a flavor
9838e25f19bSMatthew Dillon * is not passed in s3 we will loop on all flavors, otherwise we will
9848e25f19bSMatthew Dillon * only process the passed-in flavor.
9858e25f19bSMatthew Dillon */
9868e25f19bSMatthew Dillon flavor = bulk->s3; /* usually NULL */
9878e25f19bSMatthew Dillon
9888e25f19bSMatthew Dillon bulk->list = NULL;
98977ac77e7SMatthew Dillon
9906fd67931SMatthew Dillon asprintf(&portpath, "%s/%s/%s", DPortsPath, bulk->s1, bulk->s2);
9916fd67931SMatthew Dillon if (flavor)
9926fd67931SMatthew Dillon asprintf(&flavarg, "FLAVOR=%s", flavor);
9936fd67931SMatthew Dillon else
9946fd67931SMatthew Dillon flavarg = NULL;
9956fd67931SMatthew Dillon
9966fd67931SMatthew Dillon cac = 0;
9976fd67931SMatthew Dillon cav[cac++] = MAKE_BINARY;
9986fd67931SMatthew Dillon cav[cac++] = "-C";
9996fd67931SMatthew Dillon cav[cac++] = portpath;
10006fd67931SMatthew Dillon if (flavarg)
10016fd67931SMatthew Dillon cav[cac++] = flavarg;
10025d0718a8SMatthew Dillon
10035d0718a8SMatthew Dillon /*
10045d0718a8SMatthew Dillon * Prevent postgresql, mysql, and other package Makefile tests
10055d0718a8SMatthew Dillon * from accessing the host system's /usr/local by setting LOCALBASE
10065d0718a8SMatthew Dillon * to an empty directory.
10075d0718a8SMatthew Dillon */
10085d0718a8SMatthew Dillon asprintf(&localbase, "LOCALBASE=%s/empty", BuildBase);
10095d0718a8SMatthew Dillon cav[cac++] = localbase;
10105d0718a8SMatthew Dillon
10115d0718a8SMatthew Dillon /*
10125d0718a8SMatthew Dillon * Variables we need to retrieve (order is specific to the switch
10135d0718a8SMatthew Dillon * below)
10145d0718a8SMatthew Dillon */
10156fd67931SMatthew Dillon cav[cac++] = "-VPKGVERSION";
10166fd67931SMatthew Dillon cav[cac++] = "-VPKGFILE:T";
10176ec1f604SMatthew Dillon cav[cac++] = "-VALLFILES";
10186fd67931SMatthew Dillon cav[cac++] = "-VDIST_SUBDIR";
10196fd67931SMatthew Dillon cav[cac++] = "-VMAKE_JOBS_NUMBER";
10206fd67931SMatthew Dillon cav[cac++] = "-VIGNORE";
10216fd67931SMatthew Dillon cav[cac++] = "-VFETCH_DEPENDS";
10226fd67931SMatthew Dillon cav[cac++] = "-VEXTRACT_DEPENDS";
10236fd67931SMatthew Dillon cav[cac++] = "-VPATCH_DEPENDS";
10246fd67931SMatthew Dillon cav[cac++] = "-VBUILD_DEPENDS";
10256fd67931SMatthew Dillon cav[cac++] = "-VLIB_DEPENDS";
10266fd67931SMatthew Dillon cav[cac++] = "-VRUN_DEPENDS";
10276fd67931SMatthew Dillon cav[cac++] = "-VSELECTED_OPTIONS";
10286fd67931SMatthew Dillon cav[cac++] = "-VDESELECTED_OPTIONS";
10296fd67931SMatthew Dillon cav[cac++] = "-VUSE_LINUX";
10306fd67931SMatthew Dillon cav[cac++] = "-VFLAVORS";
1031f4094b20SMatthew Dillon cav[cac++] = "-VUSES";
10326fd67931SMatthew Dillon
1033f9d29536SMatthew Dillon fp = dexec_open(portpath + strlen(DPortsPath) + 1, cav, cac,
1034f9d29536SMatthew Dillon &pid, NULL, 1, 1);
10356fd67931SMatthew Dillon freestrp(&flavarg);
10365d0718a8SMatthew Dillon freestrp(&localbase);
10378e25f19bSMatthew Dillon
10388e25f19bSMatthew Dillon pkg = allocpkg();
10398e25f19bSMatthew Dillon if (flavor)
10408e25f19bSMatthew Dillon asprintf(&pkg->portdir, "%s/%s@%s", bulk->s1, bulk->s2, flavor);
10418e25f19bSMatthew Dillon else
10428e25f19bSMatthew Dillon asprintf(&pkg->portdir, "%s/%s", bulk->s1, bulk->s2);
10438e25f19bSMatthew Dillon
10446fd67931SMatthew Dillon line = 1;
10458e25f19bSMatthew Dillon while ((ptr = fgetln(fp, &len)) != NULL) {
10468e25f19bSMatthew Dillon if (len == 0 || ptr[len-1] != '\n') {
10478e25f19bSMatthew Dillon dfatal("Bad package info for %s/%s response line %d",
10488e25f19bSMatthew Dillon bulk->s1, bulk->s2, line);
10498e25f19bSMatthew Dillon }
10508e25f19bSMatthew Dillon ptr[--len] = 0;
10518e25f19bSMatthew Dillon
10528e25f19bSMatthew Dillon switch(line) {
10538e25f19bSMatthew Dillon case 1: /* PKGVERSION */
10548e25f19bSMatthew Dillon asprintf(&pkg->version, "%s", ptr);
10558e25f19bSMatthew Dillon break;
10568e25f19bSMatthew Dillon case 2: /* PKGFILE */
10578e25f19bSMatthew Dillon asprintf(&pkg->pkgfile, "%s", ptr);
10588e25f19bSMatthew Dillon break;
10596ec1f604SMatthew Dillon case 3: /* ALLFILES (aka DISTFILES + patch files) */
10601645cafeSMatthew Dillon asprintf(&pkg->distfiles, "%s", ptr);
10611645cafeSMatthew Dillon break;
10621645cafeSMatthew Dillon case 4: /* DIST_SUBDIR */
10634ea2ee4dSMatthew Dillon pkg->distsubdir = strdup_or_null(ptr);
10641645cafeSMatthew Dillon break;
10651645cafeSMatthew Dillon case 5: /* MAKE_JOBS_NUMBER */
10668e25f19bSMatthew Dillon pkg->make_jobs_number = strtol(ptr, NULL, 0);
10678e25f19bSMatthew Dillon break;
10681645cafeSMatthew Dillon case 6: /* IGNORE */
10694ea2ee4dSMatthew Dillon pkg->ignore = strdup_or_null(ptr);
10708e25f19bSMatthew Dillon break;
10711645cafeSMatthew Dillon case 7: /* FETCH_DEPENDS */
10724ea2ee4dSMatthew Dillon pkg->fetch_deps = strdup_or_null(ptr);
10738e25f19bSMatthew Dillon break;
10741645cafeSMatthew Dillon case 8: /* EXTRACT_DEPENDS */
10754ea2ee4dSMatthew Dillon pkg->ext_deps = strdup_or_null(ptr);
10768e25f19bSMatthew Dillon break;
10771645cafeSMatthew Dillon case 9: /* PATCH_DEPENDS */
10784ea2ee4dSMatthew Dillon pkg->patch_deps = strdup_or_null(ptr);
10798e25f19bSMatthew Dillon break;
10801645cafeSMatthew Dillon case 10: /* BUILD_DEPENDS */
10814ea2ee4dSMatthew Dillon pkg->build_deps = strdup_or_null(ptr);
10828e25f19bSMatthew Dillon break;
10831645cafeSMatthew Dillon case 11: /* LIB_DEPENDS */
10844ea2ee4dSMatthew Dillon pkg->lib_deps = strdup_or_null(ptr);
10858e25f19bSMatthew Dillon break;
10861645cafeSMatthew Dillon case 12: /* RUN_DEPENDS */
10874ea2ee4dSMatthew Dillon pkg->run_deps = strdup_or_null(ptr);
10888e25f19bSMatthew Dillon break;
10891645cafeSMatthew Dillon case 13: /* SELECTED_OPTIONS */
10904ea2ee4dSMatthew Dillon pkg->pos_options = strdup_or_null(ptr);
10918e25f19bSMatthew Dillon break;
10921645cafeSMatthew Dillon case 14: /* DESELECTED_OPTIONS */
10934ea2ee4dSMatthew Dillon pkg->neg_options = strdup_or_null(ptr);
10948e25f19bSMatthew Dillon break;
10951645cafeSMatthew Dillon case 15: /* USE_LINUX */
10968e25f19bSMatthew Dillon if (ptr[0])
10978e25f19bSMatthew Dillon pkg->use_linux = 1;
10988e25f19bSMatthew Dillon break;
10991645cafeSMatthew Dillon case 16: /* FLAVORS */
11008e25f19bSMatthew Dillon asprintf(&pkg->flavors, "%s", ptr);
11018e25f19bSMatthew Dillon break;
1102f4094b20SMatthew Dillon case 17: /* USES */
1103f4094b20SMatthew Dillon asprintf(&pkg->uses, "%s", ptr);
1104f4094b20SMatthew Dillon if (strstr(pkg->uses, "metaport"))
1105f4094b20SMatthew Dillon pkg->flags |= PKGF_META;
1106f4094b20SMatthew Dillon break;
11078e25f19bSMatthew Dillon default:
11088e25f19bSMatthew Dillon printf("EXTRA LINE: %s\n", ptr);
11098e25f19bSMatthew Dillon break;
11108e25f19bSMatthew Dillon }
11118e25f19bSMatthew Dillon ++line;
11128e25f19bSMatthew Dillon }
11138e25f19bSMatthew Dillon if (line == 1) {
11148e25f19bSMatthew Dillon printf("DPort not found: %s/%s\n", bulk->s1, bulk->s2);
11158e25f19bSMatthew Dillon pkg->flags |= PKGF_NOTFOUND;
1116f4094b20SMatthew Dillon } else if (line != 17 + 1) {
11178e25f19bSMatthew Dillon printf("DPort corrupt: %s/%s\n", bulk->s1, bulk->s2);
11188e25f19bSMatthew Dillon pkg->flags |= PKGF_CORRUPT;
11198e25f19bSMatthew Dillon }
11206fd67931SMatthew Dillon if (dexec_close(fp, pid)) {
11216fd67931SMatthew Dillon printf("make -V* command for %s/%s failed\n",
11226fd67931SMatthew Dillon bulk->s1, bulk->s2);
11236fd67931SMatthew Dillon pkg->flags |= PKGF_CORRUPT;
11246fd67931SMatthew Dillon }
11258e25f19bSMatthew Dillon ddassert(bulk->s1);
11268e25f19bSMatthew Dillon
11278e25f19bSMatthew Dillon /*
1128710838f7SMatthew Dillon * DEBUGSTOP mode
1129710838f7SMatthew Dillon */
1130710838f7SMatthew Dillon if (bulk->s4 && bulk->s4[0] == 'd')
1131710838f7SMatthew Dillon pkg->flags |= PKGF_DEBUGSTOP;
1132710838f7SMatthew Dillon
1133710838f7SMatthew Dillon /*
113477ac77e7SMatthew Dillon * Mark as a dummy node, the front-end will iterate the flavors
113577ac77e7SMatthew Dillon * and create sub-nodes for us.
11368e25f19bSMatthew Dillon *
113777ac77e7SMatthew Dillon * Get rid of elements returned that are for the first flavor.
113877ac77e7SMatthew Dillon * We are creating a dummy node here, not the node for the first
113977ac77e7SMatthew Dillon * flavor.
11408e25f19bSMatthew Dillon */
114177ac77e7SMatthew Dillon if (flavor == NULL && pkg->flavors && pkg->flavors[0]) {
11428e25f19bSMatthew Dillon pkg->flags |= PKGF_DUMMY;
11438e25f19bSMatthew Dillon freestrp(&pkg->fetch_deps);
11448e25f19bSMatthew Dillon freestrp(&pkg->ext_deps);
11458e25f19bSMatthew Dillon freestrp(&pkg->patch_deps);
11468e25f19bSMatthew Dillon freestrp(&pkg->build_deps);
11478e25f19bSMatthew Dillon freestrp(&pkg->lib_deps);
11488e25f19bSMatthew Dillon freestrp(&pkg->run_deps);
11498e25f19bSMatthew Dillon freestrp(&pkg->pkgfile);
11508e25f19bSMatthew Dillon }
11518e25f19bSMatthew Dillon
11528e25f19bSMatthew Dillon /*
1153b6bd007bSMatthew Dillon * Checksum the port directory tree. This just rollsup crcs of the
1154b6bd007bSMatthew Dillon * path names and a few stat fields (mtime, size) in order to detect
1155b6bd007bSMatthew Dillon * if any modification has been made to the port.
1156b6bd007bSMatthew Dillon */
1157b6bd007bSMatthew Dillon pkg->crc32 = crcDirTree(portpath);
1158b6bd007bSMatthew Dillon
1159b6bd007bSMatthew Dillon /*
116077ac77e7SMatthew Dillon * Only one pkg is put on the return list now. This code no
116177ac77e7SMatthew Dillon * longer creates pseudo-nodes for flavors (the frontend requests
116277ac77e7SMatthew Dillon * each flavor instead).
11638e25f19bSMatthew Dillon */
116477ac77e7SMatthew Dillon bulk->list = pkg;
1165b6bd007bSMatthew Dillon free(portpath);
11668e25f19bSMatthew Dillon }
11678e25f19bSMatthew Dillon
11688e25f19bSMatthew Dillon /*
11698e25f19bSMatthew Dillon * Query the package (at least to make sure it hasn't been truncated)
11708e25f19bSMatthew Dillon * and mark it as PACKAGED if found.
11718e25f19bSMatthew Dillon *
1172753e4c44SMatthew Dillon * This is a pre-req prior to doing builds, so we cannot assume that
1173753e4c44SMatthew Dillon * the template has its pkg-static binary yet.
1174753e4c44SMatthew Dillon *
11758e25f19bSMatthew Dillon * Threaded function
11768e25f19bSMatthew Dillon */
11778e25f19bSMatthew Dillon static void
childGetBinaryDistInfo(bulk_t * bulk)11788e25f19bSMatthew Dillon childGetBinaryDistInfo(bulk_t *bulk)
11798e25f19bSMatthew Dillon {
11808e25f19bSMatthew Dillon char *ptr;
11818e25f19bSMatthew Dillon FILE *fp;
11828e25f19bSMatthew Dillon size_t len;
11838e25f19bSMatthew Dillon pkg_t *pkg;
11846fd67931SMatthew Dillon const char *cav[MAXCAC];
11856fd67931SMatthew Dillon char *repopath;
11866fd67931SMatthew Dillon char buf[1024];
11876fd67931SMatthew Dillon pid_t pid;
11886fd67931SMatthew Dillon int cac;
1189dc46751bSMatthew Dillon int deleteme;
11908e25f19bSMatthew Dillon
11916fd67931SMatthew Dillon asprintf(&repopath, "%s/%s", RepositoryPath, bulk->s1);
11926fd67931SMatthew Dillon
11936fd67931SMatthew Dillon cac = 0;
11946fd67931SMatthew Dillon cav[cac++] = PKG_BINARY;
11956fd67931SMatthew Dillon cav[cac++] = "query";
11966fd67931SMatthew Dillon cav[cac++] = "-F";
11976fd67931SMatthew Dillon cav[cac++] = repopath;
11986fd67931SMatthew Dillon cav[cac++] = "%n-%v";
11996fd67931SMatthew Dillon
1200f9d29536SMatthew Dillon fp = dexec_open(NULL, cav, cac, &pid, NULL, 1, 0);
1201dc46751bSMatthew Dillon deleteme = DeleteObsoletePkgs;
12026fd67931SMatthew Dillon
12038e25f19bSMatthew Dillon while ((ptr = fgetln(fp, &len)) != NULL) {
12048e25f19bSMatthew Dillon if (len == 0 || ptr[len-1] != '\n')
12058e25f19bSMatthew Dillon continue;
12068e25f19bSMatthew Dillon ptr[len-1] = 0;
12078e25f19bSMatthew Dillon
1208753e4c44SMatthew Dillon /*
1209753e4c44SMatthew Dillon * As of pkg 1.17 the binary dist files use a .pkg suffix
1210753e4c44SMatthew Dillon * regardless of the compression format, so always check
1211753e4c44SMatthew Dillon * those.
1212753e4c44SMatthew Dillon */
1213753e4c44SMatthew Dillon snprintf(buf, sizeof(buf), "%s%s", ptr, ".pkg");
12148e25f19bSMatthew Dillon pkg = pkg_find(buf);
1215753e4c44SMatthew Dillon if (pkg == NULL) {
1216753e4c44SMatthew Dillon snprintf(buf, sizeof(buf), "%s%s", ptr, UsePkgSufx);
1217753e4c44SMatthew Dillon pkg = pkg_find(buf);
1218753e4c44SMatthew Dillon }
12198d9409b8SMatthew Dillon if (pkg) {
1220325ef124SMatthew Dillon if (FetchOnlyOpt) {
1221325ef124SMatthew Dillon ddprintf(0, "Note: Package is already packaged, ignore for -f: %s\n", ptr);
1222325ef124SMatthew Dillon deleteme = 0;
1223325ef124SMatthew Dillon } else {
12248e25f19bSMatthew Dillon pkg->flags |= PKGF_PACKAGED;
1225dc46751bSMatthew Dillon deleteme = 0;
1226325ef124SMatthew Dillon }
12278d9409b8SMatthew Dillon } else {
12288e25f19bSMatthew Dillon ddprintf(0, "Note: package scan, not in list, "
1229753e4c44SMatthew Dillon "skipping %s{.%s,.pkg}\n", ptr, UsePkgSufx);
12308e25f19bSMatthew Dillon }
12318d9409b8SMatthew Dillon }
12326fd67931SMatthew Dillon if (dexec_close(fp, pid)) {
12336fd67931SMatthew Dillon printf("pkg query command failed for %s\n", repopath);
12346fd67931SMatthew Dillon }
1235dc46751bSMatthew Dillon if (deleteme) {
1236dc46751bSMatthew Dillon dlog(DLOG_ALL | DLOG_STDOUT,
1237dc46751bSMatthew Dillon "Deleting obsolete package %s\n", repopath);
1238dc46751bSMatthew Dillon remove(repopath);
1239dc46751bSMatthew Dillon }
12406fd67931SMatthew Dillon free(repopath);
12418e25f19bSMatthew Dillon }
12428e25f19bSMatthew Dillon
1243a67bf8dbSMatthew Dillon static void
childOptimizeEnv(bulk_t * bulk)1244a67bf8dbSMatthew Dillon childOptimizeEnv(bulk_t *bulk)
1245a67bf8dbSMatthew Dillon {
1246a67bf8dbSMatthew Dillon char *portpath;
12475d0718a8SMatthew Dillon char *localbase;
1248a67bf8dbSMatthew Dillon char *ptr;
1249a67bf8dbSMatthew Dillon FILE *fp;
1250a67bf8dbSMatthew Dillon int line;
1251a67bf8dbSMatthew Dillon size_t len;
1252a67bf8dbSMatthew Dillon const char *cav[MAXCAC];
1253a67bf8dbSMatthew Dillon pid_t pid;
1254a67bf8dbSMatthew Dillon int cac;
1255a67bf8dbSMatthew Dillon
1256a67bf8dbSMatthew Dillon asprintf(&portpath, "%s/%s/%s", DPortsPath, bulk->s1, bulk->s2);
1257a67bf8dbSMatthew Dillon
12585d0718a8SMatthew Dillon /*
12595d0718a8SMatthew Dillon * Prevent postgresql, mysql, and other package Makefile tests
12605d0718a8SMatthew Dillon * from accessing the host system's /usr/local by setting LOCALBASE
12615d0718a8SMatthew Dillon * to an empty directory.
12625d0718a8SMatthew Dillon */
12635d0718a8SMatthew Dillon asprintf(&localbase, "LOCALBASE=%s/empty", BuildBase);
12645d0718a8SMatthew Dillon
1265a67bf8dbSMatthew Dillon cac = 0;
1266a67bf8dbSMatthew Dillon cav[cac++] = MAKE_BINARY;
1267a67bf8dbSMatthew Dillon cav[cac++] = "-C";
1268a67bf8dbSMatthew Dillon cav[cac++] = portpath;
12695d0718a8SMatthew Dillon cav[cac++] = localbase;
1270a67bf8dbSMatthew Dillon cav[cac++] = "-V_PERL5_FROM_BIN";
1271a67bf8dbSMatthew Dillon
1272f9d29536SMatthew Dillon fp = dexec_open(portpath + strlen(DPortsPath) + 1, cav, cac,
1273f9d29536SMatthew Dillon &pid, NULL, 1, 1);
12745d0718a8SMatthew Dillon free(localbase);
1275a67bf8dbSMatthew Dillon free(portpath);
1276a67bf8dbSMatthew Dillon
1277a67bf8dbSMatthew Dillon line = 1;
1278a67bf8dbSMatthew Dillon while ((ptr = fgetln(fp, &len)) != NULL) {
1279a67bf8dbSMatthew Dillon if (len == 0 || ptr[len-1] != '\n') {
1280a67bf8dbSMatthew Dillon dfatal("Bad package info for %s/%s response line %d",
1281a67bf8dbSMatthew Dillon bulk->s1, bulk->s2, line);
1282a67bf8dbSMatthew Dillon }
1283a67bf8dbSMatthew Dillon ptr[--len] = 0;
1284a67bf8dbSMatthew Dillon
1285a67bf8dbSMatthew Dillon switch(line) {
1286a67bf8dbSMatthew Dillon case 1: /* _PERL5_FROM_BIN */
1287a67bf8dbSMatthew Dillon addbuildenv("_PERL5_FROM_BIN", ptr, BENV_ENVIRONMENT);
1288a67bf8dbSMatthew Dillon break;
1289a67bf8dbSMatthew Dillon default:
1290a67bf8dbSMatthew Dillon printf("childOptimizeEnv: EXTRA LINE: %s\n", ptr);
1291a67bf8dbSMatthew Dillon break;
1292a67bf8dbSMatthew Dillon }
1293a67bf8dbSMatthew Dillon ++line;
1294a67bf8dbSMatthew Dillon }
1295a67bf8dbSMatthew Dillon if (line == 1) {
1296a67bf8dbSMatthew Dillon printf("DPort not found: %s/%s\n", bulk->s1, bulk->s2);
1297a67bf8dbSMatthew Dillon } else if (line != 1 + 1) {
1298a67bf8dbSMatthew Dillon printf("DPort corrupt: %s/%s\n", bulk->s1, bulk->s2);
1299a67bf8dbSMatthew Dillon }
1300a67bf8dbSMatthew Dillon if (dexec_close(fp, pid)) {
1301a67bf8dbSMatthew Dillon printf("childOptimizeEnv() failed\n");
1302a67bf8dbSMatthew Dillon }
1303a67bf8dbSMatthew Dillon }
1304a67bf8dbSMatthew Dillon
13058e25f19bSMatthew Dillon static int
scan_and_queue_dir(const char * path,const char * level1,int level)13068e25f19bSMatthew Dillon scan_and_queue_dir(const char *path, const char *level1, int level)
13078e25f19bSMatthew Dillon {
13088e25f19bSMatthew Dillon DIR *dir;
13098e25f19bSMatthew Dillon char *s1;
13108e25f19bSMatthew Dillon char *s2;
13118e25f19bSMatthew Dillon struct dirent *den;
13128e25f19bSMatthew Dillon struct stat st;
13138e25f19bSMatthew Dillon int count = 0;
13148e25f19bSMatthew Dillon
13158e25f19bSMatthew Dillon dir = opendir(path);
13168e25f19bSMatthew Dillon dassert(dir, "Cannot open dports path \"%s\"", path);
13178e25f19bSMatthew Dillon
13188e25f19bSMatthew Dillon while ((den = readdir(dir)) != NULL) {
13198e25f19bSMatthew Dillon if (den->d_namlen == 1 && den->d_name[0] == '.')
13208e25f19bSMatthew Dillon continue;
13218e25f19bSMatthew Dillon if (den->d_namlen == 2 &&
13228e25f19bSMatthew Dillon den->d_name[0] == '.' && den->d_name[1] == '.')
13238e25f19bSMatthew Dillon continue;
13248e25f19bSMatthew Dillon asprintf(&s1, "%s/%s", path, den->d_name);
13258e25f19bSMatthew Dillon if (lstat(s1, &st) < 0 || !S_ISDIR(st.st_mode)) {
13268e25f19bSMatthew Dillon free(s1);
13278e25f19bSMatthew Dillon continue;
13288e25f19bSMatthew Dillon }
13298e25f19bSMatthew Dillon if (level == 1) {
13308e25f19bSMatthew Dillon count += scan_and_queue_dir(s1, den->d_name, 2);
13318e25f19bSMatthew Dillon free(s1);
13328e25f19bSMatthew Dillon continue;
13338e25f19bSMatthew Dillon }
13348e25f19bSMatthew Dillon asprintf(&s2, "%s/Makefile", s1);
13358e25f19bSMatthew Dillon if (lstat(s2, &st) == 0) {
13368e25f19bSMatthew Dillon queuebulk(level1, den->d_name, NULL, NULL);
13378e25f19bSMatthew Dillon ++count;
13388e25f19bSMatthew Dillon }
13398e25f19bSMatthew Dillon free(s1);
13408e25f19bSMatthew Dillon free(s2);
13418e25f19bSMatthew Dillon }
13428e25f19bSMatthew Dillon closedir(dir);
13438e25f19bSMatthew Dillon
13448e25f19bSMatthew Dillon return count;
13458e25f19bSMatthew Dillon }
13468e25f19bSMatthew Dillon
13478e25f19bSMatthew Dillon static int
scan_binary_repo(const char * path)13488e25f19bSMatthew Dillon scan_binary_repo(const char *path)
13498e25f19bSMatthew Dillon {
13508e25f19bSMatthew Dillon DIR *dir;
13518e25f19bSMatthew Dillon struct dirent *den;
13528e25f19bSMatthew Dillon int count;
13538e25f19bSMatthew Dillon
13548e25f19bSMatthew Dillon count = 0;
13558e25f19bSMatthew Dillon dir = opendir(path);
13568e25f19bSMatthew Dillon dassert(dir, "Cannot open repository path \"%s\"", path);
13578e25f19bSMatthew Dillon
13588d9409b8SMatthew Dillon /*
13598d9409b8SMatthew Dillon * NOTE: Test includes the '.' in the suffix.
13608d9409b8SMatthew Dillon */
13618e25f19bSMatthew Dillon while ((den = readdir(dir)) != NULL) {
13628d6cd058SMatthew Dillon const char *suffix;
13638d6cd058SMatthew Dillon
13648d6cd058SMatthew Dillon suffix = strrchr(den->d_name, '.');
13658d6cd058SMatthew Dillon if (suffix && suffix != den->d_name &&
1366753e4c44SMatthew Dillon strcmp(suffix, UsePkgSufx) == 0)
1367753e4c44SMatthew Dillon {
1368753e4c44SMatthew Dillon queuebulk(den->d_name, NULL, NULL, NULL);
1369753e4c44SMatthew Dillon ++count;
1370753e4c44SMatthew Dillon }
1371753e4c44SMatthew Dillon
1372753e4c44SMatthew Dillon /*
1373753e4c44SMatthew Dillon * As of 1.17, pkg generates .pkg files.
1374753e4c44SMatthew Dillon */
1375753e4c44SMatthew Dillon if (suffix && suffix != den->d_name &&
1376753e4c44SMatthew Dillon strcmp(suffix, ".pkg") == 0)
1377753e4c44SMatthew Dillon {
13788e25f19bSMatthew Dillon queuebulk(den->d_name, NULL, NULL, NULL);
13798e25f19bSMatthew Dillon ++count;
13808e25f19bSMatthew Dillon }
13818e25f19bSMatthew Dillon }
13828e25f19bSMatthew Dillon closedir(dir);
13838e25f19bSMatthew Dillon
13848e25f19bSMatthew Dillon return count;
13858e25f19bSMatthew Dillon }
13868e25f19bSMatthew Dillon
13878e25f19bSMatthew Dillon #if 0
13888e25f19bSMatthew Dillon static void
13898e25f19bSMatthew Dillon pkgfree(pkg_t *pkg)
13908e25f19bSMatthew Dillon {
13918e25f19bSMatthew Dillon freestrp(&pkg->portdir);
13928e25f19bSMatthew Dillon freestrp(&pkg->version);
13938e25f19bSMatthew Dillon freestrp(&pkg->pkgfile);
13948e25f19bSMatthew Dillon freestrp(&pkg->ignore);
13958e25f19bSMatthew Dillon freestrp(&pkg->fetch_deps);
13968e25f19bSMatthew Dillon freestrp(&pkg->ext_deps);
13978e25f19bSMatthew Dillon freestrp(&pkg->patch_deps);
13988e25f19bSMatthew Dillon freestrp(&pkg->build_deps);
13998e25f19bSMatthew Dillon freestrp(&pkg->lib_deps);
14008e25f19bSMatthew Dillon freestrp(&pkg->run_deps);
14018e25f19bSMatthew Dillon freestrp(&pkg->pos_options);
14028e25f19bSMatthew Dillon freestrp(&pkg->neg_options);
14038e25f19bSMatthew Dillon freestrp(&pkg->flavors);
14048e25f19bSMatthew Dillon free(pkg);
14058e25f19bSMatthew Dillon }
14068e25f19bSMatthew Dillon #endif
1407