Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 30 Apr 2012 21:26:36 +0000 (UTC)
From:      Baptiste Daroussin <bapt@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r234851 - in head: libexec/rtld-elf share/man/man5
Message-ID:  <201204302126.q3ULQac3085886@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: bapt
Date: Mon Apr 30 21:26:35 2012
New Revision: 234851
URL: http://svn.freebsd.org/changeset/base/234851

Log:
  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

Modified:
  head/libexec/rtld-elf/libmap.c
  head/share/man/man5/libmap.conf.5

Modified: head/libexec/rtld-elf/libmap.c
==============================================================================
--- head/libexec/rtld-elf/libmap.c	Mon Apr 30 21:02:57 2012	(r234850)
+++ head/libexec/rtld-elf/libmap.c	Mon Apr 30 21:26:35 2012	(r234851)
@@ -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 c
 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);

Modified: head/share/man/man5/libmap.conf.5
==============================================================================
--- head/share/man/man5/libmap.conf.5	Mon Apr 30 21:02:57 2012	(r234850)
+++ head/share/man/man5/libmap.conf.5	Mon Apr 30 21:26:35 2012	(r234851)
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd January 31, 2004
+.Dd April 28, 2012
 .Dt LIBMAP.CONF 5
 .Os
 .Sh NAME
@@ -43,6 +43,27 @@ left hand side containing the mapping ca
 side containing the mapping.
 Dependencies are matched against candidates and replaced with the mappings.
 .Pp
+Two special directives are available:
+.Bl -tag -width indent
+.It Cm include Ar file
+Parse the contents of
+.Ar file
+before continuing with the current file.
+.It Cm includedir Ar dir
+Parse the contents of every file in
+.Ar dir
+that ends in
+.Pa .conf
+before continuing with the current file.
+.El
+.Pp
+Any file or directory encountered while processing
+.Cm include
+or
+.Cm includedir
+directives will be parsed exactly once, even if it is encountered
+multiple times.
+.Pp
 Constrained mappings may be specified by enclosing the name of the
 executable or library in brackets.
 All mappings following a constraint will only be evaluated for that constraint.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201204302126.q3ULQac3085886>