summaryrefslogtreecommitdiffstats
path: root/libexec
diff options
context:
space:
mode:
authorbapt <bapt@FreeBSD.org>2012-04-30 21:26:35 +0000
committerbapt <bapt@FreeBSD.org>2012-04-30 21:26:35 +0000
commit89ed2f6036023c693e82ca528d76e6407e831c76 (patch)
tree12b372966ae1de24821822c51eaaec480f571857 /libexec
parent0ab5229941284beb42ae9a306ce80110115de611 (diff)
downloadFreeBSD-src-89ed2f6036023c693e82ca528d76e6407e831c76.zip
FreeBSD-src-89ed2f6036023c693e82ca528d76e6407e831c76.tar.gz
Add two special directives to libmap.conf:
include <file>: Parse the contents of file before continuing with the current file. includedir <dir>: Parse the contents of every file in dir that ends in .conf before continuing with the current file. Any file or directory encountered while processing include or includedir directives will be parsed exactly once, even if it is encountered multiple times. Reviewed by: kib, des Approved by: des (mentor) MFC after: 1 month
Diffstat (limited to 'libexec')
-rw-r--r--libexec/rtld-elf/libmap.c162
1 files changed, 132 insertions, 30 deletions
diff --git a/libexec/rtld-elf/libmap.c b/libexec/rtld-elf/libmap.c
index cf86703..239dd0c 100644
--- a/libexec/rtld-elf/libmap.c
+++ b/libexec/rtld-elf/libmap.c
@@ -2,11 +2,13 @@
* $FreeBSD$
*/
+#include <sys/types.h>
#include <sys/param.h>
#include <sys/fcntl.h>
#include <sys/mman.h>
#include <sys/queue.h>
#include <sys/stat.h>
+#include <dirent.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
@@ -39,9 +41,17 @@ struct lmp {
TAILQ_ENTRY(lmp) lmp_link;
};
+static TAILQ_HEAD(lmc_list, lmc) lmc_head = TAILQ_HEAD_INITIALIZER(lmc_head);
+struct lmc {
+ char *path;
+ TAILQ_ENTRY(lmc) next;
+};
+
static int lm_count;
static void lmc_parse(char *, size_t);
+static void lmc_parse_file(char *);
+static void lmc_parse_dir(char *);
static void lm_add(const char *, const char *, const char *);
static void lm_free(struct lm_list *);
static char *lml_find(struct lm_list *, const char *);
@@ -61,37 +71,13 @@ static const char *quickbasename(const char *);
int
lm_init(char *libmap_override)
{
- struct stat st;
- char *lm_map, *p;
- int fd;
+ char *p;
dbg("lm_init(\"%s\")", libmap_override);
TAILQ_INIT(&lmp_head);
- fd = open(_PATH_LIBMAP_CONF, O_RDONLY);
- if (fd == -1) {
- dbg("lm_init: open(\"%s\") failed, %s", _PATH_LIBMAP_CONF,
- rtld_strerror(errno));
- goto override;
- }
- if (fstat(fd, &st) == -1) {
- close(fd);
- dbg("lm_init: fstat(\"%s\") failed, %s", _PATH_LIBMAP_CONF,
- rtld_strerror(errno));
- goto override;
- }
- lm_map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
- if (lm_map == (const char *)MAP_FAILED) {
- close(fd);
- dbg("lm_init: mmap(\"%s\") failed, %s", _PATH_LIBMAP_CONF,
- rtld_strerror(errno));
- goto override;
- }
- close(fd);
- lmc_parse(lm_map, st.st_size);
- munmap(lm_map, st.st_size);
+ lmc_parse_file(_PATH_LIBMAP_CONF);
-override:
if (libmap_override) {
/*
* Do some character replacement to make $LIBMAP look
@@ -116,14 +102,116 @@ override:
}
static void
+lmc_parse_file(char *path)
+{
+ struct lmc *p;
+ struct stat st;
+ int fd;
+ char *rpath;
+ char *lm_map;
+
+ rpath = realpath(path, NULL);
+ if (rpath == NULL)
+ return;
+
+ TAILQ_FOREACH(p, &lmc_head, next) {
+ if (strcmp(p->path, rpath) == 0) {
+ free(rpath);
+ return;
+ }
+ }
+
+ fd = open(path, O_RDONLY);
+ if (fd == -1) {
+ dbg("lm_init: open(\"%s\") failed, %s", path,
+ rtld_strerror(errno));
+ free(rpath);
+ return;
+ }
+ if (fstat(fd, &st) == -1) {
+ close(fd);
+ dbg("lm_init: fstat(\"%s\") failed, %s", path,
+ rtld_strerror(errno));
+ free(rpath);
+ return;
+ }
+ lm_map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (lm_map == (const char *)MAP_FAILED) {
+ close(fd);
+ dbg("lm_init: mmap(\"%s\") failed, %s", path,
+ rtld_strerror(errno));
+ free(rpath);
+ return;
+ }
+ close(fd);
+ p = xmalloc(sizeof(struct lmc));
+ p->path = rpath;
+ TAILQ_INSERT_HEAD(&lmc_head, p, next);
+ lmc_parse(lm_map, st.st_size);
+ munmap(lm_map, st.st_size);
+}
+
+static void
+lmc_parse_dir(char *idir)
+{
+ DIR *d;
+ struct dirent *dp;
+ struct lmc *p;
+ char conffile[MAXPATHLEN];
+ char *ext;
+ char *rpath;
+
+ rpath = realpath(idir, NULL);
+ if (rpath == NULL)
+ return;
+
+ TAILQ_FOREACH(p, &lmc_head, next) {
+ if (strcmp(p->path, rpath) == 0) {
+ free(rpath);
+ return;
+ }
+ }
+ d = opendir(idir);
+ if (d == NULL) {
+ free(rpath);
+ return;
+ }
+
+ p = xmalloc(sizeof(struct lmc));
+ p->path = rpath;
+ TAILQ_INSERT_HEAD(&lmc_head, p, next);
+
+ while ((dp = readdir(d)) != NULL) {
+ if (dp->d_ino == 0)
+ continue;
+ if (dp->d_type != DT_REG)
+ continue;
+ ext = strrchr(dp->d_name, '.');
+ if (ext == NULL)
+ continue;
+ if (strcmp(ext, ".conf") != 0)
+ continue;
+ if (strlcpy(conffile, idir, MAXPATHLEN) >= MAXPATHLEN)
+ continue; /* too long */
+ if (strlcat(conffile, "/", MAXPATHLEN) >= MAXPATHLEN)
+ continue; /* too long */
+ if (strlcat(conffile, dp->d_name, MAXPATHLEN) >= MAXPATHLEN)
+ continue; /* too long */
+ lmc_parse_file(conffile);
+ }
+ closedir(d);
+}
+
+static void
lmc_parse(char *lm_p, size_t lm_len)
{
char *cp, *f, *t, *c, *p;
char prog[MAXPATHLEN];
- char line[MAXPATHLEN + 2];
+ /* allow includedir + full length path */
+ char line[MAXPATHLEN + 13];
size_t cnt;
int i;
-
+
cnt = 0;
p = NULL;
while (cnt < lm_len) {
@@ -181,7 +269,8 @@ lmc_parse(char *lm_p, size_t lm_len)
while(rtld_isspace(*cp)) cp++;
if (!iseol(*cp)) continue;
- strcpy(prog, c);
+ if (strlcpy(prog, c, sizeof prog) >= sizeof prog)
+ continue;
p = prog;
continue;
}
@@ -207,7 +296,12 @@ lmc_parse(char *lm_p, size_t lm_len)
if (!iseol(*cp)) continue;
*cp = '\0';
- lm_add(p, f, t);
+ if (strcmp(f, "includedir") == 0)
+ lmc_parse_dir(t);
+ else if (strcmp(f, "include") == 0)
+ lmc_parse_file(t);
+ else
+ lm_add(p, f, t);
}
}
@@ -232,9 +326,17 @@ void
lm_fini (void)
{
struct lmp *lmp;
+ struct lmc *p;
dbg("%s()", __func__);
+ while (!TAILQ_EMPTY(&lmc_head)) {
+ p = TAILQ_FIRST(&lmc_head);
+ TAILQ_REMOVE(&lmc_head, p, next);
+ free(p->path);
+ free(p);
+ }
+
while (!TAILQ_EMPTY(&lmp_head)) {
lmp = TAILQ_FIRST(&lmp_head);
TAILQ_REMOVE(&lmp_head, lmp, lmp_link);
OpenPOWER on IntegriCloud