aboutsummaryrefslogtreecommitdiff
path: root/elf
diff options
context:
space:
mode:
Diffstat (limited to 'elf')
-rw-r--r--elf/ldconfig.c81
1 files changed, 77 insertions, 4 deletions
diff --git a/elf/ldconfig.c b/elf/ldconfig.c
index a3b2cdc073..a208ce628d 100644
--- a/elf/ldconfig.c
+++ b/elf/ldconfig.c
@@ -34,6 +34,8 @@
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <glob.h>
+#include <libgen.h>
#include "ldconfig.h"
#include "dl-cache.h"
@@ -934,16 +936,20 @@ search_dirs (void)
}
+static void parse_conf_include (const char *config_file, unsigned int lineno,
+ bool do_chroot, const char *pattern);
+
/* Parse configuration file. */
static void
-parse_conf (const char *filename)
+parse_conf (const char *filename, bool do_chroot)
{
FILE *file = NULL;
char *line = NULL;
const char *canon;
size_t len = 0;
+ unsigned int lineno;
- if (opt_chroot)
+ if (do_chroot && opt_chroot)
{
canon = chroot_canon (opt_chroot, filename);
if (canon)
@@ -971,12 +977,14 @@ parse_conf (const char *filename)
if (canon != filename)
free ((char *) canon);
+ lineno = 0;
do
{
ssize_t n = getline (&line, &len, file);
if (n < 0)
break;
+ ++lineno;
if (line[n - 1] == '\n')
line[n - 1] = '\0';
@@ -994,7 +1002,16 @@ parse_conf (const char *filename)
if (cp[0] == '\0')
continue;
- add_dir (cp);
+ if (!strncmp (cp, "include", 7) && isblank (cp[7]))
+ {
+ char *dir;
+ cp += 8;
+ while ((dir = strsep (&cp, " \t")) != NULL)
+ if (dir[0] != '\0')
+ parse_conf_include (filename, lineno, do_chroot, dir);
+ }
+ else
+ add_dir (cp);
}
while (!feof_unlocked (file));
@@ -1003,6 +1020,62 @@ parse_conf (const char *filename)
fclose (file);
}
+/* Handle one word in an `include' line, a glob pattern of additional
+ config files to read. */
+static void
+parse_conf_include (const char *config_file, unsigned int lineno,
+ bool do_chroot, const char *pattern)
+{
+ if (opt_chroot && pattern[0] != '/')
+ error (EXIT_FAILURE, 0,
+ _("need absolute file name for configuration file when using -r"));
+
+ char *copy = NULL;
+ if (pattern[0] != '/' && strchr (config_file, '/') != NULL)
+ {
+ asprintf (&copy, "%s/%s", dirname (strdupa (config_file)), pattern);
+ pattern = copy;
+ }
+
+ glob64_t gl;
+ int result;
+ if (do_chroot && opt_chroot)
+ {
+ char *canon = chroot_canon (opt_chroot, pattern);
+ result = glob64 (canon ?: pattern, 0, NULL, &gl);
+ free (canon);
+ }
+ else
+ result = glob64 (pattern, 0, NULL, &gl);
+
+ switch (result)
+ {
+ case 0:
+ for (size_t i = 0; i < gl.gl_pathc; ++i)
+ parse_conf (gl.gl_pathv[i], false);
+ globfree64 (&gl);
+ break;
+
+ case GLOB_NOMATCH:
+ break;
+
+ case GLOB_NOSPACE:
+ errno = ENOMEM;
+ case GLOB_ABORTED:
+ if (opt_verbose)
+ error (0, errno, _("%s:%u: cannot read directory %s"),
+ config_file, lineno, pattern);
+ break;
+
+ default:
+ abort ();
+ break;
+ }
+
+ if (copy)
+ free (copy);
+}
+
/* Honour LD_HWCAP_MASK. */
static void
set_hwcap (void)
@@ -1127,7 +1200,7 @@ main (int argc, char **argv)
if (!opt_only_cline)
{
- parse_conf (config_file);
+ parse_conf (config_file, true);
/* Always add the standard search paths. */
add_system_dir (SLIBDIR);