xref: /dflybsd-src/usr.bin/dsynth/repo.c (revision 066daf2a487e53af6dc7229324ef705f249bcdff)
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 
45f4094b20SMatthew Dillon static void removePackagesMetaRecurse(pkg_t *pkg);
461645cafeSMatthew Dillon static int pinfocmp(const void *s1, const void *s2);
471645cafeSMatthew Dillon static void scanit(const char *path, const char *subpath,
481645cafeSMatthew Dillon 			int *countp, pinfo_t ***list_tailp);
491645cafeSMatthew Dillon pinfo_t *pinfofind(pinfo_t **ary, int count, char *spath);
50*066daf2aSMatthew Dillon static void childRebuildRepo(bulk_t *bulk);
51f7f25838SMatthew Dillon static void scandeletenew(const char *path);
521645cafeSMatthew Dillon 
53*066daf2aSMatthew Dillon static void rebuildTerminateSignal(int signo);
54*066daf2aSMatthew Dillon 
55*066daf2aSMatthew Dillon static char *RebuildRemovePath;
56*066daf2aSMatthew Dillon 
578e25f19bSMatthew Dillon void
581645cafeSMatthew Dillon DoRebuildRepo(int ask)
598e25f19bSMatthew Dillon {
60*066daf2aSMatthew Dillon 	bulk_t *bulk;
61*066daf2aSMatthew Dillon 	FILE *fp;
62*066daf2aSMatthew Dillon 	int fd;
63*066daf2aSMatthew Dillon 	char tpath[256];
641645cafeSMatthew Dillon 
651645cafeSMatthew Dillon 	if (ask) {
661645cafeSMatthew Dillon 		if (askyn("Rebuild the repository? ") == 0)
671645cafeSMatthew Dillon 			return;
681645cafeSMatthew Dillon 	}
69f7f25838SMatthew Dillon 
70f7f25838SMatthew Dillon 	/*
71f7f25838SMatthew Dillon 	 * Scan the repository for temporary .new files and delete them.
72f7f25838SMatthew Dillon 	 */
73f7f25838SMatthew Dillon 	scandeletenew(RepositoryPath);
74f7f25838SMatthew Dillon 
75f7f25838SMatthew Dillon 	/*
76*066daf2aSMatthew Dillon 	 * Generate temporary file
77f7f25838SMatthew Dillon 	 */
78*066daf2aSMatthew Dillon 	snprintf(tpath, sizeof(tpath), "/tmp/meta.XXXXXXXX.conf");
79*066daf2aSMatthew Dillon 
80*066daf2aSMatthew Dillon 	signal(SIGTERM, rebuildTerminateSignal);
81*066daf2aSMatthew Dillon 	signal(SIGINT, rebuildTerminateSignal);
82*066daf2aSMatthew Dillon 	signal(SIGHUP, rebuildTerminateSignal);
83*066daf2aSMatthew Dillon 
84*066daf2aSMatthew Dillon 	RebuildRemovePath = tpath;
85*066daf2aSMatthew Dillon 
86*066daf2aSMatthew Dillon 	fd = mkostemps(tpath, 5, 0);
87*066daf2aSMatthew Dillon 	if (fd < 0)
88*066daf2aSMatthew Dillon 		dfatal_errno("Cannot create %s", tpath);
89*066daf2aSMatthew Dillon 	fp = fdopen(fd, "w");
90*066daf2aSMatthew Dillon 	fprintf(fp, "version = 1;\n");
91*066daf2aSMatthew Dillon 	fprintf(fp, "packing_format = \"%s\";\n", USE_PKG_SUFX + 1);
92*066daf2aSMatthew Dillon 	fclose(fp);
93*066daf2aSMatthew Dillon 
94*066daf2aSMatthew Dillon 	/*
95*066daf2aSMatthew Dillon 	 * Run the operation under our bulk infrastructure to
96*066daf2aSMatthew Dillon 	 * get the correct environment.
97*066daf2aSMatthew Dillon 	 */
98*066daf2aSMatthew Dillon 	initbulk(childRebuildRepo, 1);
99*066daf2aSMatthew Dillon 	queuebulk(tpath, NULL, NULL, NULL);
100*066daf2aSMatthew Dillon 	bulk = getbulk();
101*066daf2aSMatthew Dillon 
102*066daf2aSMatthew Dillon 	if (bulk->r1)
1031645cafeSMatthew Dillon 		printf("Rebuild succeeded\n");
104*066daf2aSMatthew Dillon 	else
105*066daf2aSMatthew Dillon 		printf("Rebuild failed\n");
106*066daf2aSMatthew Dillon 	donebulk();
107*066daf2aSMatthew Dillon 
108*066daf2aSMatthew Dillon 	remove(tpath);
109*066daf2aSMatthew Dillon }
110*066daf2aSMatthew Dillon 
111*066daf2aSMatthew Dillon static void
112*066daf2aSMatthew Dillon childRebuildRepo(bulk_t *bulk)
113*066daf2aSMatthew Dillon {
114*066daf2aSMatthew Dillon 	FILE *fp;
115*066daf2aSMatthew Dillon 	char *ptr;
116*066daf2aSMatthew Dillon 	size_t len;
117*066daf2aSMatthew Dillon 	pid_t pid;
118*066daf2aSMatthew Dillon 	const char *cav[MAXCAC];
119*066daf2aSMatthew Dillon 	int cac;
120*066daf2aSMatthew Dillon 
121*066daf2aSMatthew Dillon 	cac = 0;
122*066daf2aSMatthew Dillon 	cav[cac++] = PKG_BINARY;
123*066daf2aSMatthew Dillon 	cav[cac++] = "repo";
124*066daf2aSMatthew Dillon 	cav[cac++] = "-m";
125*066daf2aSMatthew Dillon 	cav[cac++] = bulk->s1;
126*066daf2aSMatthew Dillon 	cav[cac++] = "-o";
127*066daf2aSMatthew Dillon 	cav[cac++] = PackagesPath;
128*066daf2aSMatthew Dillon 	cav[cac++] = RepositoryPath;
129*066daf2aSMatthew Dillon 
130*066daf2aSMatthew Dillon 	printf("pkg repo -m %s -o %s %s\n",
131*066daf2aSMatthew Dillon 	       bulk->s1, PackagesPath, RepositoryPath);
132*066daf2aSMatthew Dillon 
133*066daf2aSMatthew Dillon 	fp = dexec_open(cav, cac, &pid, 1, 0);
134*066daf2aSMatthew Dillon 	while ((ptr = fgetln(fp, &len)) != NULL)
135*066daf2aSMatthew Dillon 		fwrite(ptr, 1, len, stdout);
136*066daf2aSMatthew Dillon 	if (dexec_close(fp, pid) == 0) {
137*066daf2aSMatthew Dillon 		bulk->r1 = strdup("");
1381645cafeSMatthew Dillon 	}
1398e25f19bSMatthew Dillon }
1408e25f19bSMatthew Dillon 
1418e25f19bSMatthew Dillon void
1428e25f19bSMatthew Dillon DoUpgradePkgs(pkg_t *pkgs __unused, int ask __unused)
1438e25f19bSMatthew Dillon {
1448e25f19bSMatthew Dillon 	dfatal("Not Implemented");
1458e25f19bSMatthew Dillon }
1468e25f19bSMatthew Dillon 
1478e25f19bSMatthew Dillon void
1481645cafeSMatthew Dillon PurgeDistfiles(pkg_t *pkgs)
1498e25f19bSMatthew Dillon {
1501645cafeSMatthew Dillon 	pinfo_t *list;
1511645cafeSMatthew Dillon 	pinfo_t *item;
1521645cafeSMatthew Dillon 	pinfo_t **list_tail;
1531645cafeSMatthew Dillon 	pinfo_t **ary;
1541645cafeSMatthew Dillon 	char *dstr;
1551645cafeSMatthew Dillon 	char *buf;
1561645cafeSMatthew Dillon 	int count;
1571645cafeSMatthew Dillon 	int delcount;
1581645cafeSMatthew Dillon 	int i;
1591645cafeSMatthew Dillon 
1601645cafeSMatthew Dillon 	printf("Scanning distfiles... ");
1611645cafeSMatthew Dillon 	fflush(stdout);
1621645cafeSMatthew Dillon 	count = 0;
1631645cafeSMatthew Dillon 	list = NULL;
1641645cafeSMatthew Dillon 	list_tail = &list;
1651645cafeSMatthew Dillon 	scanit(DistFilesPath, NULL, &count, &list_tail);
1661645cafeSMatthew Dillon 	printf("Checking %d distfiles\n", count);
1671645cafeSMatthew Dillon 	fflush(stdout);
1681645cafeSMatthew Dillon 
1691645cafeSMatthew Dillon 	ary = calloc(count, sizeof(pinfo_t *));
1701645cafeSMatthew Dillon 	for (i = 0; i < count; ++i) {
1711645cafeSMatthew Dillon 		ary[i] = list;
1721645cafeSMatthew Dillon 		list = list->next;
1731645cafeSMatthew Dillon 	}
1741645cafeSMatthew Dillon 	ddassert(list == NULL);
1751645cafeSMatthew Dillon 	qsort(ary, count, sizeof(pinfo_t *), pinfocmp);
1761645cafeSMatthew Dillon 
1771645cafeSMatthew Dillon 	for (; pkgs; pkgs = pkgs->bnext) {
1781645cafeSMatthew Dillon 		if (pkgs->distfiles == NULL || pkgs->distfiles[0] == 0)
1791645cafeSMatthew Dillon 			continue;
1801645cafeSMatthew Dillon 		ddprintf(0, "distfiles %s\n", pkgs->distfiles);
1811645cafeSMatthew Dillon 		dstr = strtok(pkgs->distfiles, " \t");
1821645cafeSMatthew Dillon 		while (dstr) {
1831645cafeSMatthew Dillon 			for (;;) {
1844ea2ee4dSMatthew Dillon 				if (pkgs->distsubdir) {
1851645cafeSMatthew Dillon 					asprintf(&buf, "%s/%s",
1861645cafeSMatthew Dillon 						 pkgs->distsubdir, dstr);
1871645cafeSMatthew Dillon 					item = pinfofind(ary, count, buf);
1881645cafeSMatthew Dillon 					ddprintf(0, "TEST %s %p\n", buf, item);
1891645cafeSMatthew Dillon 					free(buf);
1901645cafeSMatthew Dillon 					buf = NULL;
1911645cafeSMatthew Dillon 				} else {
1921645cafeSMatthew Dillon 					item = pinfofind(ary, count, dstr);
1931645cafeSMatthew Dillon 					ddprintf(0, "TEST %s %p\n", dstr, item);
1941645cafeSMatthew Dillon 				}
1951645cafeSMatthew Dillon 				if (item) {
1961645cafeSMatthew Dillon 					item->foundit = 1;
1971645cafeSMatthew Dillon 					break;
1981645cafeSMatthew Dillon 				}
1991645cafeSMatthew Dillon 				if (strrchr(dstr, ':') == NULL)
2001645cafeSMatthew Dillon 					break;
2011645cafeSMatthew Dillon 				*strrchr(dstr, ':') = 0;
2021645cafeSMatthew Dillon 			}
2031645cafeSMatthew Dillon 			dstr = strtok(NULL, " \t");
2041645cafeSMatthew Dillon 		}
2051645cafeSMatthew Dillon 	}
2061645cafeSMatthew Dillon 
2071645cafeSMatthew Dillon 	delcount = 0;
2081645cafeSMatthew Dillon 	for (i = 0; i < count; ++i) {
2091645cafeSMatthew Dillon 		item = ary[i];
2101645cafeSMatthew Dillon 		if (item->foundit == 0) {
2111645cafeSMatthew Dillon 			++delcount;
2121645cafeSMatthew Dillon 		}
2131645cafeSMatthew Dillon 	}
2141645cafeSMatthew Dillon 	if (askyn("Delete %d of %d items? ", delcount, count)) {
2151645cafeSMatthew Dillon 		printf("Deleting %d/%d obsolete source distfiles\n",
2161645cafeSMatthew Dillon 		       delcount, count);
2171645cafeSMatthew Dillon 		for (i = 0; i < count; ++i) {
2181645cafeSMatthew Dillon 			item = ary[i];
2191645cafeSMatthew Dillon 			if (item->foundit == 0) {
2201645cafeSMatthew Dillon 				asprintf(&buf, "%s/%s",
2211645cafeSMatthew Dillon 					 DistFilesPath, item->spath);
2221645cafeSMatthew Dillon 				if (remove(buf) < 0)
2231645cafeSMatthew Dillon 					printf("Cannot delete %s\n", buf);
2241645cafeSMatthew Dillon 				free(buf);
2251645cafeSMatthew Dillon 			}
2261645cafeSMatthew Dillon 		}
2271645cafeSMatthew Dillon 	}
2281645cafeSMatthew Dillon 
2291645cafeSMatthew Dillon 
2301645cafeSMatthew Dillon 	free(ary);
2318e25f19bSMatthew Dillon }
2328e25f19bSMatthew Dillon 
2338e25f19bSMatthew Dillon void
234f4094b20SMatthew Dillon RemovePackages(pkg_t *list)
2358e25f19bSMatthew Dillon {
236f4094b20SMatthew Dillon 	pkg_t *scan;
237f4094b20SMatthew Dillon 	char *path;
238f4094b20SMatthew Dillon 
239f4094b20SMatthew Dillon 	for (scan = list; scan; scan = scan->bnext) {
240f4094b20SMatthew Dillon 		if ((scan->flags & PKGF_MANUALSEL) == 0)
241f4094b20SMatthew Dillon 			continue;
242f4094b20SMatthew Dillon 		if (scan->pkgfile) {
243f4094b20SMatthew Dillon 			scan->flags &= ~PKGF_PACKAGED;
244f4094b20SMatthew Dillon 			scan->pkgfile_size = 0;
245f4094b20SMatthew Dillon 			asprintf(&path, "%s/%s", RepositoryPath, scan->pkgfile);
246f4094b20SMatthew Dillon 			if (remove(path) == 0)
247f4094b20SMatthew Dillon 				printf("Removed: %s\n", path);
248f4094b20SMatthew Dillon 			free(path);
249f4094b20SMatthew Dillon 		}
250f4094b20SMatthew Dillon 		if (scan->pkgfile == NULL ||
251f4094b20SMatthew Dillon 		    (scan->flags & (PKGF_DUMMY | PKGF_META))) {
252f4094b20SMatthew Dillon 			removePackagesMetaRecurse(scan);
253f4094b20SMatthew Dillon 		}
254f4094b20SMatthew Dillon 	}
255f4094b20SMatthew Dillon }
256f4094b20SMatthew Dillon 
257f4094b20SMatthew Dillon static void
258f4094b20SMatthew Dillon removePackagesMetaRecurse(pkg_t *pkg)
259f4094b20SMatthew Dillon {
260f4094b20SMatthew Dillon 	pkglink_t *link;
261f4094b20SMatthew Dillon 	pkg_t *scan;
262f4094b20SMatthew Dillon 	char *path;
263f4094b20SMatthew Dillon 
264f4094b20SMatthew Dillon 	PKGLIST_FOREACH(link, &pkg->idepon_list) {
265f4094b20SMatthew Dillon 		scan = link->pkg;
266f4094b20SMatthew Dillon 		if (scan == NULL)
267f4094b20SMatthew Dillon 			continue;
268f4094b20SMatthew Dillon 		if (scan->pkgfile == NULL ||
269f4094b20SMatthew Dillon 		    (scan->flags & (PKGF_DUMMY | PKGF_META))) {
270f4094b20SMatthew Dillon 			removePackagesMetaRecurse(scan);
271f4094b20SMatthew Dillon 			continue;
272f4094b20SMatthew Dillon 		}
273f4094b20SMatthew Dillon 		scan->flags &= ~PKGF_PACKAGED;
274f4094b20SMatthew Dillon 		scan->pkgfile_size = 0;
275f4094b20SMatthew Dillon 
276f4094b20SMatthew Dillon 		asprintf(&path, "%s/%s", RepositoryPath, scan->pkgfile);
277f4094b20SMatthew Dillon 		if (remove(path) == 0)
278f4094b20SMatthew Dillon 			printf("Removed: %s\n", path);
279f4094b20SMatthew Dillon 		free(path);
280f4094b20SMatthew Dillon 	}
2818e25f19bSMatthew Dillon }
2821645cafeSMatthew Dillon 
2831645cafeSMatthew Dillon static int
2841645cafeSMatthew Dillon pinfocmp(const void *s1, const void *s2)
2851645cafeSMatthew Dillon {
2861645cafeSMatthew Dillon 	const pinfo_t *item1 = *(const pinfo_t *const*)s1;
2871645cafeSMatthew Dillon 	const pinfo_t *item2 = *(const pinfo_t *const*)s2;
2881645cafeSMatthew Dillon 
2891645cafeSMatthew Dillon 	return (strcmp(item1->spath, item2->spath));
2901645cafeSMatthew Dillon }
2911645cafeSMatthew Dillon 
2921645cafeSMatthew Dillon pinfo_t *
2931645cafeSMatthew Dillon pinfofind(pinfo_t **ary, int count, char *spath)
2941645cafeSMatthew Dillon {
2951645cafeSMatthew Dillon 	pinfo_t *item;
2961645cafeSMatthew Dillon 	int res;
2971645cafeSMatthew Dillon 	int b;
2981645cafeSMatthew Dillon 	int e;
2991645cafeSMatthew Dillon 	int m;
3001645cafeSMatthew Dillon 
3011645cafeSMatthew Dillon 	b = 0;
3021645cafeSMatthew Dillon 	e = count;
3031645cafeSMatthew Dillon 	while (b != e) {
3041645cafeSMatthew Dillon 		m = b + (e - b) / 2;
3051645cafeSMatthew Dillon 		item = ary[m];
3061645cafeSMatthew Dillon 		res = strcmp(spath, item->spath);
3071645cafeSMatthew Dillon 		if (res == 0)
3081645cafeSMatthew Dillon 			return item;
3091645cafeSMatthew Dillon 		if (res < 0) {
3101645cafeSMatthew Dillon 			e = m;
3111645cafeSMatthew Dillon 		} else {
3121645cafeSMatthew Dillon 			b = m + 1;
3131645cafeSMatthew Dillon 		}
3141645cafeSMatthew Dillon 	}
3151645cafeSMatthew Dillon 	return NULL;
3161645cafeSMatthew Dillon }
3171645cafeSMatthew Dillon 
3181645cafeSMatthew Dillon void
3191645cafeSMatthew Dillon scanit(const char *path, const char *subpath,
3201645cafeSMatthew Dillon        int *countp, pinfo_t ***list_tailp)
3211645cafeSMatthew Dillon {
3221645cafeSMatthew Dillon 	struct dirent *den;
3231645cafeSMatthew Dillon 	pinfo_t *item;
3241645cafeSMatthew Dillon 	char *npath;
3251645cafeSMatthew Dillon 	char *spath;
3261645cafeSMatthew Dillon 	DIR *dir;
3271645cafeSMatthew Dillon 	struct stat st;
3281645cafeSMatthew Dillon 
3291645cafeSMatthew Dillon 	if ((dir = opendir(path)) != NULL) {
3301645cafeSMatthew Dillon 		while ((den = readdir(dir)) != NULL) {
3311645cafeSMatthew Dillon 			if (den->d_namlen == 1 && den->d_name[0] == '.')
3321645cafeSMatthew Dillon 				continue;
3331645cafeSMatthew Dillon 			if (den->d_namlen == 2 && den->d_name[0] == '.' &&
3341645cafeSMatthew Dillon 			    den->d_name[1] == '.')
3351645cafeSMatthew Dillon 				continue;
3361645cafeSMatthew Dillon 			asprintf(&npath, "%s/%s", path, den->d_name);
3371645cafeSMatthew Dillon 			if (lstat(npath, &st) < 0) {
3381645cafeSMatthew Dillon 				free(npath);
3391645cafeSMatthew Dillon 				continue;
3401645cafeSMatthew Dillon 			}
3411645cafeSMatthew Dillon 			if (S_ISDIR(st.st_mode)) {
3421645cafeSMatthew Dillon 				if (subpath) {
3431645cafeSMatthew Dillon 					asprintf(&spath, "%s/%s",
3441645cafeSMatthew Dillon 						 subpath, den->d_name);
3451645cafeSMatthew Dillon 					scanit(npath, spath,
3461645cafeSMatthew Dillon 					       countp, list_tailp);
3471645cafeSMatthew Dillon 					free(spath);
3481645cafeSMatthew Dillon 				} else {
3491645cafeSMatthew Dillon 					scanit(npath, den->d_name,
3501645cafeSMatthew Dillon 					       countp, list_tailp);
3511645cafeSMatthew Dillon 				}
3521645cafeSMatthew Dillon 			} else if (S_ISREG(st.st_mode)) {
3531645cafeSMatthew Dillon 				item = calloc(1, sizeof(*item));
3541645cafeSMatthew Dillon 				if (subpath) {
3551645cafeSMatthew Dillon 					asprintf(&item->spath, "%s/%s",
3561645cafeSMatthew Dillon 						 subpath, den->d_name);
3571645cafeSMatthew Dillon 				} else {
3581645cafeSMatthew Dillon 					item->spath = strdup(den->d_name);
3591645cafeSMatthew Dillon 				}
3601645cafeSMatthew Dillon 				**list_tailp = item;
3611645cafeSMatthew Dillon 				*list_tailp = &item->next;
3621645cafeSMatthew Dillon 				++*countp;
3631645cafeSMatthew Dillon 				ddprintf(0, "scan   %s\n", item->spath);
3641645cafeSMatthew Dillon 			}
3656a3a20b1SMatthew Dillon 			free(npath);
3661645cafeSMatthew Dillon 		}
3671645cafeSMatthew Dillon 		closedir(dir);
3681645cafeSMatthew Dillon 	}
3691645cafeSMatthew Dillon }
370f7f25838SMatthew Dillon 
371f7f25838SMatthew Dillon /*
372f7f25838SMatthew Dillon  * This removes any .new files left over in the repo.  These can wind
373f7f25838SMatthew Dillon  * being left around when dsynth is killed.
374f7f25838SMatthew Dillon  */
375f7f25838SMatthew Dillon static void
376f7f25838SMatthew Dillon scandeletenew(const char *path)
377f7f25838SMatthew Dillon {
378f7f25838SMatthew Dillon 	struct dirent *den;
379f7f25838SMatthew Dillon 	const char *ptr;
380f7f25838SMatthew Dillon 	DIR *dir;
381f7f25838SMatthew Dillon 	char *buf;
382f7f25838SMatthew Dillon 
383f7f25838SMatthew Dillon 	if ((dir = opendir(path)) == NULL)
384f7f25838SMatthew Dillon 		dfatal_errno("Cannot scan directory %s", path);
385f7f25838SMatthew Dillon 	while ((den = readdir(dir)) != NULL) {
386f7f25838SMatthew Dillon 		if ((ptr = strrchr(den->d_name, '.')) != NULL &&
387f7f25838SMatthew Dillon 		    strcmp(ptr, ".new") == 0) {
388f7f25838SMatthew Dillon 			asprintf(&buf, "%s/%s", path, den->d_name);
389f7f25838SMatthew Dillon 			if (remove(buf) < 0)
390f7f25838SMatthew Dillon 				dfatal_errno("remove: Garbage %s\n", buf);
391f7f25838SMatthew Dillon 			printf("Deleted Garbage %s\n", buf);
392f7f25838SMatthew Dillon 			free(buf);
393f7f25838SMatthew Dillon 		}
394f7f25838SMatthew Dillon 	}
395f7f25838SMatthew Dillon 	closedir(dir);
396f7f25838SMatthew Dillon }
397*066daf2aSMatthew Dillon 
398*066daf2aSMatthew Dillon static void
399*066daf2aSMatthew Dillon rebuildTerminateSignal(int signo __unused)
400*066daf2aSMatthew Dillon {
401*066daf2aSMatthew Dillon 	if (RebuildRemovePath)
402*066daf2aSMatthew Dillon 		remove(RebuildRemovePath);
403*066daf2aSMatthew Dillon 	exit(1);
404*066daf2aSMatthew Dillon 
405*066daf2aSMatthew Dillon }
406