18e25f19bSMatthew Dillon /* 26ec1f604SMatthew Dillon * Copyright (c) 2019-2020 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 #include "dsynth.h" 386ec1f604SMatthew Dillon #include <openssl/md5.h> 398e25f19bSMatthew Dillon 401645cafeSMatthew Dillon typedef struct pinfo { 411645cafeSMatthew Dillon struct pinfo *next; 421645cafeSMatthew Dillon char *spath; 431645cafeSMatthew Dillon int foundit; 446ec1f604SMatthew Dillon int inlocks; 451645cafeSMatthew Dillon } pinfo_t; 461645cafeSMatthew Dillon 47f4094b20SMatthew Dillon static void removePackagesMetaRecurse(pkg_t *pkg); 481645cafeSMatthew Dillon static int pinfocmp(const void *s1, const void *s2); 491645cafeSMatthew Dillon static void scanit(const char *path, const char *subpath, 506ec1f604SMatthew Dillon int *countp, pinfo_t ***list_tailp, 516ec1f604SMatthew Dillon int inlocks); 521645cafeSMatthew Dillon pinfo_t *pinfofind(pinfo_t **ary, int count, char *spath); 53066daf2aSMatthew Dillon static void childRebuildRepo(bulk_t *bulk); 54f7f25838SMatthew Dillon static void scandeletenew(const char *path); 551645cafeSMatthew Dillon 56066daf2aSMatthew Dillon static void rebuildTerminateSignal(int signo); 576ec1f604SMatthew Dillon static char *md5lkfile(char *rpath, int which); 586ec1f604SMatthew Dillon static int lkdircount(char *buf); 59066daf2aSMatthew Dillon 60066daf2aSMatthew Dillon static char *RebuildRemovePath; 61066daf2aSMatthew Dillon 628e25f19bSMatthew Dillon void 631645cafeSMatthew Dillon DoRebuildRepo(int ask) 648e25f19bSMatthew Dillon { 65066daf2aSMatthew Dillon bulk_t *bulk; 66066daf2aSMatthew Dillon FILE *fp; 67066daf2aSMatthew Dillon int fd; 68066daf2aSMatthew Dillon char tpath[256]; 6968dc2eeaSMatthew Dillon const char *sufx; 701645cafeSMatthew Dillon 711645cafeSMatthew Dillon if (ask) { 721645cafeSMatthew Dillon if (askyn("Rebuild the repository? ") == 0) 731645cafeSMatthew Dillon return; 741645cafeSMatthew Dillon } 75f7f25838SMatthew Dillon 76f7f25838SMatthew Dillon /* 77f7f25838SMatthew Dillon * Scan the repository for temporary .new files and delete them. 78f7f25838SMatthew Dillon */ 79f7f25838SMatthew Dillon scandeletenew(RepositoryPath); 80f7f25838SMatthew Dillon 81f7f25838SMatthew Dillon /* 82066daf2aSMatthew Dillon * Generate temporary file 83f7f25838SMatthew Dillon */ 84066daf2aSMatthew Dillon snprintf(tpath, sizeof(tpath), "/tmp/meta.XXXXXXXX.conf"); 85066daf2aSMatthew Dillon 86066daf2aSMatthew Dillon signal(SIGTERM, rebuildTerminateSignal); 87066daf2aSMatthew Dillon signal(SIGINT, rebuildTerminateSignal); 88066daf2aSMatthew Dillon signal(SIGHUP, rebuildTerminateSignal); 89066daf2aSMatthew Dillon 90066daf2aSMatthew Dillon RebuildRemovePath = tpath; 91066daf2aSMatthew Dillon 92483dbac9SMatthew Dillon sufx = UsePkgSufx; 93066daf2aSMatthew Dillon fd = mkostemps(tpath, 5, 0); 94066daf2aSMatthew Dillon if (fd < 0) 95066daf2aSMatthew Dillon dfatal_errno("Cannot create %s", tpath); 96066daf2aSMatthew Dillon fp = fdopen(fd, "w"); 97*6a7ba689SMatthew Dillon fprintf(fp, "version = %d;\n", MetaVersion); 9868dc2eeaSMatthew Dillon fprintf(fp, "packing_format = \"%s\";\n", sufx + 1); 99066daf2aSMatthew Dillon fclose(fp); 100066daf2aSMatthew Dillon 101066daf2aSMatthew Dillon /* 102066daf2aSMatthew Dillon * Run the operation under our bulk infrastructure to 103066daf2aSMatthew Dillon * get the correct environment. 104066daf2aSMatthew Dillon */ 105066daf2aSMatthew Dillon initbulk(childRebuildRepo, 1); 106066daf2aSMatthew Dillon queuebulk(tpath, NULL, NULL, NULL); 107066daf2aSMatthew Dillon bulk = getbulk(); 108066daf2aSMatthew Dillon 109066daf2aSMatthew Dillon if (bulk->r1) 1101645cafeSMatthew Dillon printf("Rebuild succeeded\n"); 111066daf2aSMatthew Dillon else 112066daf2aSMatthew Dillon printf("Rebuild failed\n"); 113066daf2aSMatthew Dillon donebulk(); 114066daf2aSMatthew Dillon 115066daf2aSMatthew Dillon remove(tpath); 116066daf2aSMatthew Dillon } 117066daf2aSMatthew Dillon 118066daf2aSMatthew Dillon static void 1197f2422cfSMatthew Dillon repackage(const char *basepath, const char *basefile, 1207f2422cfSMatthew Dillon const char *decomp_suffix, const char *comp_suffix, 1217f2422cfSMatthew Dillon const char *decomp, const char *comp); 122cda252a4SMatthew Dillon 123cda252a4SMatthew Dillon static void 124066daf2aSMatthew Dillon childRebuildRepo(bulk_t *bulk) 125066daf2aSMatthew Dillon { 126066daf2aSMatthew Dillon FILE *fp; 127066daf2aSMatthew Dillon char *ptr; 128066daf2aSMatthew Dillon size_t len; 129066daf2aSMatthew Dillon pid_t pid; 130066daf2aSMatthew Dillon const char *cav[MAXCAC]; 131753e4c44SMatthew Dillon char *pkg_path; 132066daf2aSMatthew Dillon int cac; 1337f2422cfSMatthew Dillon int repackage_mode = 0; 134066daf2aSMatthew Dillon 135753e4c44SMatthew Dillon /* 136753e4c44SMatthew Dillon * We have to use the pkg-static that we built as part of the 137753e4c44SMatthew Dillon * build process to rebuild the repo because the system pkg might 138753e4c44SMatthew Dillon * not be compatible with the repo format changes made in 1.17. 139753e4c44SMatthew Dillon */ 140753e4c44SMatthew Dillon asprintf(&pkg_path, "%s/Template/usr/local/sbin/pkg-static", BuildBase); 141753e4c44SMatthew Dillon 142066daf2aSMatthew Dillon cac = 0; 143753e4c44SMatthew Dillon cav[cac++] = pkg_path; 144066daf2aSMatthew Dillon cav[cac++] = "repo"; 145066daf2aSMatthew Dillon cav[cac++] = "-m"; 146066daf2aSMatthew Dillon cav[cac++] = bulk->s1; 147066daf2aSMatthew Dillon cav[cac++] = "-o"; 148066daf2aSMatthew Dillon cav[cac++] = PackagesPath; 149cda252a4SMatthew Dillon 150cda252a4SMatthew Dillon /* 151cda252a4SMatthew Dillon * The yaml needs to generate paths relative to PackagePath 152cda252a4SMatthew Dillon */ 153cda252a4SMatthew Dillon if (strncmp(PackagesPath, RepositoryPath, strlen(PackagesPath)) == 0) 154cda252a4SMatthew Dillon cav[cac++] = PackagesPath; 155cda252a4SMatthew Dillon else 156066daf2aSMatthew Dillon cav[cac++] = RepositoryPath; 157066daf2aSMatthew Dillon 158cda252a4SMatthew Dillon printf("pkg repo -m %s -o %s %s\n", bulk->s1, cav[cac-2], cav[cac-1]); 159066daf2aSMatthew Dillon 160f9d29536SMatthew Dillon fp = dexec_open(NULL, cav, cac, &pid, NULL, 1, 0); 161066daf2aSMatthew Dillon while ((ptr = fgetln(fp, &len)) != NULL) 162066daf2aSMatthew Dillon fwrite(ptr, 1, len, stdout); 16396cc8f92SMatthew Dillon if (dexec_close(fp, pid) == 0) 164066daf2aSMatthew Dillon bulk->r1 = strdup(""); 16596cc8f92SMatthew Dillon 16696cc8f92SMatthew Dillon /* 16796cc8f92SMatthew Dillon * Check package version. Pkg version 1.12 and later generates 16896cc8f92SMatthew Dillon * the proper repo compression format. Prior to that version 16996cc8f92SMatthew Dillon * the repo directive always generated .txz files. 17096cc8f92SMatthew Dillon */ 17196cc8f92SMatthew Dillon cac = 0; 172753e4c44SMatthew Dillon cav[cac++] = pkg_path; 17396cc8f92SMatthew Dillon cav[cac++] = "-v"; 174f9d29536SMatthew Dillon fp = dexec_open(NULL, cav, cac, &pid, NULL, 1, 0); 17596cc8f92SMatthew Dillon if ((ptr = fgetln(fp, &len)) != NULL && len > 0) { 17696cc8f92SMatthew Dillon int v1; 17796cc8f92SMatthew Dillon int v2; 17896cc8f92SMatthew Dillon 17996cc8f92SMatthew Dillon ptr[len-1] = 0; 18096cc8f92SMatthew Dillon if (sscanf(ptr, "%d.%d", &v1, &v2) == 2) { 181753e4c44SMatthew Dillon printf("pkg repo - pkg version: %d.%d\n", v1, v2); 18296cc8f92SMatthew Dillon if (v1 > 1 || (v1 == 1 && v2 >= 12)) 1837f2422cfSMatthew Dillon repackage_mode = 1; 1841645cafeSMatthew Dillon } 18596cc8f92SMatthew Dillon } 18696cc8f92SMatthew Dillon dexec_close(fp, pid); 187cda252a4SMatthew Dillon 188cda252a4SMatthew Dillon /* 189cda252a4SMatthew Dillon * Repackage the .txz files created by pkg repo if necessary 190cda252a4SMatthew Dillon */ 1917f2422cfSMatthew Dillon if (repackage_mode == 0 && strcmp(UsePkgSufx, ".txz") != 0) { 192cda252a4SMatthew Dillon const char *comp; 193cda252a4SMatthew Dillon const char *decomp; 194cda252a4SMatthew Dillon 1957f2422cfSMatthew Dillon printf("pkg repo - recompressing digests and packagesite\n"); 19696cc8f92SMatthew Dillon 197483dbac9SMatthew Dillon if (strcmp(UsePkgSufx, ".tar") == 0) { 198cda252a4SMatthew Dillon decomp = "unxz"; 199cda252a4SMatthew Dillon comp = "cat"; 200483dbac9SMatthew Dillon } else if (strcmp(UsePkgSufx, ".tgz") == 0) { 201cda252a4SMatthew Dillon decomp = "unxz"; 202cda252a4SMatthew Dillon comp = "gzip"; 203483dbac9SMatthew Dillon } else if (strcmp(UsePkgSufx, ".tbz") == 0) { 204cda252a4SMatthew Dillon decomp = "unxz"; 205cda252a4SMatthew Dillon comp = "bzip"; 206ef0c0bf5SKrzysztof Piecuch } else if (strcmp(UsePkgSufx, ".tzst") == 0) { 207ef0c0bf5SKrzysztof Piecuch decomp = "unxz"; 208ef0c0bf5SKrzysztof Piecuch comp = "zstd"; 209cda252a4SMatthew Dillon } else { 2107f2422cfSMatthew Dillon dfatal("recompressing as %s not supported", 2117f2422cfSMatthew Dillon UsePkgSufx); 212cda252a4SMatthew Dillon decomp = "unxz"; 213cda252a4SMatthew Dillon comp = "cat"; 214cda252a4SMatthew Dillon } 2157f2422cfSMatthew Dillon repackage(PackagesPath, "digests", 2167f2422cfSMatthew Dillon ".txz", UsePkgSufx, 2177f2422cfSMatthew Dillon decomp, comp); 2187f2422cfSMatthew Dillon repackage(PackagesPath, "packagesite", 2197f2422cfSMatthew Dillon ".txz", UsePkgSufx, 2207f2422cfSMatthew Dillon decomp, comp); 2217f2422cfSMatthew Dillon } else if (repackage_mode == 1 && strcmp(UsePkgSufx, ".txz") != 0) { 2227f2422cfSMatthew Dillon const char *comp; 2237f2422cfSMatthew Dillon const char *decomp; 2247f2422cfSMatthew Dillon 2257f2422cfSMatthew Dillon printf("pkg repo - recompressing meta\n"); 2267f2422cfSMatthew Dillon 2277f2422cfSMatthew Dillon if (strcmp(UsePkgSufx, ".tar") == 0) { 2287f2422cfSMatthew Dillon decomp = "cat"; 2297f2422cfSMatthew Dillon comp = "xz"; 2307f2422cfSMatthew Dillon } else if (strcmp(UsePkgSufx, ".tgz") == 0) { 2317f2422cfSMatthew Dillon decomp = "gunzip"; 2327f2422cfSMatthew Dillon comp = "xz"; 2337f2422cfSMatthew Dillon } else if (strcmp(UsePkgSufx, ".tbz") == 0) { 2347f2422cfSMatthew Dillon decomp = "bunzip2"; 2357f2422cfSMatthew Dillon comp = "xz"; 236ef0c0bf5SKrzysztof Piecuch } else if (strcmp(UsePkgSufx, ".tzst") == 0) { 237ef0c0bf5SKrzysztof Piecuch decomp = "unzstd"; 238ef0c0bf5SKrzysztof Piecuch comp = "xz"; 2397f2422cfSMatthew Dillon } else { 2407f2422cfSMatthew Dillon dfatal("recompressing from %s not supported", 2417f2422cfSMatthew Dillon UsePkgSufx); 2427f2422cfSMatthew Dillon decomp = "cat"; 2437f2422cfSMatthew Dillon comp = "cat"; 2447f2422cfSMatthew Dillon } 2457f2422cfSMatthew Dillon repackage(PackagesPath, "meta", 2467f2422cfSMatthew Dillon UsePkgSufx, ".txz", 2477f2422cfSMatthew Dillon decomp, comp); 248cda252a4SMatthew Dillon } 249753e4c44SMatthew Dillon free (pkg_path); 250cda252a4SMatthew Dillon } 251cda252a4SMatthew Dillon 252cda252a4SMatthew Dillon static 253cda252a4SMatthew Dillon void 2547f2422cfSMatthew Dillon repackage(const char *basepath, const char *basefile, 2557f2422cfSMatthew Dillon const char *decomp_suffix, const char *comp_suffix, 2567f2422cfSMatthew Dillon const char *decomp, const char *comp) 257cda252a4SMatthew Dillon { 258cda252a4SMatthew Dillon char *buf; 259cda252a4SMatthew Dillon 2607f2422cfSMatthew Dillon asprintf(&buf, "%s < %s/%s%s | %s > %s/%s%s", 2617f2422cfSMatthew Dillon decomp, basepath, basefile, decomp_suffix, 2627f2422cfSMatthew Dillon comp, basepath, basefile, comp_suffix); 263cda252a4SMatthew Dillon if (system(buf) != 0) { 264cda252a4SMatthew Dillon dfatal("command failed: %s", buf); 265cda252a4SMatthew Dillon } 266cda252a4SMatthew Dillon free(buf); 2678e25f19bSMatthew Dillon } 2688e25f19bSMatthew Dillon 2698e25f19bSMatthew Dillon void 2708e25f19bSMatthew Dillon DoUpgradePkgs(pkg_t *pkgs __unused, int ask __unused) 2718e25f19bSMatthew Dillon { 2728e25f19bSMatthew Dillon dfatal("Not Implemented"); 2738e25f19bSMatthew Dillon } 2748e25f19bSMatthew Dillon 2758e25f19bSMatthew Dillon void 2761645cafeSMatthew Dillon PurgeDistfiles(pkg_t *pkgs) 2778e25f19bSMatthew Dillon { 2781645cafeSMatthew Dillon pinfo_t *list; 2791645cafeSMatthew Dillon pinfo_t *item; 2801645cafeSMatthew Dillon pinfo_t **list_tail; 2811645cafeSMatthew Dillon pinfo_t **ary; 2821645cafeSMatthew Dillon char *dstr; 2831645cafeSMatthew Dillon char *buf; 2841645cafeSMatthew Dillon int count; 2851645cafeSMatthew Dillon int delcount; 2861645cafeSMatthew Dillon int i; 2871645cafeSMatthew Dillon 2881645cafeSMatthew Dillon printf("Scanning distfiles... "); 2891645cafeSMatthew Dillon fflush(stdout); 2901645cafeSMatthew Dillon count = 0; 2911645cafeSMatthew Dillon list = NULL; 2921645cafeSMatthew Dillon list_tail = &list; 2936ec1f604SMatthew Dillon scanit(DistFilesPath, NULL, &count, &list_tail, 0); 2941645cafeSMatthew Dillon printf("Checking %d distfiles\n", count); 2951645cafeSMatthew Dillon fflush(stdout); 2961645cafeSMatthew Dillon 2971645cafeSMatthew Dillon ary = calloc(count, sizeof(pinfo_t *)); 2981645cafeSMatthew Dillon for (i = 0; i < count; ++i) { 2991645cafeSMatthew Dillon ary[i] = list; 3001645cafeSMatthew Dillon list = list->next; 3011645cafeSMatthew Dillon } 3021645cafeSMatthew Dillon ddassert(list == NULL); 3031645cafeSMatthew Dillon qsort(ary, count, sizeof(pinfo_t *), pinfocmp); 3041645cafeSMatthew Dillon 3051645cafeSMatthew Dillon for (; pkgs; pkgs = pkgs->bnext) { 3061645cafeSMatthew Dillon if (pkgs->distfiles == NULL || pkgs->distfiles[0] == 0) 3071645cafeSMatthew Dillon continue; 3081645cafeSMatthew Dillon ddprintf(0, "distfiles %s\n", pkgs->distfiles); 3091645cafeSMatthew Dillon dstr = strtok(pkgs->distfiles, " \t"); 3101645cafeSMatthew Dillon while (dstr) { 3111645cafeSMatthew Dillon for (;;) { 3126ec1f604SMatthew Dillon /* 3136ec1f604SMatthew Dillon * Look for distfile 3146ec1f604SMatthew Dillon */ 3154ea2ee4dSMatthew Dillon if (pkgs->distsubdir) { 3161645cafeSMatthew Dillon asprintf(&buf, "%s/%s", 3171645cafeSMatthew Dillon pkgs->distsubdir, dstr); 3186ec1f604SMatthew Dillon } else { 3196ec1f604SMatthew Dillon buf = dstr; 3206ec1f604SMatthew Dillon } 3211645cafeSMatthew Dillon item = pinfofind(ary, count, buf); 3226ec1f604SMatthew Dillon if (item) 3236ec1f604SMatthew Dillon item->foundit = 1; 3246ec1f604SMatthew Dillon if (item && item->inlocks == 0) { 3256ec1f604SMatthew Dillon /* 3266ec1f604SMatthew Dillon * Look for the lock file 3276ec1f604SMatthew Dillon */ 3286ec1f604SMatthew Dillon int scount; 3296ec1f604SMatthew Dillon 3306ec1f604SMatthew Dillon scount = lkdircount(buf); 3316ec1f604SMatthew Dillon 3326ec1f604SMatthew Dillon for (i = 0; i <= scount; ++i) { 3336ec1f604SMatthew Dillon item = pinfofind(ary, count, 3346ec1f604SMatthew Dillon md5lkfile(buf, i)); 3356ec1f604SMatthew Dillon if (item) 3366ec1f604SMatthew Dillon item->foundit = 1; 3376ec1f604SMatthew Dillon } 3386ec1f604SMatthew Dillon } 3396ec1f604SMatthew Dillon 3406ec1f604SMatthew Dillon /* 3416ec1f604SMatthew Dillon * Cleanup and iterate 3426ec1f604SMatthew Dillon */ 3436ec1f604SMatthew Dillon if (buf != dstr) { 3441645cafeSMatthew Dillon free(buf); 3451645cafeSMatthew Dillon buf = NULL; 3461645cafeSMatthew Dillon } 3471645cafeSMatthew Dillon if (strrchr(dstr, ':') == NULL) 3481645cafeSMatthew Dillon break; 3491645cafeSMatthew Dillon *strrchr(dstr, ':') = 0; 3501645cafeSMatthew Dillon } 3511645cafeSMatthew Dillon dstr = strtok(NULL, " \t"); 3521645cafeSMatthew Dillon } 3531645cafeSMatthew Dillon } 3541645cafeSMatthew Dillon 3551645cafeSMatthew Dillon delcount = 0; 3561645cafeSMatthew Dillon for (i = 0; i < count; ++i) { 3571645cafeSMatthew Dillon item = ary[i]; 3581645cafeSMatthew Dillon if (item->foundit == 0) { 3591645cafeSMatthew Dillon ++delcount; 3601645cafeSMatthew Dillon } 3611645cafeSMatthew Dillon } 36261e823a7SMatthew Dillon if (delcount == 0) { 36361e823a7SMatthew Dillon printf("No obsolete source files out of %d found\n", count); 36461e823a7SMatthew Dillon } else if (askyn("Delete %d of %d items? ", delcount, count)) { 3651645cafeSMatthew Dillon printf("Deleting %d/%d obsolete source distfiles\n", 3661645cafeSMatthew Dillon delcount, count); 3671645cafeSMatthew Dillon for (i = 0; i < count; ++i) { 3681645cafeSMatthew Dillon item = ary[i]; 3691645cafeSMatthew Dillon if (item->foundit == 0) { 3701645cafeSMatthew Dillon asprintf(&buf, "%s/%s", 3711645cafeSMatthew Dillon DistFilesPath, item->spath); 3721645cafeSMatthew Dillon if (remove(buf) < 0) 3731645cafeSMatthew Dillon printf("Cannot delete %s\n", buf); 3746ec1f604SMatthew Dillon else 3756ec1f604SMatthew Dillon printf("Deleted %s\n", item->spath); 3761645cafeSMatthew Dillon free(buf); 3771645cafeSMatthew Dillon } 3781645cafeSMatthew Dillon } 3791645cafeSMatthew Dillon } 3801645cafeSMatthew Dillon 3811645cafeSMatthew Dillon 3821645cafeSMatthew Dillon free(ary); 3838e25f19bSMatthew Dillon } 3848e25f19bSMatthew Dillon 3858e25f19bSMatthew Dillon void 386f4094b20SMatthew Dillon RemovePackages(pkg_t *list) 3878e25f19bSMatthew Dillon { 388f4094b20SMatthew Dillon pkg_t *scan; 389f4094b20SMatthew Dillon char *path; 390f4094b20SMatthew Dillon 391f4094b20SMatthew Dillon for (scan = list; scan; scan = scan->bnext) { 392f4094b20SMatthew Dillon if ((scan->flags & PKGF_MANUALSEL) == 0) 393f4094b20SMatthew Dillon continue; 394f4094b20SMatthew Dillon if (scan->pkgfile) { 395f4094b20SMatthew Dillon scan->flags &= ~PKGF_PACKAGED; 396f4094b20SMatthew Dillon scan->pkgfile_size = 0; 397f4094b20SMatthew Dillon asprintf(&path, "%s/%s", RepositoryPath, scan->pkgfile); 398f4094b20SMatthew Dillon if (remove(path) == 0) 399f4094b20SMatthew Dillon printf("Removed: %s\n", path); 400f4094b20SMatthew Dillon free(path); 401f4094b20SMatthew Dillon } 402f4094b20SMatthew Dillon if (scan->pkgfile == NULL || 403f4094b20SMatthew Dillon (scan->flags & (PKGF_DUMMY | PKGF_META))) { 404f4094b20SMatthew Dillon removePackagesMetaRecurse(scan); 405f4094b20SMatthew Dillon } 406f4094b20SMatthew Dillon } 407f4094b20SMatthew Dillon } 408f4094b20SMatthew Dillon 409f4094b20SMatthew Dillon static void 410f4094b20SMatthew Dillon removePackagesMetaRecurse(pkg_t *pkg) 411f4094b20SMatthew Dillon { 412f4094b20SMatthew Dillon pkglink_t *link; 413f4094b20SMatthew Dillon pkg_t *scan; 414f4094b20SMatthew Dillon char *path; 415f4094b20SMatthew Dillon 416f4094b20SMatthew Dillon PKGLIST_FOREACH(link, &pkg->idepon_list) { 417f4094b20SMatthew Dillon scan = link->pkg; 418f4094b20SMatthew Dillon if (scan == NULL) 419f4094b20SMatthew Dillon continue; 420f4094b20SMatthew Dillon if (scan->pkgfile == NULL || 421f4094b20SMatthew Dillon (scan->flags & (PKGF_DUMMY | PKGF_META))) { 422f4094b20SMatthew Dillon removePackagesMetaRecurse(scan); 423f4094b20SMatthew Dillon continue; 424f4094b20SMatthew Dillon } 425f4094b20SMatthew Dillon scan->flags &= ~PKGF_PACKAGED; 426f4094b20SMatthew Dillon scan->pkgfile_size = 0; 427f4094b20SMatthew Dillon 428f4094b20SMatthew Dillon asprintf(&path, "%s/%s", RepositoryPath, scan->pkgfile); 429f4094b20SMatthew Dillon if (remove(path) == 0) 430f4094b20SMatthew Dillon printf("Removed: %s\n", path); 431f4094b20SMatthew Dillon free(path); 432f4094b20SMatthew Dillon } 4338e25f19bSMatthew Dillon } 4341645cafeSMatthew Dillon 4351645cafeSMatthew Dillon static int 4361645cafeSMatthew Dillon pinfocmp(const void *s1, const void *s2) 4371645cafeSMatthew Dillon { 4381645cafeSMatthew Dillon const pinfo_t *item1 = *(const pinfo_t *const*)s1; 4391645cafeSMatthew Dillon const pinfo_t *item2 = *(const pinfo_t *const*)s2; 4401645cafeSMatthew Dillon 4411645cafeSMatthew Dillon return (strcmp(item1->spath, item2->spath)); 4421645cafeSMatthew Dillon } 4431645cafeSMatthew Dillon 4441645cafeSMatthew Dillon pinfo_t * 4451645cafeSMatthew Dillon pinfofind(pinfo_t **ary, int count, char *spath) 4461645cafeSMatthew Dillon { 4471645cafeSMatthew Dillon pinfo_t *item; 4481645cafeSMatthew Dillon int res; 4491645cafeSMatthew Dillon int b; 4501645cafeSMatthew Dillon int e; 4511645cafeSMatthew Dillon int m; 4521645cafeSMatthew Dillon 4531645cafeSMatthew Dillon b = 0; 4541645cafeSMatthew Dillon e = count; 4551645cafeSMatthew Dillon while (b != e) { 4561645cafeSMatthew Dillon m = b + (e - b) / 2; 4571645cafeSMatthew Dillon item = ary[m]; 4581645cafeSMatthew Dillon res = strcmp(spath, item->spath); 4591645cafeSMatthew Dillon if (res == 0) 4601645cafeSMatthew Dillon return item; 4611645cafeSMatthew Dillon if (res < 0) { 4621645cafeSMatthew Dillon e = m; 4631645cafeSMatthew Dillon } else { 4641645cafeSMatthew Dillon b = m + 1; 4651645cafeSMatthew Dillon } 4661645cafeSMatthew Dillon } 4671645cafeSMatthew Dillon return NULL; 4681645cafeSMatthew Dillon } 4691645cafeSMatthew Dillon 4701645cafeSMatthew Dillon void 4711645cafeSMatthew Dillon scanit(const char *path, const char *subpath, 4726ec1f604SMatthew Dillon int *countp, pinfo_t ***list_tailp, 4736ec1f604SMatthew Dillon int inlocks) 4741645cafeSMatthew Dillon { 4751645cafeSMatthew Dillon struct dirent *den; 4761645cafeSMatthew Dillon pinfo_t *item; 4771645cafeSMatthew Dillon char *npath; 4781645cafeSMatthew Dillon char *spath; 4791645cafeSMatthew Dillon DIR *dir; 4801645cafeSMatthew Dillon struct stat st; 4811645cafeSMatthew Dillon 4821645cafeSMatthew Dillon if ((dir = opendir(path)) != NULL) { 4831645cafeSMatthew Dillon while ((den = readdir(dir)) != NULL) { 4841645cafeSMatthew Dillon if (den->d_namlen == 1 && den->d_name[0] == '.') 4851645cafeSMatthew Dillon continue; 4861645cafeSMatthew Dillon if (den->d_namlen == 2 && den->d_name[0] == '.' && 4871645cafeSMatthew Dillon den->d_name[1] == '.') 4881645cafeSMatthew Dillon continue; 4891645cafeSMatthew Dillon asprintf(&npath, "%s/%s", path, den->d_name); 4901645cafeSMatthew Dillon if (lstat(npath, &st) < 0) { 4911645cafeSMatthew Dillon free(npath); 4921645cafeSMatthew Dillon continue; 4931645cafeSMatthew Dillon } 4941645cafeSMatthew Dillon if (S_ISDIR(st.st_mode)) { 4956ec1f604SMatthew Dillon int sublocks; 4966ec1f604SMatthew Dillon 4976ec1f604SMatthew Dillon sublocks = 4986ec1f604SMatthew Dillon (strcmp(den->d_name, ".locks") == 0); 4996ec1f604SMatthew Dillon 5001645cafeSMatthew Dillon if (subpath) { 5011645cafeSMatthew Dillon asprintf(&spath, "%s/%s", 5021645cafeSMatthew Dillon subpath, den->d_name); 5036ec1f604SMatthew Dillon scanit(npath, spath, countp, 5046ec1f604SMatthew Dillon list_tailp, sublocks); 5051645cafeSMatthew Dillon free(spath); 5061645cafeSMatthew Dillon } else { 5076ec1f604SMatthew Dillon scanit(npath, den->d_name, countp, 5086ec1f604SMatthew Dillon list_tailp, sublocks); 5091645cafeSMatthew Dillon } 5101645cafeSMatthew Dillon } else if (S_ISREG(st.st_mode)) { 5111645cafeSMatthew Dillon item = calloc(1, sizeof(*item)); 5121645cafeSMatthew Dillon if (subpath) { 5131645cafeSMatthew Dillon asprintf(&item->spath, "%s/%s", 5141645cafeSMatthew Dillon subpath, den->d_name); 5151645cafeSMatthew Dillon } else { 5161645cafeSMatthew Dillon item->spath = strdup(den->d_name); 5171645cafeSMatthew Dillon } 5186ec1f604SMatthew Dillon item->inlocks = inlocks; 5196ec1f604SMatthew Dillon 5201645cafeSMatthew Dillon **list_tailp = item; 5211645cafeSMatthew Dillon *list_tailp = &item->next; 5221645cafeSMatthew Dillon ++*countp; 5231645cafeSMatthew Dillon ddprintf(0, "scan %s\n", item->spath); 5241645cafeSMatthew Dillon } 5256a3a20b1SMatthew Dillon free(npath); 5261645cafeSMatthew Dillon } 5271645cafeSMatthew Dillon closedir(dir); 5281645cafeSMatthew Dillon } 5291645cafeSMatthew Dillon } 530f7f25838SMatthew Dillon 531f7f25838SMatthew Dillon /* 532f7f25838SMatthew Dillon * This removes any .new files left over in the repo. These can wind 533f7f25838SMatthew Dillon * being left around when dsynth is killed. 534f7f25838SMatthew Dillon */ 535f7f25838SMatthew Dillon static void 536f7f25838SMatthew Dillon scandeletenew(const char *path) 537f7f25838SMatthew Dillon { 538f7f25838SMatthew Dillon struct dirent *den; 539f7f25838SMatthew Dillon const char *ptr; 540f7f25838SMatthew Dillon DIR *dir; 541f7f25838SMatthew Dillon char *buf; 542f7f25838SMatthew Dillon 543f7f25838SMatthew Dillon if ((dir = opendir(path)) == NULL) 544f7f25838SMatthew Dillon dfatal_errno("Cannot scan directory %s", path); 545f7f25838SMatthew Dillon while ((den = readdir(dir)) != NULL) { 546f7f25838SMatthew Dillon if ((ptr = strrchr(den->d_name, '.')) != NULL && 547f7f25838SMatthew Dillon strcmp(ptr, ".new") == 0) { 548f7f25838SMatthew Dillon asprintf(&buf, "%s/%s", path, den->d_name); 549f7f25838SMatthew Dillon if (remove(buf) < 0) 550f7f25838SMatthew Dillon dfatal_errno("remove: Garbage %s\n", buf); 551f7f25838SMatthew Dillon printf("Deleted Garbage %s\n", buf); 552f7f25838SMatthew Dillon free(buf); 553f7f25838SMatthew Dillon } 554f7f25838SMatthew Dillon } 555f7f25838SMatthew Dillon closedir(dir); 556f7f25838SMatthew Dillon } 557066daf2aSMatthew Dillon 558066daf2aSMatthew Dillon static void 559066daf2aSMatthew Dillon rebuildTerminateSignal(int signo __unused) 560066daf2aSMatthew Dillon { 561066daf2aSMatthew Dillon if (RebuildRemovePath) 562066daf2aSMatthew Dillon remove(RebuildRemovePath); 563066daf2aSMatthew Dillon exit(1); 564066daf2aSMatthew Dillon 565066daf2aSMatthew Dillon } 5666ec1f604SMatthew Dillon 5676ec1f604SMatthew Dillon /* 5686ec1f604SMatthew Dillon * There will be a .locks sub-directory in /usr/distfiles and also 5696ec1f604SMatthew Dillon * in each sub-directory underneath it containing the MD5 sums for 5706ec1f604SMatthew Dillon * the files in that subdirectory. 5716ec1f604SMatthew Dillon * 5726ec1f604SMatthew Dillon * This is a bit of a mess. Sometimes the .locks/ for a subdirectory 5736ec1f604SMatthew Dillon * are in parentdir/.locks and not parentdir/subdir/.locks. The invocation 5746ec1f604SMatthew Dillon * of do-fetch can be a bit messy so we look for a .locks subdir everywhere. 5756ec1f604SMatthew Dillon * 5766ec1f604SMatthew Dillon * The /usr/dports/Mk/Scripts/do-fetch.sh script uses 'echo blah | md5', 5776ec1f604SMatthew Dillon * so we have to add a newline to the buffer being md5'd. 5786ec1f604SMatthew Dillon * 5796ec1f604SMatthew Dillon * The pass-in rpath is relative to the distfiles base. 5806ec1f604SMatthew Dillon */ 5816ec1f604SMatthew Dillon static char * 5826ec1f604SMatthew Dillon md5lkfile(char *rpath, int which_slash) 5836ec1f604SMatthew Dillon { 5846ec1f604SMatthew Dillon static char mstr[128]; 5856ec1f604SMatthew Dillon static char lkfile[128]; 5866ec1f604SMatthew Dillon uint8_t digest[MD5_DIGEST_LENGTH]; 5876ec1f604SMatthew Dillon int bplen; 5886ec1f604SMatthew Dillon int i; 5896ec1f604SMatthew Dillon 5906ec1f604SMatthew Dillon bplen = 0; 5916ec1f604SMatthew Dillon for (i = 0; i < which_slash; ++i) { 5926ec1f604SMatthew Dillon while (rpath[bplen] && rpath[bplen] != '/') 5936ec1f604SMatthew Dillon ++bplen; 5946ec1f604SMatthew Dillon if (rpath[bplen]) 5956ec1f604SMatthew Dillon ++bplen; 5966ec1f604SMatthew Dillon } 5976ec1f604SMatthew Dillon snprintf(mstr, sizeof(mstr), "%s\n", rpath + bplen); 5986ec1f604SMatthew Dillon MD5(mstr, strlen(mstr), digest); 5996ec1f604SMatthew Dillon 6006ec1f604SMatthew Dillon snprintf(lkfile, sizeof(lkfile), 6016ec1f604SMatthew Dillon "%*.*s.locks/" 6026ec1f604SMatthew Dillon "%02x%02x%02x%02x%02x%02x%02x%02x" 6036ec1f604SMatthew Dillon "%02x%02x%02x%02x%02x%02x%02x%02x" 6046ec1f604SMatthew Dillon ".lk", 6056ec1f604SMatthew Dillon bplen, bplen, rpath, 6066ec1f604SMatthew Dillon digest[0], digest[1], digest[2], digest[3], 6076ec1f604SMatthew Dillon digest[4], digest[5], digest[6], digest[7], 6086ec1f604SMatthew Dillon digest[8], digest[9], digest[10], digest[11], 6096ec1f604SMatthew Dillon digest[12], digest[13], digest[14], digest[15]); 6106ec1f604SMatthew Dillon 6116ec1f604SMatthew Dillon return lkfile; 6126ec1f604SMatthew Dillon } 6136ec1f604SMatthew Dillon 6146ec1f604SMatthew Dillon static int 6156ec1f604SMatthew Dillon lkdircount(char *buf) 6166ec1f604SMatthew Dillon { 6176ec1f604SMatthew Dillon int i; 6186ec1f604SMatthew Dillon int n; 6196ec1f604SMatthew Dillon 6206ec1f604SMatthew Dillon n = 0; 6216ec1f604SMatthew Dillon for (i = 0; buf[i]; ++i) { 6226ec1f604SMatthew Dillon if (buf[i] == '/') 6236ec1f604SMatthew Dillon ++n; 6246ec1f604SMatthew Dillon } 6256ec1f604SMatthew Dillon return n; 6266ec1f604SMatthew Dillon } 627