Radish alpha
H
HardenedBSD Package Manager
Radicle
Git (anonymous pull)
Log in to clone via SSH
Implement automatic dirrm (not optimized at all but working
Baptiste Daroussin committed 15 years ago
commit 7f8a290c896867df2284c8f0a9f3bd48deea122a
parent a24ddc0fc7fd80a46a82b71e44ee04568ae0f98f
3 files changed +58 -0
modified libpkg/pkg.c
@@ -86,6 +86,7 @@ pkg_set(struct pkg *pkg, pkg_attr attr, const char *value)
			} else {
				sbuf_set(&pkg->mtree, "#mtree\n");
				sbuf_cat(pkg->mtree, value);
+
				sbuf_finish(pkg->mtree);
				return (EPKG_OK);
			}
			return (sbuf_set(&pkg->mtree, value));
modified libpkg/pkg.h
@@ -137,6 +137,7 @@ typedef enum {
	EPKG_UNKNOWN_SCRIPT,
	EPKG_NOT_ORIGIN,
	EPKG_NOT_NAME,
+
	EPKG_ERROR_MTREE,
} pkg_error_t;

/**
modified libpkg/pkg_delete.c
@@ -2,8 +2,24 @@
#include <err.h>
#include <unistd.h>
#include <sha256.h>
+
#include <search.h>
+
#include <archive.h>
+
#include <archive_entry.h>
+
#include <stdlib.h>

#include "pkg.h"
+
#include "pkg_util.h"
+

+
static
+
int
+
dircmp(char *path, struct array *a)
+
{
+
	for (size_t i = 0; i < a->len; i++)
+
		if (strcmp(path, a->data[i]) == 0)
+
			return (1);
+

+
	return (0);
+
} 

int
pkg_delete(struct pkg *pkg, struct pkgdb *db, int force)
@@ -11,12 +27,20 @@ pkg_delete(struct pkg *pkg, struct pkgdb *db, int force)
	struct pkg **rdeps;
	struct pkg_file **files;
	char sha256[65];
+
	const char *mtree = NULL;
+
	struct archive *a;
+
	struct archive_entry *ae;
+
	struct array mtreedirs;
+
	const char *prefix;
+
	char *path, *end, *fullpath;
+
	int ret;

	if (pkg == NULL || db == NULL)
		return (-1);

	rdeps = pkg_rdeps(pkg);
	files = pkg_files(pkg);
+
	prefix = pkg_get(pkg, PKG_PREFIX);

	if (rdeps == NULL || files == NULL)
		return (-1);
@@ -26,6 +50,20 @@ pkg_delete(struct pkg *pkg, struct pkgdb *db, int force)
		return (-1); /* TODO: special return code */
	}

+
	a = archive_read_new();
+
	archive_read_support_compression_none(a);
+
	archive_read_support_format_mtree(a);
+

+
	mtree = pkg_get(pkg, PKG_MTREE);
+
	if (archive_read_open_memory(a, strdup(mtree), strlen(mtree)) != ARCHIVE_OK)
+
		return (EPKG_ERROR_MTREE);
+

+
	bzero(&mtreedirs, sizeof(mtreedirs));
+
	array_init(&mtreedirs, 20);
+

+
	while ((ret = archive_read_next_header(a, &ae)) == ARCHIVE_OK)
+
		array_append(&mtreedirs, strdup(archive_entry_pathname(ae)));
+

	for (int i = 0; files[i] != NULL; i++) {
		/* check sha256 */
		if (pkg_file_sha256(files[i])[0] != '\0' &&
@@ -37,8 +75,26 @@ pkg_delete(struct pkg *pkg, struct pkgdb *db, int force)
		else if (unlink(pkg_file_path(files[i])) == -1) {
			warn("unlink(%s)", pkg_file_path(files[i]));
			continue;
+
		} else {
+
			/* only delete directories that are in prefix */
+
			if (STARTS_WITH(pkg_file_path(files[i]), prefix)) {
+
				path = strdup(pkg_file_path(files[i]));
+
				fullpath = path;
+
				path += strlen(prefix) + 1;
+

+
				if (path[0] == '/')
+
					path++;
+

+
				while ((end = strrchr(path, '/')) != NULL) {
+
					end[0] = '\0';
+
					if (!dircmp(path, &mtreedirs))
+
						rmdir(fullpath);
+
				}
+
				free(fullpath);
+
			}
		}
	}
+
	array_free(&mtreedirs, &free);

	return (pkgdb_unregister_pkg(db, pkg_get(pkg, PKG_ORIGIN)));
}