xref: /dflybsd-src/usr.bin/dsynth/repo.c (revision 96cc8f92ce28dbc4069c94b7988d221b2bd0cd12)
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);
50066daf2aSMatthew Dillon static void childRebuildRepo(bulk_t *bulk);
51f7f25838SMatthew Dillon static void scandeletenew(const char *path);
521645cafeSMatthew Dillon 
53066daf2aSMatthew Dillon static void rebuildTerminateSignal(int signo);
54066daf2aSMatthew Dillon 
55066daf2aSMatthew Dillon static char *RebuildRemovePath;
56066daf2aSMatthew Dillon 
578e25f19bSMatthew Dillon void
581645cafeSMatthew Dillon DoRebuildRepo(int ask)
598e25f19bSMatthew Dillon {
60066daf2aSMatthew Dillon 	bulk_t *bulk;
61066daf2aSMatthew Dillon 	FILE *fp;
62066daf2aSMatthew Dillon 	int fd;
63066daf2aSMatthew Dillon 	char tpath[256];
6468dc2eeaSMatthew Dillon 	const char *sufx;
651645cafeSMatthew Dillon 
661645cafeSMatthew Dillon 	if (ask) {
671645cafeSMatthew Dillon 		if (askyn("Rebuild the repository? ") == 0)
681645cafeSMatthew Dillon 			return;
691645cafeSMatthew Dillon 	}
70f7f25838SMatthew Dillon 
71f7f25838SMatthew Dillon 	/*
72f7f25838SMatthew Dillon 	 * Scan the repository for temporary .new files and delete them.
73f7f25838SMatthew Dillon 	 */
74f7f25838SMatthew Dillon 	scandeletenew(RepositoryPath);
75f7f25838SMatthew Dillon 
76f7f25838SMatthew Dillon 	/*
77066daf2aSMatthew Dillon 	 * Generate temporary file
78f7f25838SMatthew Dillon 	 */
79066daf2aSMatthew Dillon 	snprintf(tpath, sizeof(tpath), "/tmp/meta.XXXXXXXX.conf");
80066daf2aSMatthew Dillon 
81066daf2aSMatthew Dillon 	signal(SIGTERM, rebuildTerminateSignal);
82066daf2aSMatthew Dillon 	signal(SIGINT, rebuildTerminateSignal);
83066daf2aSMatthew Dillon 	signal(SIGHUP, rebuildTerminateSignal);
84066daf2aSMatthew Dillon 
85066daf2aSMatthew Dillon 	RebuildRemovePath = tpath;
86066daf2aSMatthew Dillon 
87483dbac9SMatthew Dillon 	sufx = UsePkgSufx;
88066daf2aSMatthew Dillon 	fd = mkostemps(tpath, 5, 0);
89066daf2aSMatthew Dillon 	if (fd < 0)
90066daf2aSMatthew Dillon 		dfatal_errno("Cannot create %s", tpath);
91066daf2aSMatthew Dillon 	fp = fdopen(fd, "w");
92066daf2aSMatthew Dillon 	fprintf(fp, "version = 1;\n");
9368dc2eeaSMatthew Dillon 	fprintf(fp, "packing_format = \"%s\";\n", sufx + 1);
94066daf2aSMatthew Dillon 	fclose(fp);
95066daf2aSMatthew Dillon 
96066daf2aSMatthew Dillon 	/*
97066daf2aSMatthew Dillon 	 * Run the operation under our bulk infrastructure to
98066daf2aSMatthew Dillon 	 * get the correct environment.
99066daf2aSMatthew Dillon 	 */
100066daf2aSMatthew Dillon 	initbulk(childRebuildRepo, 1);
101066daf2aSMatthew Dillon 	queuebulk(tpath, NULL, NULL, NULL);
102066daf2aSMatthew Dillon 	bulk = getbulk();
103066daf2aSMatthew Dillon 
104066daf2aSMatthew Dillon 	if (bulk->r1)
1051645cafeSMatthew Dillon 		printf("Rebuild succeeded\n");
106066daf2aSMatthew Dillon 	else
107066daf2aSMatthew Dillon 		printf("Rebuild failed\n");
108066daf2aSMatthew Dillon 	donebulk();
109066daf2aSMatthew Dillon 
110066daf2aSMatthew Dillon 	remove(tpath);
111066daf2aSMatthew Dillon }
112066daf2aSMatthew Dillon 
113066daf2aSMatthew Dillon static void
114cda252a4SMatthew Dillon repackage(const char *basepath, const char *basefile, const char *sufx,
115cda252a4SMatthew Dillon 	  const char *comp, const char *decomp);
116cda252a4SMatthew Dillon 
117cda252a4SMatthew Dillon static void
118066daf2aSMatthew Dillon childRebuildRepo(bulk_t *bulk)
119066daf2aSMatthew Dillon {
120066daf2aSMatthew Dillon 	FILE *fp;
121066daf2aSMatthew Dillon 	char *ptr;
122066daf2aSMatthew Dillon 	size_t len;
123066daf2aSMatthew Dillon 	pid_t pid;
124066daf2aSMatthew Dillon 	const char *cav[MAXCAC];
125066daf2aSMatthew Dillon 	int cac;
126*96cc8f92SMatthew Dillon 	int repackage_needed = 1;
127066daf2aSMatthew Dillon 
128066daf2aSMatthew Dillon 	cac = 0;
129066daf2aSMatthew Dillon 	cav[cac++] = PKG_BINARY;
130066daf2aSMatthew Dillon 	cav[cac++] = "repo";
131066daf2aSMatthew Dillon 	cav[cac++] = "-m";
132066daf2aSMatthew Dillon 	cav[cac++] = bulk->s1;
133066daf2aSMatthew Dillon 	cav[cac++] = "-o";
134066daf2aSMatthew Dillon 	cav[cac++] = PackagesPath;
135cda252a4SMatthew Dillon 
136cda252a4SMatthew Dillon 	/*
137cda252a4SMatthew Dillon 	 * The yaml needs to generate paths relative to PackagePath
138cda252a4SMatthew Dillon 	 */
139cda252a4SMatthew Dillon 	if (strncmp(PackagesPath, RepositoryPath, strlen(PackagesPath)) == 0)
140cda252a4SMatthew Dillon 		cav[cac++] = PackagesPath;
141cda252a4SMatthew Dillon 	else
142066daf2aSMatthew Dillon 		cav[cac++] = RepositoryPath;
143066daf2aSMatthew Dillon 
144cda252a4SMatthew Dillon 	printf("pkg repo -m %s -o %s %s\n", bulk->s1, cav[cac-2], cav[cac-1]);
145066daf2aSMatthew Dillon 
14668dc2eeaSMatthew Dillon 	fp = dexec_open(cav, cac, &pid, NULL, 1, 0);
147066daf2aSMatthew Dillon 	while ((ptr = fgetln(fp, &len)) != NULL)
148066daf2aSMatthew Dillon 		fwrite(ptr, 1, len, stdout);
149*96cc8f92SMatthew Dillon 	if (dexec_close(fp, pid) == 0)
150066daf2aSMatthew Dillon 		bulk->r1 = strdup("");
151*96cc8f92SMatthew Dillon 
152*96cc8f92SMatthew Dillon 	/*
153*96cc8f92SMatthew Dillon 	 * Check package version.  Pkg version 1.12 and later generates
154*96cc8f92SMatthew Dillon 	 * the proper repo compression format.  Prior to that version
155*96cc8f92SMatthew Dillon 	 * the repo directive always generated .txz files.
156*96cc8f92SMatthew Dillon 	 */
157*96cc8f92SMatthew Dillon 	cac = 0;
158*96cc8f92SMatthew Dillon 	cav[cac++] = PKG_BINARY;
159*96cc8f92SMatthew Dillon 	cav[cac++] = "-v";
160*96cc8f92SMatthew Dillon 	fp = dexec_open(cav, cac, &pid, NULL, 1, 0);
161*96cc8f92SMatthew Dillon 	if ((ptr = fgetln(fp, &len)) != NULL && len > 0) {
162*96cc8f92SMatthew Dillon 		int v1;
163*96cc8f92SMatthew Dillon 		int v2;
164*96cc8f92SMatthew Dillon 
165*96cc8f92SMatthew Dillon 		ptr[len-1] = 0;
166*96cc8f92SMatthew Dillon 		if (sscanf(ptr, "%d.%d", &v1, &v2) == 2) {
167*96cc8f92SMatthew Dillon 			if (v1 > 1 || (v1 == 1 && v2 >= 12))
168*96cc8f92SMatthew Dillon 				repackage_needed = 0;
1691645cafeSMatthew Dillon 		}
170*96cc8f92SMatthew Dillon 	}
171*96cc8f92SMatthew Dillon 	dexec_close(fp, pid);
172cda252a4SMatthew Dillon 
173cda252a4SMatthew Dillon 	/*
174cda252a4SMatthew Dillon 	 * Repackage the .txz files created by pkg repo if necessary
175cda252a4SMatthew Dillon 	 */
176*96cc8f92SMatthew Dillon 	if (repackage_needed && strcmp(UsePkgSufx, ".txz") != 0) {
177cda252a4SMatthew Dillon 		const char *comp;
178cda252a4SMatthew Dillon 		const char *decomp;
179cda252a4SMatthew Dillon 
180*96cc8f92SMatthew Dillon 		printf("pkg repo - version requires repackaging\n");
181*96cc8f92SMatthew Dillon 
182483dbac9SMatthew Dillon 		if (strcmp(UsePkgSufx, ".tar") == 0) {
183cda252a4SMatthew Dillon 			decomp = "unxz";
184cda252a4SMatthew Dillon 			comp = "cat";
185483dbac9SMatthew Dillon 		} else if (strcmp(UsePkgSufx, ".tgz") == 0) {
186cda252a4SMatthew Dillon 			decomp = "unxz";
187cda252a4SMatthew Dillon 			comp = "gzip";
188483dbac9SMatthew Dillon 		} else if (strcmp(UsePkgSufx, ".tbz") == 0) {
189cda252a4SMatthew Dillon 			decomp = "unxz";
190cda252a4SMatthew Dillon 			comp = "bzip";
191cda252a4SMatthew Dillon 		} else {
192483dbac9SMatthew Dillon 			dfatal("repackaging as %s not supported", UsePkgSufx);
193cda252a4SMatthew Dillon 			decomp = "unxz";
194cda252a4SMatthew Dillon 			comp = "cat";
195cda252a4SMatthew Dillon 		}
196483dbac9SMatthew Dillon 		repackage(PackagesPath, "digests", UsePkgSufx,
197cda252a4SMatthew Dillon 			  comp, decomp);
198483dbac9SMatthew Dillon 		repackage(PackagesPath, "packagesite", UsePkgSufx,
199cda252a4SMatthew Dillon 			  comp, decomp);
200*96cc8f92SMatthew Dillon 	} else if (strcmp(UsePkgSufx, ".txz") != 0) {
201*96cc8f92SMatthew Dillon 		printf("pkg repo - version does not require repackaging\n");
202cda252a4SMatthew Dillon 	}
203cda252a4SMatthew Dillon }
204cda252a4SMatthew Dillon 
205cda252a4SMatthew Dillon static
206cda252a4SMatthew Dillon void
207cda252a4SMatthew Dillon repackage(const char *basepath, const char *basefile, const char *sufx,
208cda252a4SMatthew Dillon 	  const char *comp, const char *decomp)
209cda252a4SMatthew Dillon {
210cda252a4SMatthew Dillon 	char *buf;
211cda252a4SMatthew Dillon 
212cda252a4SMatthew Dillon 	asprintf(&buf, "%s < %s/%s.txz | %s > %s/%s%s",
213cda252a4SMatthew Dillon 		decomp, basepath, basefile, comp, basepath, basefile, sufx);
214cda252a4SMatthew Dillon 	if (system(buf) != 0) {
215cda252a4SMatthew Dillon 		dfatal("command failed: %s", buf);
216cda252a4SMatthew Dillon 	}
217cda252a4SMatthew Dillon 	free(buf);
2188e25f19bSMatthew Dillon }
2198e25f19bSMatthew Dillon 
2208e25f19bSMatthew Dillon void
2218e25f19bSMatthew Dillon DoUpgradePkgs(pkg_t *pkgs __unused, int ask __unused)
2228e25f19bSMatthew Dillon {
2238e25f19bSMatthew Dillon 	dfatal("Not Implemented");
2248e25f19bSMatthew Dillon }
2258e25f19bSMatthew Dillon 
2268e25f19bSMatthew Dillon void
2271645cafeSMatthew Dillon PurgeDistfiles(pkg_t *pkgs)
2288e25f19bSMatthew Dillon {
2291645cafeSMatthew Dillon 	pinfo_t *list;
2301645cafeSMatthew Dillon 	pinfo_t *item;
2311645cafeSMatthew Dillon 	pinfo_t **list_tail;
2321645cafeSMatthew Dillon 	pinfo_t **ary;
2331645cafeSMatthew Dillon 	char *dstr;
2341645cafeSMatthew Dillon 	char *buf;
2351645cafeSMatthew Dillon 	int count;
2361645cafeSMatthew Dillon 	int delcount;
2371645cafeSMatthew Dillon 	int i;
2381645cafeSMatthew Dillon 
2391645cafeSMatthew Dillon 	printf("Scanning distfiles... ");
2401645cafeSMatthew Dillon 	fflush(stdout);
2411645cafeSMatthew Dillon 	count = 0;
2421645cafeSMatthew Dillon 	list = NULL;
2431645cafeSMatthew Dillon 	list_tail = &list;
2441645cafeSMatthew Dillon 	scanit(DistFilesPath, NULL, &count, &list_tail);
2451645cafeSMatthew Dillon 	printf("Checking %d distfiles\n", count);
2461645cafeSMatthew Dillon 	fflush(stdout);
2471645cafeSMatthew Dillon 
2481645cafeSMatthew Dillon 	ary = calloc(count, sizeof(pinfo_t *));
2491645cafeSMatthew Dillon 	for (i = 0; i < count; ++i) {
2501645cafeSMatthew Dillon 		ary[i] = list;
2511645cafeSMatthew Dillon 		list = list->next;
2521645cafeSMatthew Dillon 	}
2531645cafeSMatthew Dillon 	ddassert(list == NULL);
2541645cafeSMatthew Dillon 	qsort(ary, count, sizeof(pinfo_t *), pinfocmp);
2551645cafeSMatthew Dillon 
2561645cafeSMatthew Dillon 	for (; pkgs; pkgs = pkgs->bnext) {
2571645cafeSMatthew Dillon 		if (pkgs->distfiles == NULL || pkgs->distfiles[0] == 0)
2581645cafeSMatthew Dillon 			continue;
2591645cafeSMatthew Dillon 		ddprintf(0, "distfiles %s\n", pkgs->distfiles);
2601645cafeSMatthew Dillon 		dstr = strtok(pkgs->distfiles, " \t");
2611645cafeSMatthew Dillon 		while (dstr) {
2621645cafeSMatthew Dillon 			for (;;) {
2634ea2ee4dSMatthew Dillon 				if (pkgs->distsubdir) {
2641645cafeSMatthew Dillon 					asprintf(&buf, "%s/%s",
2651645cafeSMatthew Dillon 						 pkgs->distsubdir, dstr);
2661645cafeSMatthew Dillon 					item = pinfofind(ary, count, buf);
2671645cafeSMatthew Dillon 					ddprintf(0, "TEST %s %p\n", buf, item);
2681645cafeSMatthew Dillon 					free(buf);
2691645cafeSMatthew Dillon 					buf = NULL;
2701645cafeSMatthew Dillon 				} else {
2711645cafeSMatthew Dillon 					item = pinfofind(ary, count, dstr);
2721645cafeSMatthew Dillon 					ddprintf(0, "TEST %s %p\n", dstr, item);
2731645cafeSMatthew Dillon 				}
2741645cafeSMatthew Dillon 				if (item) {
2751645cafeSMatthew Dillon 					item->foundit = 1;
2761645cafeSMatthew Dillon 					break;
2771645cafeSMatthew Dillon 				}
2781645cafeSMatthew Dillon 				if (strrchr(dstr, ':') == NULL)
2791645cafeSMatthew Dillon 					break;
2801645cafeSMatthew Dillon 				*strrchr(dstr, ':') = 0;
2811645cafeSMatthew Dillon 			}
2821645cafeSMatthew Dillon 			dstr = strtok(NULL, " \t");
2831645cafeSMatthew Dillon 		}
2841645cafeSMatthew Dillon 	}
2851645cafeSMatthew Dillon 
2861645cafeSMatthew Dillon 	delcount = 0;
2871645cafeSMatthew Dillon 	for (i = 0; i < count; ++i) {
2881645cafeSMatthew Dillon 		item = ary[i];
2891645cafeSMatthew Dillon 		if (item->foundit == 0) {
2901645cafeSMatthew Dillon 			++delcount;
2911645cafeSMatthew Dillon 		}
2921645cafeSMatthew Dillon 	}
2931645cafeSMatthew Dillon 	if (askyn("Delete %d of %d items? ", delcount, count)) {
2941645cafeSMatthew Dillon 		printf("Deleting %d/%d obsolete source distfiles\n",
2951645cafeSMatthew Dillon 		       delcount, count);
2961645cafeSMatthew Dillon 		for (i = 0; i < count; ++i) {
2971645cafeSMatthew Dillon 			item = ary[i];
2981645cafeSMatthew Dillon 			if (item->foundit == 0) {
2991645cafeSMatthew Dillon 				asprintf(&buf, "%s/%s",
3001645cafeSMatthew Dillon 					 DistFilesPath, item->spath);
3011645cafeSMatthew Dillon 				if (remove(buf) < 0)
3021645cafeSMatthew Dillon 					printf("Cannot delete %s\n", buf);
3031645cafeSMatthew Dillon 				free(buf);
3041645cafeSMatthew Dillon 			}
3051645cafeSMatthew Dillon 		}
3061645cafeSMatthew Dillon 	}
3071645cafeSMatthew Dillon 
3081645cafeSMatthew Dillon 
3091645cafeSMatthew Dillon 	free(ary);
3108e25f19bSMatthew Dillon }
3118e25f19bSMatthew Dillon 
3128e25f19bSMatthew Dillon void
313f4094b20SMatthew Dillon RemovePackages(pkg_t *list)
3148e25f19bSMatthew Dillon {
315f4094b20SMatthew Dillon 	pkg_t *scan;
316f4094b20SMatthew Dillon 	char *path;
317f4094b20SMatthew Dillon 
318f4094b20SMatthew Dillon 	for (scan = list; scan; scan = scan->bnext) {
319f4094b20SMatthew Dillon 		if ((scan->flags & PKGF_MANUALSEL) == 0)
320f4094b20SMatthew Dillon 			continue;
321f4094b20SMatthew Dillon 		if (scan->pkgfile) {
322f4094b20SMatthew Dillon 			scan->flags &= ~PKGF_PACKAGED;
323f4094b20SMatthew Dillon 			scan->pkgfile_size = 0;
324f4094b20SMatthew Dillon 			asprintf(&path, "%s/%s", RepositoryPath, scan->pkgfile);
325f4094b20SMatthew Dillon 			if (remove(path) == 0)
326f4094b20SMatthew Dillon 				printf("Removed: %s\n", path);
327f4094b20SMatthew Dillon 			free(path);
328f4094b20SMatthew Dillon 		}
329f4094b20SMatthew Dillon 		if (scan->pkgfile == NULL ||
330f4094b20SMatthew Dillon 		    (scan->flags & (PKGF_DUMMY | PKGF_META))) {
331f4094b20SMatthew Dillon 			removePackagesMetaRecurse(scan);
332f4094b20SMatthew Dillon 		}
333f4094b20SMatthew Dillon 	}
334f4094b20SMatthew Dillon }
335f4094b20SMatthew Dillon 
336f4094b20SMatthew Dillon static void
337f4094b20SMatthew Dillon removePackagesMetaRecurse(pkg_t *pkg)
338f4094b20SMatthew Dillon {
339f4094b20SMatthew Dillon 	pkglink_t *link;
340f4094b20SMatthew Dillon 	pkg_t *scan;
341f4094b20SMatthew Dillon 	char *path;
342f4094b20SMatthew Dillon 
343f4094b20SMatthew Dillon 	PKGLIST_FOREACH(link, &pkg->idepon_list) {
344f4094b20SMatthew Dillon 		scan = link->pkg;
345f4094b20SMatthew Dillon 		if (scan == NULL)
346f4094b20SMatthew Dillon 			continue;
347f4094b20SMatthew Dillon 		if (scan->pkgfile == NULL ||
348f4094b20SMatthew Dillon 		    (scan->flags & (PKGF_DUMMY | PKGF_META))) {
349f4094b20SMatthew Dillon 			removePackagesMetaRecurse(scan);
350f4094b20SMatthew Dillon 			continue;
351f4094b20SMatthew Dillon 		}
352f4094b20SMatthew Dillon 		scan->flags &= ~PKGF_PACKAGED;
353f4094b20SMatthew Dillon 		scan->pkgfile_size = 0;
354f4094b20SMatthew Dillon 
355f4094b20SMatthew Dillon 		asprintf(&path, "%s/%s", RepositoryPath, scan->pkgfile);
356f4094b20SMatthew Dillon 		if (remove(path) == 0)
357f4094b20SMatthew Dillon 			printf("Removed: %s\n", path);
358f4094b20SMatthew Dillon 		free(path);
359f4094b20SMatthew Dillon 	}
3608e25f19bSMatthew Dillon }
3611645cafeSMatthew Dillon 
3621645cafeSMatthew Dillon static int
3631645cafeSMatthew Dillon pinfocmp(const void *s1, const void *s2)
3641645cafeSMatthew Dillon {
3651645cafeSMatthew Dillon 	const pinfo_t *item1 = *(const pinfo_t *const*)s1;
3661645cafeSMatthew Dillon 	const pinfo_t *item2 = *(const pinfo_t *const*)s2;
3671645cafeSMatthew Dillon 
3681645cafeSMatthew Dillon 	return (strcmp(item1->spath, item2->spath));
3691645cafeSMatthew Dillon }
3701645cafeSMatthew Dillon 
3711645cafeSMatthew Dillon pinfo_t *
3721645cafeSMatthew Dillon pinfofind(pinfo_t **ary, int count, char *spath)
3731645cafeSMatthew Dillon {
3741645cafeSMatthew Dillon 	pinfo_t *item;
3751645cafeSMatthew Dillon 	int res;
3761645cafeSMatthew Dillon 	int b;
3771645cafeSMatthew Dillon 	int e;
3781645cafeSMatthew Dillon 	int m;
3791645cafeSMatthew Dillon 
3801645cafeSMatthew Dillon 	b = 0;
3811645cafeSMatthew Dillon 	e = count;
3821645cafeSMatthew Dillon 	while (b != e) {
3831645cafeSMatthew Dillon 		m = b + (e - b) / 2;
3841645cafeSMatthew Dillon 		item = ary[m];
3851645cafeSMatthew Dillon 		res = strcmp(spath, item->spath);
3861645cafeSMatthew Dillon 		if (res == 0)
3871645cafeSMatthew Dillon 			return item;
3881645cafeSMatthew Dillon 		if (res < 0) {
3891645cafeSMatthew Dillon 			e = m;
3901645cafeSMatthew Dillon 		} else {
3911645cafeSMatthew Dillon 			b = m + 1;
3921645cafeSMatthew Dillon 		}
3931645cafeSMatthew Dillon 	}
3941645cafeSMatthew Dillon 	return NULL;
3951645cafeSMatthew Dillon }
3961645cafeSMatthew Dillon 
3971645cafeSMatthew Dillon void
3981645cafeSMatthew Dillon scanit(const char *path, const char *subpath,
3991645cafeSMatthew Dillon        int *countp, pinfo_t ***list_tailp)
4001645cafeSMatthew Dillon {
4011645cafeSMatthew Dillon 	struct dirent *den;
4021645cafeSMatthew Dillon 	pinfo_t *item;
4031645cafeSMatthew Dillon 	char *npath;
4041645cafeSMatthew Dillon 	char *spath;
4051645cafeSMatthew Dillon 	DIR *dir;
4061645cafeSMatthew Dillon 	struct stat st;
4071645cafeSMatthew Dillon 
4081645cafeSMatthew Dillon 	if ((dir = opendir(path)) != NULL) {
4091645cafeSMatthew Dillon 		while ((den = readdir(dir)) != NULL) {
4101645cafeSMatthew Dillon 			if (den->d_namlen == 1 && den->d_name[0] == '.')
4111645cafeSMatthew Dillon 				continue;
4121645cafeSMatthew Dillon 			if (den->d_namlen == 2 && den->d_name[0] == '.' &&
4131645cafeSMatthew Dillon 			    den->d_name[1] == '.')
4141645cafeSMatthew Dillon 				continue;
4151645cafeSMatthew Dillon 			asprintf(&npath, "%s/%s", path, den->d_name);
4161645cafeSMatthew Dillon 			if (lstat(npath, &st) < 0) {
4171645cafeSMatthew Dillon 				free(npath);
4181645cafeSMatthew Dillon 				continue;
4191645cafeSMatthew Dillon 			}
4201645cafeSMatthew Dillon 			if (S_ISDIR(st.st_mode)) {
4211645cafeSMatthew Dillon 				if (subpath) {
4221645cafeSMatthew Dillon 					asprintf(&spath, "%s/%s",
4231645cafeSMatthew Dillon 						 subpath, den->d_name);
4241645cafeSMatthew Dillon 					scanit(npath, spath,
4251645cafeSMatthew Dillon 					       countp, list_tailp);
4261645cafeSMatthew Dillon 					free(spath);
4271645cafeSMatthew Dillon 				} else {
4281645cafeSMatthew Dillon 					scanit(npath, den->d_name,
4291645cafeSMatthew Dillon 					       countp, list_tailp);
4301645cafeSMatthew Dillon 				}
4311645cafeSMatthew Dillon 			} else if (S_ISREG(st.st_mode)) {
4321645cafeSMatthew Dillon 				item = calloc(1, sizeof(*item));
4331645cafeSMatthew Dillon 				if (subpath) {
4341645cafeSMatthew Dillon 					asprintf(&item->spath, "%s/%s",
4351645cafeSMatthew Dillon 						 subpath, den->d_name);
4361645cafeSMatthew Dillon 				} else {
4371645cafeSMatthew Dillon 					item->spath = strdup(den->d_name);
4381645cafeSMatthew Dillon 				}
4391645cafeSMatthew Dillon 				**list_tailp = item;
4401645cafeSMatthew Dillon 				*list_tailp = &item->next;
4411645cafeSMatthew Dillon 				++*countp;
4421645cafeSMatthew Dillon 				ddprintf(0, "scan   %s\n", item->spath);
4431645cafeSMatthew Dillon 			}
4446a3a20b1SMatthew Dillon 			free(npath);
4451645cafeSMatthew Dillon 		}
4461645cafeSMatthew Dillon 		closedir(dir);
4471645cafeSMatthew Dillon 	}
4481645cafeSMatthew Dillon }
449f7f25838SMatthew Dillon 
450f7f25838SMatthew Dillon /*
451f7f25838SMatthew Dillon  * This removes any .new files left over in the repo.  These can wind
452f7f25838SMatthew Dillon  * being left around when dsynth is killed.
453f7f25838SMatthew Dillon  */
454f7f25838SMatthew Dillon static void
455f7f25838SMatthew Dillon scandeletenew(const char *path)
456f7f25838SMatthew Dillon {
457f7f25838SMatthew Dillon 	struct dirent *den;
458f7f25838SMatthew Dillon 	const char *ptr;
459f7f25838SMatthew Dillon 	DIR *dir;
460f7f25838SMatthew Dillon 	char *buf;
461f7f25838SMatthew Dillon 
462f7f25838SMatthew Dillon 	if ((dir = opendir(path)) == NULL)
463f7f25838SMatthew Dillon 		dfatal_errno("Cannot scan directory %s", path);
464f7f25838SMatthew Dillon 	while ((den = readdir(dir)) != NULL) {
465f7f25838SMatthew Dillon 		if ((ptr = strrchr(den->d_name, '.')) != NULL &&
466f7f25838SMatthew Dillon 		    strcmp(ptr, ".new") == 0) {
467f7f25838SMatthew Dillon 			asprintf(&buf, "%s/%s", path, den->d_name);
468f7f25838SMatthew Dillon 			if (remove(buf) < 0)
469f7f25838SMatthew Dillon 				dfatal_errno("remove: Garbage %s\n", buf);
470f7f25838SMatthew Dillon 			printf("Deleted Garbage %s\n", buf);
471f7f25838SMatthew Dillon 			free(buf);
472f7f25838SMatthew Dillon 		}
473f7f25838SMatthew Dillon 	}
474f7f25838SMatthew Dillon 	closedir(dir);
475f7f25838SMatthew Dillon }
476066daf2aSMatthew Dillon 
477066daf2aSMatthew Dillon static void
478066daf2aSMatthew Dillon rebuildTerminateSignal(int signo __unused)
479066daf2aSMatthew Dillon {
480066daf2aSMatthew Dillon 	if (RebuildRemovePath)
481066daf2aSMatthew Dillon 		remove(RebuildRemovePath);
482066daf2aSMatthew Dillon 	exit(1);
483066daf2aSMatthew Dillon 
484066daf2aSMatthew Dillon }
485