diff options
Diffstat (limited to 'elf')
-rw-r--r-- | elf/ldconfig.c | 81 |
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 (©, "%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); |