Radish alpha
H
HardenedBSD Package Manager
Radicle
Git (anonymous pull)
Log in to clone via SSH
Modify pkg_analyse_files() to register shared libraries per package alternatively to adding any missing dependencies.
Matthew Seaman committed 14 years ago
commit 54d87ca81f518fade144416f3674fcb2f5935cb1
parent 99a6922f0808d47b213b9e1e0aeacccb194e006e
3 files changed +96 -36
modified libpkg/pkg.h
@@ -394,15 +394,26 @@ int pkg_options(struct pkg *, struct pkg_option **option);

/**
 * Iterates over the shared libraries used by the package.
-
 * @param Must be set to NULL for the first call.
+
 * @param shlib must be set to NULL for the first call.
 * @return An error code
 */
int pkg_shlibs(struct pkg *pkg, struct pkg_shlib **shlib);

/**
-
 * @todo Document
+
 * Iterate over all of the files within the package.  Determine which
+
 * are ELF format executables or shared objects, and extract the names
+
 * of any shared libraries those depend on.  If pkg_analyse_action is
+
 * PKG_ANALYSE_ADD_MISSING_DEPS, determine which (if any) package
+
 * supplied the shared library and add that package to the
+
 * dependencies of pkg if not already known.  If pkg_analyse_action
+
 * is PKG_ANALYSE_REGISTER_SHLIBS, register the names of all shared
+
 * libraries required by pkg files in the database.
+
 * @return An error code
 */
-
int pkg_analyse_files(struct pkgdb *, struct pkg *);
+

+
typedef enum { PKG_ANALYSE_ADD_MISSING_DEPS, PKG_ANALYSE_REGISTER_SHLIBS } pkg_analyse_action;
+

+
int pkg_analyse_files(struct pkgdb *, struct pkg *, pkg_analyse_action);

/**
 * Generic setter for simple attributes.
modified libpkg/pkg_elf.c
@@ -29,6 +29,7 @@
#include <sys/elf_common.h>

#include <ctype.h>
+
#include <assert.h>
#include <fcntl.h>
#include <dlfcn.h>
#include <gelf.h>
@@ -43,28 +44,87 @@
#include "private/elf_tables.h"

static int
-
analyse_elf(struct pkgdb *db, struct pkg *pkg, const char *fpath)
+
add_forgotten_depends(struct pkgdb *db, struct pkg *pkg, const char *name)
{
	struct pkg_dep *dep = NULL;
	struct pkg *p = NULL;
	struct pkgdb_it *it = NULL;
-
	Elf *e = NULL;
+
	const char *pkgorigin, *pkgname, *pkgversion;
+
	Link_map *map;
+
	bool found = false;
+
	void *handle;
+

+
	handle = dlopen(name, RTLD_LAZY);
+
	if (handle == NULL) {
+
		pkg_emit_error("accessing shared library %s failed -- %s", name, dlerror());
+
		return (EPKG_FATAL);
+
	}
+

+
	dlinfo(handle, RTLD_DI_LINKMAP, &map);
+

+
	if ((it = pkgdb_query_which(db, map->l_name)) == NULL) {
+
		dlclose(handle);
+
		return (EPKG_OK); /* shlib not from any pkg */
+
	}
+
	if (pkgdb_it_next(it, &p, PKG_LOAD_BASIC) == EPKG_OK) {
+
		found = false;
+
		pkg_get(pkg, PKG_ORIGIN, &pkgorigin);
+
		while (pkg_deps(pkg, &dep) == EPKG_OK) {
+
			if (strcmp(pkg_dep_get(dep, PKG_DEP_ORIGIN), pkgorigin) == 0) {
+
				found = true;
+
				break;
+
			}
+
		}
+
		if (!found) {
+
			pkg_get(p, PKG_ORIGIN, &pkgorigin, PKG_NAME, &pkgname, PKG_VERSION, &pkgversion);
+
			pkg_emit_error("adding forgotten depends (%s): %s-%s",
+
				       map->l_name, pkgname, pkgversion);
+
			pkg_adddep(pkg, pkgname, pkgorigin, pkgversion);
+
		}
+
		pkg_free(p);
+
	}
+
	dlclose(handle);
+
	pkgdb_it_free(it);
+

+
	return (EPKG_OK);
+
}
+

+
static int
+
register_shlibs(__unused struct pkgdb *db, struct pkg *pkg, const char *name)
+
{
+
	struct pkg_shlib *s = NULL;
+

+
	assert(pkg != NULL);
+
	assert(name != NULL && name[0] != '\0');
+

+
	while (pkg_shlibs(pkg, &s) == EPKG_OK) {
+
		if (strcmp(name, pkg_shlib_name(s)) == 0) {
+
			/* already registered, but that's OK */
+
			return (EPKG_OK);
+
		}
+
	}
+
	pkg_shlib_new(&s);
+
	sbuf_set(&s->name, name);
+
	STAILQ_INSERT_TAIL(&pkg->shlibs, s, next);
+
	return (EPKG_OK);
+
}
+

+
static int
+
analyse_elf(struct pkgdb *db, struct pkg *pkg, const char *fpath,
+
	    int(*lib_handler)(struct pkgdb*, struct pkg*, const char*))
+
{
+
	Elf *e;
	Elf_Scn *scn = NULL;
	GElf_Shdr shdr;
	Elf_Data *data;
	GElf_Dyn *dyn, dyn_mem;

-
	const char *pkgorigin, *pkgname, *pkgversion;
	size_t numdyn;
	size_t dynidx;
-
	void *handle;
-
	Link_map *map;
	char *name;
-
	bool found=false;

	int fd;

-
	pkg_get(pkg, PKG_ORIGIN, &pkgorigin, PKG_NAME, &pkgname, PKG_VERSION, &pkgversion);
	if ((fd = open(fpath, O_RDONLY, 0)) < 0)
		return (EPKG_FATAL);

@@ -96,28 +156,9 @@ analyse_elf(struct pkgdb *db, struct pkg *pkg, const char *fpath)
			continue;

		name = elf_strptr(e, shdr.sh_link, dyn->d_un.d_val);
-
		handle = dlopen(name, RTLD_LAZY);
-

-
		if (handle != NULL) {
-
			dlinfo(handle, RTLD_DI_LINKMAP, &map);
-
			if ((it = pkgdb_query_which(db, map->l_name)) == NULL)
-
				return (EPKG_FATAL);
-

-
			if (pkgdb_it_next(it, &p, PKG_LOAD_BASIC) == EPKG_OK) {
-
				found = false;
-
				while (pkg_deps(pkg, &dep) == EPKG_OK) {
-
					if (strcmp(pkg_dep_get(dep, PKG_DEP_ORIGIN), pkgorigin) == 0)
-
						found = true;
-
				}
-
				if (!found) {
-
					pkg_emit_error("adding forgotten depends (%s): %s-%s",
-
					    map->l_name, pkgname, pkgversion);
-
					pkg_adddep(pkg, pkgname, pkgorigin, pkgversion);
-
				}
-
			}
-
			dlclose(handle);
-
		}
-
		pkgdb_it_free(it);
+

+
		if ( lib_handler(db, pkg, name) != EPKG_OK )
+
			break;			
	}
	pkg_free(p);
	if (e != NULL)
@@ -129,15 +170,23 @@ analyse_elf(struct pkgdb *db, struct pkg *pkg, const char *fpath)
}

int
-
pkg_analyse_files(struct pkgdb *db, struct pkg *pkg)
+
pkg_analyse_files(struct pkgdb *db, struct pkg *pkg, pkg_analyse_action action)
{
	struct pkg_file *file = NULL;

	if (elf_version(EV_CURRENT) == EV_NONE)
		return (EPKG_FATAL);

-
	while (pkg_files(pkg, &file) == EPKG_OK)
-
		analyse_elf(db, pkg, pkg_file_get(file, PKG_FILE_PATH));
+
	switch (action) {
+
		case PKG_ANALYSE_ADD_MISSING_DEPS:
+
			while (pkg_files(pkg, &file) == EPKG_OK)
+
				analyse_elf(db, pkg, pkg_file_get(file, PKG_FILE_PATH), add_forgotten_depends);
+
			break;
+
		case PKG_ANALYSE_REGISTER_SHLIBS:
+
			while (pkg_files(pkg, &file) == EPKG_OK)
+
				analyse_elf(db, pkg, pkg_file_get(file, PKG_FILE_PATH), register_shlibs);
+
			break;
+
	}

	return (EPKG_OK);
}
modified pkg/register.c
@@ -204,7 +204,7 @@ exec_register(int argc, char **argv)
	}

	if (heuristic)
-
		pkg_analyse_files(db, pkg);
+
		pkg_analyse_files(db, pkg, PKG_ANALYSE_ADD_MISSING_DEPS);

	if (input_path != NULL) {
		pkg_copy_tree(pkg, input_path, "/");