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