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 #include "dsynth.h" 388e25f19bSMatthew Dillon 391645cafeSMatthew Dillon typedef struct pinfo { 401645cafeSMatthew Dillon struct pinfo *next; 411645cafeSMatthew Dillon char *spath; 421645cafeSMatthew Dillon int foundit; 431645cafeSMatthew Dillon } pinfo_t; 441645cafeSMatthew Dillon 451645cafeSMatthew Dillon static int pinfocmp(const void *s1, const void *s2); 461645cafeSMatthew Dillon static void scanit(const char *path, const char *subpath, 471645cafeSMatthew Dillon int *countp, pinfo_t ***list_tailp); 481645cafeSMatthew Dillon pinfo_t *pinfofind(pinfo_t **ary, int count, char *spath); 49f7f25838SMatthew Dillon static void scandeletenew(const char *path); 501645cafeSMatthew Dillon 518e25f19bSMatthew Dillon void 521645cafeSMatthew Dillon DoRebuildRepo(int ask) 538e25f19bSMatthew Dillon { 541645cafeSMatthew Dillon char *buf; 551645cafeSMatthew Dillon 561645cafeSMatthew Dillon if (ask) { 571645cafeSMatthew Dillon if (askyn("Rebuild the repository? ") == 0) 581645cafeSMatthew Dillon return; 591645cafeSMatthew Dillon } 60f7f25838SMatthew Dillon 61f7f25838SMatthew Dillon /* 62f7f25838SMatthew Dillon * Scan the repository for temporary .new files and delete them. 63f7f25838SMatthew Dillon */ 64f7f25838SMatthew Dillon scandeletenew(RepositoryPath); 65f7f25838SMatthew Dillon 66f7f25838SMatthew Dillon /* 67f7f25838SMatthew Dillon * Issue the repo command to rebuild the repo 68f7f25838SMatthew Dillon */ 691645cafeSMatthew Dillon asprintf(&buf, "pkg repo -o %s %s", PackagesPath, RepositoryPath); 701645cafeSMatthew Dillon printf("Rebuilding repository\n"); 711645cafeSMatthew Dillon if (system(buf)) { 721645cafeSMatthew Dillon printf("Rebuild failed\n"); 731645cafeSMatthew Dillon } else { 741645cafeSMatthew Dillon printf("Rebuild succeeded\n"); 751645cafeSMatthew Dillon } 768e25f19bSMatthew Dillon } 778e25f19bSMatthew Dillon 788e25f19bSMatthew Dillon void 798e25f19bSMatthew Dillon DoUpgradePkgs(pkg_t *pkgs __unused, int ask __unused) 808e25f19bSMatthew Dillon { 818e25f19bSMatthew Dillon dfatal("Not Implemented"); 828e25f19bSMatthew Dillon } 838e25f19bSMatthew Dillon 848e25f19bSMatthew Dillon void 851645cafeSMatthew Dillon PurgeDistfiles(pkg_t *pkgs) 868e25f19bSMatthew Dillon { 871645cafeSMatthew Dillon pinfo_t *list; 881645cafeSMatthew Dillon pinfo_t *item; 891645cafeSMatthew Dillon pinfo_t **list_tail; 901645cafeSMatthew Dillon pinfo_t **ary; 911645cafeSMatthew Dillon char *dstr; 921645cafeSMatthew Dillon char *buf; 931645cafeSMatthew Dillon int count; 941645cafeSMatthew Dillon int delcount; 951645cafeSMatthew Dillon int i; 961645cafeSMatthew Dillon 971645cafeSMatthew Dillon printf("Scanning distfiles... "); 981645cafeSMatthew Dillon fflush(stdout); 991645cafeSMatthew Dillon count = 0; 1001645cafeSMatthew Dillon list = NULL; 1011645cafeSMatthew Dillon list_tail = &list; 1021645cafeSMatthew Dillon scanit(DistFilesPath, NULL, &count, &list_tail); 1031645cafeSMatthew Dillon printf("Checking %d distfiles\n", count); 1041645cafeSMatthew Dillon fflush(stdout); 1051645cafeSMatthew Dillon 1061645cafeSMatthew Dillon ary = calloc(count, sizeof(pinfo_t *)); 1071645cafeSMatthew Dillon for (i = 0; i < count; ++i) { 1081645cafeSMatthew Dillon ary[i] = list; 1091645cafeSMatthew Dillon list = list->next; 1101645cafeSMatthew Dillon } 1111645cafeSMatthew Dillon ddassert(list == NULL); 1121645cafeSMatthew Dillon qsort(ary, count, sizeof(pinfo_t *), pinfocmp); 1131645cafeSMatthew Dillon 1141645cafeSMatthew Dillon for (; pkgs; pkgs = pkgs->bnext) { 1151645cafeSMatthew Dillon if (pkgs->distfiles == NULL || pkgs->distfiles[0] == 0) 1161645cafeSMatthew Dillon continue; 1171645cafeSMatthew Dillon ddprintf(0, "distfiles %s\n", pkgs->distfiles); 1181645cafeSMatthew Dillon dstr = strtok(pkgs->distfiles, " \t"); 1191645cafeSMatthew Dillon while (dstr) { 1201645cafeSMatthew Dillon for (;;) { 1211645cafeSMatthew Dillon if (pkgs->distsubdir && pkgs->distsubdir[0]) { 1221645cafeSMatthew Dillon asprintf(&buf, "%s/%s", 1231645cafeSMatthew Dillon pkgs->distsubdir, dstr); 1241645cafeSMatthew Dillon item = pinfofind(ary, count, buf); 1251645cafeSMatthew Dillon ddprintf(0, "TEST %s %p\n", buf, item); 1261645cafeSMatthew Dillon free(buf); 1271645cafeSMatthew Dillon buf = NULL; 1281645cafeSMatthew Dillon } else { 1291645cafeSMatthew Dillon item = pinfofind(ary, count, dstr); 1301645cafeSMatthew Dillon ddprintf(0, "TEST %s %p\n", dstr, item); 1311645cafeSMatthew Dillon } 1321645cafeSMatthew Dillon if (item) { 1331645cafeSMatthew Dillon item->foundit = 1; 1341645cafeSMatthew Dillon break; 1351645cafeSMatthew Dillon } 1361645cafeSMatthew Dillon if (strrchr(dstr, ':') == NULL) 1371645cafeSMatthew Dillon break; 1381645cafeSMatthew Dillon *strrchr(dstr, ':') = 0; 1391645cafeSMatthew Dillon } 1401645cafeSMatthew Dillon dstr = strtok(NULL, " \t"); 1411645cafeSMatthew Dillon } 1421645cafeSMatthew Dillon } 1431645cafeSMatthew Dillon 1441645cafeSMatthew Dillon delcount = 0; 1451645cafeSMatthew Dillon for (i = 0; i < count; ++i) { 1461645cafeSMatthew Dillon item = ary[i]; 1471645cafeSMatthew Dillon if (item->foundit == 0) { 1481645cafeSMatthew Dillon ++delcount; 1491645cafeSMatthew Dillon } 1501645cafeSMatthew Dillon } 1511645cafeSMatthew Dillon if (askyn("Delete %d of %d items? ", delcount, count)) { 1521645cafeSMatthew Dillon printf("Deleting %d/%d obsolete source distfiles\n", 1531645cafeSMatthew Dillon delcount, count); 1541645cafeSMatthew Dillon for (i = 0; i < count; ++i) { 1551645cafeSMatthew Dillon item = ary[i]; 1561645cafeSMatthew Dillon if (item->foundit == 0) { 1571645cafeSMatthew Dillon asprintf(&buf, "%s/%s", 1581645cafeSMatthew Dillon DistFilesPath, item->spath); 1591645cafeSMatthew Dillon if (remove(buf) < 0) 1601645cafeSMatthew Dillon printf("Cannot delete %s\n", buf); 1611645cafeSMatthew Dillon free(buf); 1621645cafeSMatthew Dillon } 1631645cafeSMatthew Dillon } 1641645cafeSMatthew Dillon } 1651645cafeSMatthew Dillon 1661645cafeSMatthew Dillon 1671645cafeSMatthew Dillon free(ary); 1688e25f19bSMatthew Dillon } 1698e25f19bSMatthew Dillon 1708e25f19bSMatthew Dillon void 1718e25f19bSMatthew Dillon RemovePackages(pkg_t *pkgs __unused) 1728e25f19bSMatthew Dillon { 1738e25f19bSMatthew Dillon dfatal("Not Implemented"); 1748e25f19bSMatthew Dillon } 1751645cafeSMatthew Dillon 1761645cafeSMatthew Dillon static int 1771645cafeSMatthew Dillon pinfocmp(const void *s1, const void *s2) 1781645cafeSMatthew Dillon { 1791645cafeSMatthew Dillon const pinfo_t *item1 = *(const pinfo_t *const*)s1; 1801645cafeSMatthew Dillon const pinfo_t *item2 = *(const pinfo_t *const*)s2; 1811645cafeSMatthew Dillon 1821645cafeSMatthew Dillon return (strcmp(item1->spath, item2->spath)); 1831645cafeSMatthew Dillon } 1841645cafeSMatthew Dillon 1851645cafeSMatthew Dillon pinfo_t * 1861645cafeSMatthew Dillon pinfofind(pinfo_t **ary, int count, char *spath) 1871645cafeSMatthew Dillon { 1881645cafeSMatthew Dillon pinfo_t *item; 1891645cafeSMatthew Dillon int res; 1901645cafeSMatthew Dillon int b; 1911645cafeSMatthew Dillon int e; 1921645cafeSMatthew Dillon int m; 1931645cafeSMatthew Dillon 1941645cafeSMatthew Dillon b = 0; 1951645cafeSMatthew Dillon e = count; 1961645cafeSMatthew Dillon while (b != e) { 1971645cafeSMatthew Dillon m = b + (e - b) / 2; 1981645cafeSMatthew Dillon item = ary[m]; 1991645cafeSMatthew Dillon res = strcmp(spath, item->spath); 2001645cafeSMatthew Dillon if (res == 0) 2011645cafeSMatthew Dillon return item; 2021645cafeSMatthew Dillon if (res < 0) { 2031645cafeSMatthew Dillon e = m; 2041645cafeSMatthew Dillon } else { 2051645cafeSMatthew Dillon b = m + 1; 2061645cafeSMatthew Dillon } 2071645cafeSMatthew Dillon } 2081645cafeSMatthew Dillon return NULL; 2091645cafeSMatthew Dillon } 2101645cafeSMatthew Dillon 2111645cafeSMatthew Dillon void 2121645cafeSMatthew Dillon scanit(const char *path, const char *subpath, 2131645cafeSMatthew Dillon int *countp, pinfo_t ***list_tailp) 2141645cafeSMatthew Dillon { 2151645cafeSMatthew Dillon struct dirent *den; 2161645cafeSMatthew Dillon pinfo_t *item; 2171645cafeSMatthew Dillon char *npath; 2181645cafeSMatthew Dillon char *spath; 2191645cafeSMatthew Dillon DIR *dir; 2201645cafeSMatthew Dillon struct stat st; 2211645cafeSMatthew Dillon 2221645cafeSMatthew Dillon if ((dir = opendir(path)) != NULL) { 2231645cafeSMatthew Dillon while ((den = readdir(dir)) != NULL) { 2241645cafeSMatthew Dillon if (den->d_namlen == 1 && den->d_name[0] == '.') 2251645cafeSMatthew Dillon continue; 2261645cafeSMatthew Dillon if (den->d_namlen == 2 && den->d_name[0] == '.' && 2271645cafeSMatthew Dillon den->d_name[1] == '.') 2281645cafeSMatthew Dillon continue; 2291645cafeSMatthew Dillon asprintf(&npath, "%s/%s", path, den->d_name); 2301645cafeSMatthew Dillon if (lstat(npath, &st) < 0) { 2311645cafeSMatthew Dillon free(npath); 2321645cafeSMatthew Dillon continue; 2331645cafeSMatthew Dillon } 2341645cafeSMatthew Dillon if (S_ISDIR(st.st_mode)) { 2351645cafeSMatthew Dillon if (subpath) { 2361645cafeSMatthew Dillon asprintf(&spath, "%s/%s", 2371645cafeSMatthew Dillon subpath, den->d_name); 2381645cafeSMatthew Dillon scanit(npath, spath, 2391645cafeSMatthew Dillon countp, list_tailp); 2401645cafeSMatthew Dillon free(spath); 2411645cafeSMatthew Dillon } else { 2421645cafeSMatthew Dillon scanit(npath, den->d_name, 2431645cafeSMatthew Dillon countp, list_tailp); 2441645cafeSMatthew Dillon } 2451645cafeSMatthew Dillon } else if (S_ISREG(st.st_mode)) { 2461645cafeSMatthew Dillon item = calloc(1, sizeof(*item)); 2471645cafeSMatthew Dillon if (subpath) { 2481645cafeSMatthew Dillon asprintf(&item->spath, "%s/%s", 2491645cafeSMatthew Dillon subpath, den->d_name); 2501645cafeSMatthew Dillon } else { 2511645cafeSMatthew Dillon item->spath = strdup(den->d_name); 2521645cafeSMatthew Dillon } 2531645cafeSMatthew Dillon **list_tailp = item; 2541645cafeSMatthew Dillon *list_tailp = &item->next; 2551645cafeSMatthew Dillon ++*countp; 2561645cafeSMatthew Dillon ddprintf(0, "scan %s\n", item->spath); 2571645cafeSMatthew Dillon } 258*6a3a20b1SMatthew Dillon free(npath); 2591645cafeSMatthew Dillon } 2601645cafeSMatthew Dillon closedir(dir); 2611645cafeSMatthew Dillon } 2621645cafeSMatthew Dillon } 263f7f25838SMatthew Dillon 264f7f25838SMatthew Dillon /* 265f7f25838SMatthew Dillon * This removes any .new files left over in the repo. These can wind 266f7f25838SMatthew Dillon * being left around when dsynth is killed. 267f7f25838SMatthew Dillon */ 268f7f25838SMatthew Dillon static void 269f7f25838SMatthew Dillon scandeletenew(const char *path) 270f7f25838SMatthew Dillon { 271f7f25838SMatthew Dillon struct dirent *den; 272f7f25838SMatthew Dillon const char *ptr; 273f7f25838SMatthew Dillon DIR *dir; 274f7f25838SMatthew Dillon char *buf; 275f7f25838SMatthew Dillon 276f7f25838SMatthew Dillon if ((dir = opendir(path)) == NULL) 277f7f25838SMatthew Dillon dfatal_errno("Cannot scan directory %s", path); 278f7f25838SMatthew Dillon while ((den = readdir(dir)) != NULL) { 279f7f25838SMatthew Dillon if ((ptr = strrchr(den->d_name, '.')) != NULL && 280f7f25838SMatthew Dillon strcmp(ptr, ".new") == 0) { 281f7f25838SMatthew Dillon asprintf(&buf, "%s/%s", path, den->d_name); 282f7f25838SMatthew Dillon if (remove(buf) < 0) 283f7f25838SMatthew Dillon dfatal_errno("remove: Garbage %s\n", buf); 284f7f25838SMatthew Dillon printf("Deleted Garbage %s\n", buf); 285f7f25838SMatthew Dillon free(buf); 286f7f25838SMatthew Dillon } 287f7f25838SMatthew Dillon } 288f7f25838SMatthew Dillon closedir(dir); 289f7f25838SMatthew Dillon } 290