Radish alpha
H
HardenedBSD Package Manager
Radicle
Git (anonymous pull)
Log in to clone via SSH
Add new option AUTODEPS and SHLIBS while here cleanup pkg_elf
Baptiste Daroussin committed 14 years ago
commit c1e3734b93c953e91dd26cf526dd42550d5db352
parent ba5a45c671784dc03bf75384f4370b111586579b
8 files changed +92 -195
modified libpkg/pkg.c
@@ -828,10 +828,9 @@ pkg_addshlib(struct pkg *pkg, const char *name)
	assert(name != NULL && name[0] != '\0');

	while (pkg_shlibs(pkg, &s) == EPKG_OK) {
-
		if (strcmp(name, pkg_shlib_name(s)) == 0) {
-
			pkg_emit_error("duplicate shared library listing: %s, ignoring", name);
+
		/* silently ignore duplicates in case of shlibs */
+
		if (strcmp(name, pkg_shlib_name(s)) == 0)
			return (EPKG_OK);
-
		}
	}

	pkg_shlib_new(&s);
modified libpkg/pkg.h
@@ -236,7 +236,9 @@ typedef enum _pkg_config_key {
	PKG_CONFIG_ASSUME_ALWAYS_YES = 7,
	PKG_CONFIG_REPOS = 8,
	PKG_CONFIG_PLIST_KEYWORDS_DIR = 9,
-
	PKG_CONFIG_SYSLOG = 10
+
	PKG_CONFIG_SYSLOG = 10,
+
	PKG_CONFIG_SHLIBS = 11,
+
	PKG_CONFIG_AUTODEPS = 12
} pkg_config_key;

typedef enum {
@@ -400,48 +402,15 @@ int pkg_options(struct pkg *, struct pkg_option **option);
int pkg_shlibs(struct pkg *pkg, struct pkg_shlib **shlib);

/**
-
 * Initialise the ELF libraries for pkg_register_shlibs_for_file() 
-
 * or pkg_analyse_one_file()
-
 * @return An error code
-
 */
-

-
int pkg_analyse_init(void);
-

-
/**
-
 * Register the shared libraries used by fname, which is one of the
-
 * files belonging to pkg.
-
 * @return An error code
-
 */
-

-
int pkg_register_shlibs_for_file(struct pkg *pkg, const char *fname);
-

-
/**
-
 * Iterate over all of the files within the package pkg, registering
-
 * the shared libraries used by each of them.
-
 * @return An error code
-
 */
-

-
int pkg_register_shlibs(struct pkg *pkg);
-

-
/**
-
 * Analyse one file fname, which belongs to package pkg.  If it is an
-
 * ELF format executable or shared library, ensure that all of the
-
 * packages providing shared objects used by the file are added to the
-
 * pkg dependency list.
-
 * @return An error code
-
 */
-

-
int pkg_analyse_one_file(struct pkgdb *db, struct pkg *pkg, const char *fname);
-

-
/**
 * Iterate over all of the files within the package pkg, ensuring the
 * dependency list contains all applicable packages providing the
 * shared objects used by pkg.
+
 * Also add all the shared object into the shlibs.
+
 * It respects the SHLIBS and AUTODEPS options from configuration
 * @return An error code
 */

int pkg_analyse_files(struct pkgdb *, struct pkg *);
-

/**
 * Generic setter for simple attributes.
 */
modified libpkg/pkg_config.c
@@ -125,6 +125,18 @@ static struct config_entry c[] = {
		"SYSLOG",
		"YES",
		{ NULL }
+
	},
+
	[PKG_CONFIG_SHLIBS] = {
+
		BOOL,
+
		"SHLIBS",
+
		"NO",
+
		{ NULL }
+
	},
+
	[PKG_CONFIG_AUTODEPS] = {
+
		BOOL,
+
		"AUTODEPS",
+
		"NO",
+
		{ NULL }
	}
};

modified libpkg/pkg_create.c
@@ -50,8 +50,6 @@ pkg_create_from_dir(struct pkg *pkg, const char *root, struct packing *pkg_archi
	struct stat st;
	char sha256[SHA256_DIGEST_LENGTH * 2 + 1];

-
	pkg_analyse_init();
-

	/*
	 * if the checksum is not provided in the manifest recompute it
	 */
@@ -66,9 +64,6 @@ pkg_create_from_dir(struct pkg *pkg, const char *root, struct packing *pkg_archi
				return (EPKG_FATAL);
			strlcpy(file->sum, sha256, sizeof(file->sum));
		}
-

-
/*		if (pkg_register_shlibs_for_file(pkg, fpath) != EPKG_OK)
-
			return (EPKG_FATAL);*/
	}

	pkg_emit_manifest(pkg, &m);
modified libpkg/pkg_elf.c
@@ -45,86 +45,72 @@
#include "private/elf_tables.h"

static int
-
register_shlibs(struct pkg *pkg, const char *namelist[])
-
{
-
	struct pkg_shlib *s;
-
	const char **name;
-
	bool found;
-

-
	assert(pkg != NULL);
-

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

-
static int
-
add_forgotten_depends(struct pkgdb *db, struct pkg *pkg, const char *namelist[])
+
test_depends(struct pkgdb *db, struct pkg *pkg, const char *name)
{
	struct pkg_dep *dep = NULL;
	struct pkgdb_it *it = NULL;
	struct pkg *d;
	Link_map *map;
	const char *deporigin, *depname, *depversion;
-
	const char **name;
	bool found;
	void *handle;
+
	bool shlibs = false;
+
	bool autodeps = false;

-
	for (name = namelist; *name != NULL; name++) {
-
		handle = dlopen(*name, RTLD_LAZY);
-
		if (handle == NULL) {
-
			pkg_emit_error("accessing shared library %s failed -- %s", name, dlerror());
-
			return (EPKG_FATAL);
-
		}
+
	pkg_config_bool(PKG_CONFIG_AUTODEPS, &autodeps);
+
	pkg_config_bool(PKG_CONFIG_SHLIBS, &shlibs);

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

-
		if ((it = pkgdb_query_which(db, map->l_name)) == NULL) {
-
			dlclose(handle);
-
			break; /* shlib not from any pkg */
-
		}
-
		d = NULL;
-
		if (pkgdb_it_next(it, &d, PKG_LOAD_BASIC) == EPKG_OK) {
-
			found = false;
-
			pkg_get(d, PKG_ORIGIN, &deporigin, PKG_NAME, &depname, PKG_VERSION, &depversion);
-

-
			dep = NULL;
-
			found = false;
-
			while (pkg_deps(pkg, &dep) == EPKG_OK) {
-
				if (strcmp(pkg_dep_get(dep, PKG_DEP_ORIGIN), deporigin) == 0) {
-
					found = true;
-
					break;
-
				}
-
			}
-
			if (!found) {
-
				pkg_emit_error("adding forgotten depends (%s): %s-%s",
-
					       map->l_name, depname, depversion);
-
				pkg_adddep(pkg, depname, deporigin, depversion);
+
	dlinfo(handle, RTLD_DI_LINKMAP, &map);
+

+
	/* match /lib, /lib32, /usr/lib and /usr/lib32 */
+
	if (strncmp(map->l_name, "/lib", 4) == 0 || strncmp(map->l_name, "/usr/lib", 7) == 0) {
+
		/* ignore libs from base */
+
		dlclose(handle);
+
		return (EPKG_OK);
+
	}
+

+
	if (shlibs)
+
		pkg_addshlib(pkg, name);
+

+
	if (!autodeps)
+
		return (EPKG_OK);
+

+
	if ((it = pkgdb_query_which(db, map->l_name)) == NULL) {
+
		dlclose(handle);
+
		return (EPKG_OK);
+
	}
+
	d = NULL;
+
	if (pkgdb_it_next(it, &d, PKG_LOAD_BASIC) == EPKG_OK) {
+
		found = false;
+
		pkg_get(d, PKG_ORIGIN, &deporigin, PKG_NAME, &depname, PKG_VERSION, &depversion);
+

+
		dep = NULL;
+
		found = false;
+
		while (pkg_deps(pkg, &dep) == EPKG_OK) {
+
			if (strcmp(pkg_dep_get(dep, PKG_DEP_ORIGIN), deporigin) == 0) {
+
				found = true;
+
				break;
			}
-
			pkg_free(d);
		}
-
		dlclose(handle);
-
		pkgdb_it_free(it);
+
		if (!found) {
+
			pkg_emit_error("adding forgotten depends (%s): %s-%s",
+
					map->l_name, depname, depversion);
+
			pkg_adddep(pkg, depname, deporigin, depversion);
+
		}
+
		pkg_free(d);
	}
+
	dlclose(handle);
+
	pkgdb_it_free(it);
	return (EPKG_OK);
}

static int
-
analyse_elf(const char *fpath, const char ***namelist)
+
analyse_elf(struct pkgdb *db, struct pkg *pkg, const char *fpath)
{
	Elf *e;
	Elf_Scn *scn = NULL;
@@ -135,14 +121,17 @@ analyse_elf(const char *fpath, const char ***namelist)
	GElf_Dyn *dyn, dyn_mem;
	struct stat sb;
	int ret = EPKG_OK;
+
	bool shlibs = false;
+
	bool autodeps = false;

	size_t numdyn;
	size_t dynidx;
	const char *osname;
-
	const char **name;

	int fd;

+
	pkg_config_bool(PKG_CONFIG_SHLIBS, &shlibs);
+
	pkg_config_bool(PKG_CONFIG_AUTODEPS, &autodeps);
	if ((fd = open(fpath, O_RDONLY, 0)) < 0) {
		return (EPKG_FATAL);
	}
@@ -201,12 +190,6 @@ analyse_elf(const char *fpath, const char ***namelist)
	data = elf_getdata(dynamic, NULL);
	numdyn = shdr.sh_size / shdr.sh_entsize;

-
	if ( (*namelist = calloc(numdyn + 1, sizeof(**namelist))) == NULL ) {
-
		ret = EPKG_FATAL;
-
		goto cleanup;
-
	}
-
	name = *namelist;
-

	for (dynidx = 0; dynidx < numdyn; dynidx++) {
		if ((dyn = gelf_getdyn(data, dynidx, &dyn_mem)) == NULL) {
			ret = EPKG_FATAL;
@@ -217,8 +200,7 @@ analyse_elf(const char *fpath, const char ***namelist)
		if (dyn->d_tag != DT_NEEDED)
			continue;

-
		*name = elf_strptr(e, shdr.sh_link, dyn->d_un.d_val);
-
		name++;
+
		test_depends(db, pkg, elf_strptr(e, shdr.sh_link, dyn->d_un.d_val));
	}

cleanup:
@@ -230,86 +212,25 @@ cleanup:
}

int
-
pkg_analyse_init(void)
-
{
-
	if (elf_version(EV_CURRENT) == EV_NONE)
-
		return (EPKG_FATAL);
-
	return (EPKG_OK);
-
}
-

-
int
-
pkg_register_shlibs_for_file(struct pkg *pkg, const char *fname)
-
{
-
	const char **namelist = NULL;
-
	int ret = EPKG_OK;
-

-
	switch (analyse_elf(fname, &namelist)) {
-
		case EPKG_OK:
-
			ret = register_shlibs(pkg, namelist);
-
			break;
-
		case EPKG_END:
-
			break; /* File not dynamically linked  */
-
		case EPKG_FATAL:
-
			ret = EPKG_FATAL;
-
			break;
-
	}
-
	if (namelist != NULL)
-
		free(namelist);
-

-
	return (ret);
-
}
-

-
int
-
pkg_register_shlibs(struct pkg *pkg)
+
pkg_analyse_files(struct pkgdb *db, struct pkg *pkg)
{
	struct pkg_file *file = NULL;
	int ret = EPKG_OK;
+
	bool shlibs = false;
+
	bool autodeps = false;

-
	if (elf_version(EV_CURRENT) == EV_NONE)
-
		return (EPKG_FATAL);
+
	pkg_config_bool(PKG_CONFIG_SHLIBS, &shlibs);
+
	pkg_config_bool(PKG_CONFIG_AUTODEPS, &autodeps);

-
	while (pkg_files(pkg, &file) == EPKG_OK) {
-
		if ((ret = pkg_register_shlibs_for_file(pkg, pkg_file_get(file, PKG_FILE_PATH))) != EPKG_OK)
-
			break;
-
	}
-
	return (EPKG_OK);
-
}
-

-
int
-
pkg_analyse_one_file(struct pkgdb *db, struct pkg *pkg, const char *fname)
-
{
-
	const char **namelist = NULL;
-
	int ret = EPKG_OK;
-

-
	switch (analyse_elf(fname, &namelist)) {
-
		case EPKG_OK:
-
			ret = add_forgotten_depends(db, pkg, namelist);
-
			break;
-
		case EPKG_END:
-
			break; /* File not dynamically linked  */
-
		case EPKG_FATAL:
-
			ret = EPKG_FATAL;
-
			break;
-
	}
-
	if (namelist != NULL)
-
		free(namelist);
-

-
	return (ret);
-
}
-

-
int
-
pkg_analyse_files(struct pkgdb *db, struct pkg *pkg)
-
{
-
	struct pkg_file *file = NULL;
-
	int ret = EPKG_OK;
+
	if (!autodeps && !shlibs)
+
		return (EPKG_OK);

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

-
	while (pkg_files(pkg, &file) == EPKG_OK) {
-
		if ((ret = pkg_analyse_one_file(db, pkg, pkg_file_get(file, PKG_FILE_PATH))) != EPKG_OK)
-
			break;
-
	}
+
	while (pkg_files(pkg, &file) == EPKG_OK)
+
		analyse_elf(db, pkg, pkg_file_get(file, PKG_FILE_PATH));
+

	return (ret);
}

modified pkg/pkg.conf.5
@@ -15,7 +15,7 @@
.\"     @(#)pkg.1
.\" $FreeBSD$
.\"
-
.Dd February 23, 2012
+
.Dd March 24, 2012
.Dt PKG.CONF 5
.Os
.Sh NAME
@@ -94,6 +94,11 @@ for this option is
.It Cm SYSLOG(boolean)
This option is enabled by default, log all the
installation/deinstallation/upgrade operation via syslog(3)
+
.It Cm SHLIBS(boolean)
+
Analyse elf and track all shared libraries needed by the packages. default: off
+
.It Cm AUTODEPS(boolean)
+
Analyse the elf to add dependencies (share libraries) that may have been
+
forgotten by the maintainer. default: off
.El
.Sh ENVIRONMENT
An environment variable with the same name as the option in the configuration 
modified pkg/pkg.conf.sample
@@ -11,7 +11,9 @@ PUBKEY : /etc/ssl/pkg.conf
HANDLE_RC_SCRIPTS   : NO
PKG_MULTIREPOS	    : NO
ASSUME_ALWAYS_YES   : NO
-
SYSLOG          : YES
+
SYSLOG		    : YES
+
SHLIBS		    : NO
+
AUTODEPS	    : NO

# Repository definitions
repos:
modified pkg/register.c
@@ -92,7 +92,6 @@ exec_register(int argc, char **argv)
	const char *desc = NULL;
	size_t size;

-
	bool heuristic = false;
	bool legacy = false;

	int i;
@@ -199,16 +198,11 @@ exec_register(int argc, char **argv)
	if (plist != NULL)
		free(plist);

-
/*	if (pkg_register_shlibs(pkg) != EPKG_OK) {
-
		return (EX_IOERR);
-
	}*/
-

	if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK) {
		return (EX_IOERR);
	}

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

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