Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
hardlinks: rework handling of hardlinks
Baptiste Daroussin committed 4 years ago
commit 70b98f1a0cca078931ce02a71c5b6400eecfbf84
parent a0da058
9 files changed +54 -33
modified libpkg/Makefile.autosetup
@@ -59,7 +59,6 @@ LOCAL_CFLAGS= -I$(top_srcdir)/compat \
		-I$(top_srcdir)/external/include \
		-I$(top_srcdir)/external/mum \
		-I$(top_srcdir)/external/libucl/include \
-
		-I$(top_srcdir)/external/libucl/klib \
		-I$(top_srcdir)/external/libfetch \
		-I$(top_srcdir)/external/lua/src \
		-I$(top_srcdir)/external/liblua/ \
modified libpkg/pkg.c
@@ -1526,14 +1526,13 @@ int
pkg_recompute(struct pkgdb *db, struct pkg *pkg)
{
	struct pkg_file *f = NULL;
-
	hardlinks_t *hl = NULL;
+
	hardlinks_t hl = tll_init();
	int64_t flatsize = 0;
	struct stat st;
	bool regular = false;
	char *sum;
	int rc = EPKG_OK;

-
	hl = kh_init_hardlinks();
	while (pkg_files(pkg, &f) == EPKG_OK) {
		if (lstat(f->path, &st) != 0)
			continue;
@@ -1550,7 +1549,7 @@ pkg_recompute(struct pkgdb *db, struct pkg *pkg)
		}

		if (st.st_nlink > 1)
-
			regular = !check_for_hardlink(hl, &st);
+
			regular = !check_for_hardlink(&hl, &st);

		if (regular)
			flatsize += st.st_size;
@@ -1559,7 +1558,7 @@ pkg_recompute(struct pkgdb *db, struct pkg *pkg)
			pkgdb_file_set_cksum(db, f, sum);
		free(sum);
	}
-
	kh_destroy_hardlinks(hl);
+
	tll_free_and_free(hl, free);

	if (flatsize != pkg->flatsize)
		pkg->flatsize = flatsize;
modified libpkg/pkg_add.c
@@ -42,6 +42,7 @@
#include <sys/time.h>
#include <time.h>
#include <xstring.h>
+
#include <tllist.h>

#include "pkg.h"
#include "private/event.h"
@@ -49,7 +50,12 @@
#include "private/pkg.h"
#include "private/pkgdb.h"

-
KHASH_MAP_INIT_INT(hls, char *);
+
struct store_hardlinks {
+
	ino_t ino;
+
	dev_t dev;
+
	const char *path;
+
};
+
typedef tll(struct store_hardlinks *) hls;

#if defined(UF_NOUNLINK)
#define NOCHANGESFLAGS	(UF_IMMUTABLE | UF_APPEND | UF_NOUNLINK | SF_IMMUTABLE | SF_APPEND | SF_NOUNLINK)
@@ -1335,7 +1341,7 @@ pkg_add_fromdir(struct pkg *pkg, const char *src)
	struct group *gr, grent;
	int err, fd, fromfd;
	int retcode;
-
	kh_hls_t *hardlinks = NULL;;
+
	hls hardlinks = tll_init();
	const char *path;
	char buffer[1024];
	size_t link_len;
@@ -1401,7 +1407,6 @@ pkg_add_fromdir(struct pkg *pkg, const char *src)
		}
	}

-
	hardlinks = kh_init_hls();
	while (pkg_files(pkg, &f) == EPKG_OK) {
		if (match_ucl_lists(f->path,
		    pkg_config_get("FILES_IGNORE_GLOB"),
@@ -1409,7 +1414,7 @@ pkg_add_fromdir(struct pkg *pkg, const char *src)
			continue;
		if (fstatat(fromfd, RELATIVE_PATH(f->path), &st,
		    AT_SYMLINK_NOFOLLOW) == -1) {
-
			kh_destroy_hls(hardlinks);
+
			tll_free_and_free(hardlinks, free);
			close(fromfd);
			pkg_fatal_errno("%s%s", src, f->path);
		}
@@ -1462,7 +1467,7 @@ pkg_add_fromdir(struct pkg *pkg, const char *src)
			if ((link_len = readlinkat(fromfd,
			    RELATIVE_PATH(f->path), target,
			    sizeof(target))) == -1) {
-
				kh_destroy_hls(hardlinks);
+
				tll_free_and_free(hardlinks, free);
				close(fromfd);
				pkg_fatal_errno("Impossible to read symlinks "
				    "'%s'", f->path);
@@ -1475,12 +1480,19 @@ pkg_add_fromdir(struct pkg *pkg, const char *src)
		} else if (S_ISREG(st.st_mode)) {
			if ((fd = openat(fromfd, RELATIVE_PATH(f->path),
			    O_RDONLY)) == -1) {
-
				kh_destroy_hls(hardlinks);
+
				tll_free_and_free(hardlinks, free);
				close(fromfd);
				pkg_fatal_errno("Impossible to open source file"
				    " '%s'", RELATIVE_PATH(f->path));
			}
-
			kh_find(hls, hardlinks, st.st_ino, path);
+
			path = NULL;
+
			tll_foreach(hardlinks, hit) {
+
				if (hit->item->ino == st.st_ino &&
+
				    hit->item->dev == st.st_dev) {
+
					path = hit->item->path;
+
					break;
+
				}
+
			}
			if (path != NULL) {
				if (create_hardlink(pkg, f, path) == EPKG_FATAL) {
					close(fd);
@@ -1493,7 +1505,11 @@ pkg_add_fromdir(struct pkg *pkg, const char *src)
					retcode = EPKG_FATAL;
					goto cleanup;
				}
-
				kh_safe_add(hls, hardlinks, f->path, st.st_ino);
+
				struct store_hardlinks *h = xcalloc(1, sizeof(*h));
+
				h->ino = st.st_ino;
+
				h->dev = st.st_dev;
+
				h->path = f->path;
+
				tll_push_back(hardlinks, h);
			}
			close(fd);
		} else {
@@ -1506,7 +1522,7 @@ pkg_add_fromdir(struct pkg *pkg, const char *src)
	retcode = pkg_extract_finalize(pkg);

cleanup:
-
	kh_destroy_hls(hardlinks);
+
	tll_free_and_free(hardlinks, free);
	close(fromfd);
	return (retcode);
}
modified libpkg/pkg_create.c
@@ -62,7 +62,7 @@ pkg_create_from_dir(struct pkg *pkg, const char *root,
	int64_t		 flatsize = 0;
	int64_t		 nfiles;
	const char	*relocation;
-
	hardlinks_t	*hardlinks;
+
	hardlinks_t	 hardlinks = tll_init();

	if (pkg_is_valid(pkg) != EPKG_OK) {
		pkg_emit_error("the package is not valid");
@@ -82,7 +82,6 @@ pkg_create_from_dir(struct pkg *pkg, const char *root,
	nfiles = pkghash_count(pkg->filehash);
	counter_init("file sizes/checksums", nfiles);

-
	hardlinks = kh_init_hardlinks();
	while (pkg_files(pkg, &file) == EPKG_OK) {

		snprintf(fpath, sizeof(fpath), "%s%s%s", root ? root : "",
@@ -90,33 +89,33 @@ pkg_create_from_dir(struct pkg *pkg, const char *root,

		if (lstat(fpath, &st) == -1) {
			pkg_emit_error("file '%s' is missing", fpath);
-
			kh_destroy_hardlinks(hardlinks);
+
			tll_free_and_free(hardlinks, free);
			return (EPKG_FATAL);
		}

		if (!(S_ISREG(st.st_mode) || S_ISLNK(st.st_mode))) {
			pkg_emit_error("file '%s' is not a regular file or symlink", fpath);
-
			kh_destroy_hardlinks(hardlinks);
+
			tll_free_and_free(hardlinks, free);
			return (EPKG_FATAL);
		}

		if (file->size == 0)
			file->size = (int64_t)st.st_size;

-
		if (st.st_nlink == 1 || !check_for_hardlink(hardlinks, &st)) {
+
		if (st.st_nlink == 1 || !check_for_hardlink(&hardlinks, &st)) {
			flatsize += file->size;
		}

		file->sum = pkg_checksum_generate_file(fpath,
		    PKG_HASH_TYPE_SHA256_HEX);
		if (file->sum == NULL) {
-
			kh_destroy_hardlinks(hardlinks);
+
			tll_free_and_free(hardlinks, free);
			return (EPKG_FATAL);
		}

		counter_count();
	}
-
	kh_destroy_hardlinks(hardlinks);
+
	tll_free_and_free(hardlinks, free);

	counter_end();

modified libpkg/pkg_ports.c
@@ -337,7 +337,7 @@ meta_file(struct plist *p, char *line, struct file_attr *a, bool is_config)

	if (S_ISREG(st.st_mode)) {
		if (st.st_nlink > 1)
-
			regular = !check_for_hardlink(p->hardlinks, &st);
+
			regular = !check_for_hardlink(&p->hardlinks, &st);
		else
			regular = true;
	} else if (S_ISLNK(st.st_mode))
@@ -1039,7 +1039,6 @@ plist_new(struct pkg *pkg, const char *stage)
	p->post_install_buf = xstring_new();
	p->pre_deinstall_buf = xstring_new();
	p->post_deinstall_buf = xstring_new();
-
	p->hardlinks = kh_init_hardlinks();

	populate_keywords(p);

@@ -1067,7 +1066,7 @@ plist_free(struct plist *p)
	free(p->gname);
	free(p->post_patterns.buf);
	free(p->post_patterns.patterns);
-
	kh_destroy_hardlinks(p->hardlinks);
+
	tll_free_and_free(p->hardlinks, free);

	xstring_free(p->post_deinstall_buf);
	xstring_free(p->post_install_buf);
modified libpkg/private/pkg.h
@@ -556,7 +556,7 @@ struct plist {
	char *gname;
	const char *slash;
	int64_t flatsize;
-
	hardlinks_t *hardlinks;
+
	hardlinks_t hardlinks;
	mode_t perm;
	struct {
		char *buf;
modified libpkg/private/utils.h
@@ -32,7 +32,7 @@
#include <sys/stat.h>
#include <sys/param.h>
#include <ucl.h>
-
#include <khash.h>
+
#include <tllist.h>
#include <pkg.h>
#include <xstring.h>

@@ -49,8 +49,11 @@
	__FILE__, __LINE__, sqlite3_errmsg(db)); \
} while (0)

-
KHASH_MAP_INIT_INT(hardlinks, int)
-
typedef khash_t(hardlinks) hardlinks_t;
+
typedef tll(struct hardlink *) hardlinks_t;
+
struct hardlink {
+
	ino_t ino;
+
	dev_t dev;
+
};

struct dns_srvinfo {
	unsigned int type;
modified libpkg/repo/binary/Makefile.autosetup
@@ -10,7 +10,7 @@ LOCAL_CFLAGS= -I$(top_srcdir)/libpkg \
		-I$(top_srcdir)/external/uthash \
		-I$(top_srcdir)/external/sqlite \
		-I$(top_srcdir)/external/libucl/include \
-
		-I$(top_srcdir)/external/libucl/klib \
+
		-I$(top_srcdir)/external/include \
		-I$(top_srcdir)/compat \
		-I$(top_srcdir)/ \

modified libpkg/utils.c
@@ -349,11 +349,17 @@ is_link(const char *path)
bool
check_for_hardlink(hardlinks_t *hl, struct stat *st)
{
-
	int absent;
+
	struct hardlink *h;

-
	kh_put_hardlinks(hl, st->st_ino, &absent);
-
	if (absent == 0)
-
		return (true);
+
	tll_foreach(*hl, it) {
+
		if (it->item->ino == st->st_ino &&
+
		    it->item->dev == st->st_dev)
+
			return (true);
+
	}
+
	h = xcalloc(1, sizeof(*h));
+
	h->ino = st->st_ino;
+
	h->dev = st->st_dev;
+
	tll_push_back(*hl, h);

	return (false);
}