diff options
-rw-r--r-- | doc/prelink.conf | 22 | ||||
-rw-r--r-- | src/cache.c | 2 | ||||
-rw-r--r-- | src/gather.c | 88 | ||||
-rwxr-xr-x | testsuite/quick2.sh | 33 |
4 files changed, 123 insertions, 22 deletions
diff --git a/doc/prelink.conf b/doc/prelink.conf index 58f1f30..0b0e8ca 100644 --- a/doc/prelink.conf +++ b/doc/prelink.conf @@ -5,18 +5,16 @@ # If a directory name is prefixed with `-h ', symbolic links in a # directory hierarchy are followed. # Directories or files with `-b ' prefix will be blacklisted. -# Lines starting with -e specify file suffixes that should be ignored -# during directory searches to speed things up. --e .la --e .png --e .py --e .pl --e .pm --e .sh --e .xml --e .xslt --e .a --e .js +-b *.la +-b *.png +-b *.py +-b *.pl +-b *.pm +-b *.sh +-b *.xml +-b *.xslt +-b *.a +-b *.js -b /lib/modules -b /usr/lib/locale -b /usr/X11R6/lib{,64}/X11/xfig diff --git a/src/cache.c b/src/cache.c index e045b53..ba9b177 100644 --- a/src/cache.c +++ b/src/cache.c @@ -350,7 +350,7 @@ prelink_load_cache (void) ents[i]->flags = cache->entry[i].flags; if (ents[i]->flags == PCF_UNPRELINKABLE) - ents[i]->type = (quick || print_cache) ? ET_UNPRELINKABLE : ET_NONE; + ents[i]->type = (quick || print_cache) ? ET_UNPRELINKABLE : ET_NONE; /* If mtime is equal to ctime, assume the filesystem does not store ctime. */ diff --git a/src/gather.c b/src/gather.c index bac4a1f..f1e6f08 100644 --- a/src/gather.c +++ b/src/gather.c @@ -20,6 +20,7 @@ #include <errno.h> #include <error.h> #include <fcntl.h> +#include <fnmatch.h> #include <ftw.h> #include <glob.h> #include <stdio.h> @@ -46,6 +47,13 @@ static struct prelink_dir *blacklist; static char *blacklist_dir; static size_t blacklist_dir_len; #endif +static struct extension +{ + const char *ext; + size_t len; + int is_glob; +} *blacklist_ext; +static int blacklist_next; static int gather_deps (DSO *dso, struct prelink_entry *ent) @@ -247,6 +255,12 @@ gather_deps (DSO *dso, struct prelink_entry *ent) } ent->ndepends = ndepends; + char *cache_dyn_depends = NULL; + if (ndepends) + { + cache_dyn_depends = alloca (ndepends); + memset (cache_dyn_depends, '\0', ndepends); + } for (i = 0; i < ndepends; ++i) { ent->depends[i] = prelink_find_entry (depends [i], NULL, 1); @@ -259,6 +273,7 @@ gather_deps (DSO *dso, struct prelink_entry *ent) free (ent->depends[i]->depends); ent->depends[i]->depends = NULL; ent->depends[i]->ndepends = 0; + cache_dyn_depends[i] = 1; } if (ent->depends[i]->type != ET_NONE @@ -267,7 +282,13 @@ gather_deps (DSO *dso, struct prelink_entry *ent) && ent->depends[i]->type != ET_UNPRELINKABLE) { error (0, 0, "%s is not a shared library", depends [i]); - goto error_out_free_depends; +error_out_regather_libs: + for (i = 0; i < ndepends; ++i) + { + if (cache_dyn_depends[i] && ent->depends[i]->type == ET_NONE) + gather_lib (ent->depends[i]); + } + goto error_out_free_depends; } } @@ -277,7 +298,10 @@ gather_deps (DSO *dso, struct prelink_entry *ent) for (i = 0; i < ndepends; ++i) if (ent->depends[i]->type == ET_NONE && gather_lib (ent->depends[i])) - goto error_out_free_depends; + { + cache_dyn_depends[i] = 0; + goto error_out_regather_libs; + } for (i = 0; i < ndepends; ++i) for (j = 0; j < ent->depends[i]->ndepends; ++j) @@ -610,9 +634,30 @@ gather_func (const char *name, const struct stat64 *st, int type, #endif if (type == FTW_F && S_ISREG (st->st_mode) && (st->st_mode & 0111)) { - int fd; + int fd, i; DSO *dso; struct prelink_entry *ent; + size_t len = strlen (name); + const char *base = NULL; + + for (i = 0; i < blacklist_next; ++i) + if (blacklist_ext[i].is_glob) + { + if (base == NULL) + { + base = strrchr (name, '/'); + if (base == NULL) + base = name; + else + ++base; + } + if (fnmatch (blacklist_ext[i].ext, base, FNM_PERIOD) == 0) + return FTW_CONTINUE; + } + else if (blacklist_ext[i].len <= len + && memcmp (name + len - blacklist_ext[i].len, + blacklist_ext[i].ext, blacklist_ext[i].len) == 0) + return FTW_CONTINUE; ent = prelink_find_entry (name, st, 0); if (ent != NULL && ent->type != ET_NONE) @@ -620,10 +665,10 @@ gather_func (const char *name, const struct stat64 *st, int type, if (verbose > 5) { if (ent->type == ET_CACHE_EXEC || ent->type == ET_CACHE_DYN) - printf ("Assuming prelinked %s\n", name); - if (ent->type == ET_UNPRELINKABLE) - printf ("Assuming non-prelinkable %s\n", name); - } + printf ("Assuming prelinked %s\n", name); + if (ent->type == ET_UNPRELINKABLE) + printf ("Assuming non-prelinkable %s\n", name); + } ent->u.explicit = 1; return FTW_CONTINUE; } @@ -1113,6 +1158,27 @@ add_to_blacklist (const char *name, int deref, int onefs) return 0; } +void +add_blacklist_ext (const char *ext) +{ + blacklist_ext = realloc (blacklist_ext, + (blacklist_next + 1) * sizeof (*blacklist_ext)); + if (blacklist_ext == NULL) + error (EXIT_FAILURE, errno, "can't create blacklist extension list"); + if (*ext == '*' && strpbrk (ext + 1, "*?[{") == NULL) + { + blacklist_ext[blacklist_next].is_glob = 0; + ext++; + } + else + blacklist_ext[blacklist_next].is_glob = 1; + blacklist_ext[blacklist_next].ext = strdup (ext); + if (blacklist_ext[blacklist_next].ext == NULL) + error (EXIT_FAILURE, errno, "can't create blacklist extension list"); + blacklist_ext[blacklist_next].len = strlen (ext); + blacklist_next++; +} + int blacklist_from_config (const char *config) { @@ -1162,6 +1228,12 @@ blacklist_from_config (const char *config) if (*p == '\0' || !blacklist) continue; + if (strchr (p, '/') == NULL) + { + add_blacklist_ext (p); + continue; + } + if (strpbrk (p, "*?[{") == NULL) { ret = add_to_blacklist (p, deref, onefs); @@ -1175,7 +1247,7 @@ blacklist_from_config (const char *config) { glob_t g; - if (!glob (p, GLOB_BRACE, NULL, &g)) + if (!glob (p, GLOB_BRACE | GLOB_PERIOD, NULL, &g)) { size_t n; diff --git a/testsuite/quick2.sh b/testsuite/quick2.sh index 3c1c96a..6a154fb 100755 --- a/testsuite/quick2.sh +++ b/testsuite/quick2.sh @@ -78,13 +78,44 @@ echo This is a sample shell script echo used to test whether even shell scripts echo and other executable non-ELF files echo are cached as non-prelinkable -echo in /etc/prelink.cache and thus don\'t +echo in /etc/prelink.cache and thus do not echo need to be reread every time prelink -aq echo is run. exit 0 EOF chmod 755 quick2.tree/usr/bin/bin8 +cat > quick2.tree/usr/bin/bin9.sh <<EOF +#!/bin/sh +echo This is another sample shell script, +echo this time with a .sh extension. +echo This does not need to be even cached +echo as non-prelinkable, provided -b *.sh +echo is present in prelink.conf. +exit 0 +EOF +chmod 755 quick2.tree/usr/bin/bin9.sh +cat > quick2.tree/usr/bin/bin10.py <<EOF +#! /usr/bin/env python +print "This is a sample python script." +print "This does not need to be even cached" +print "as non-prelinkable, provided -b *.py" +print "is present in prelink.conf." +EOF +chmod 755 quick2.tree/usr/bin/bin10.py +cat > quick2.tree/usr/bin/bin11.script <<EOF +#!/bin/sh +echo This is another sample shell script, +echo this time matching b*11*r[hijk]*t shell pattern. +echo This does not need to be even cached +echo as non-prelinkable, provided -b b*11*r[hijk]*t +echo is present in prelink.conf. +exit 0 +EOF +chmod 755 quick2.tree/usr/bin/bin11.script cat > quick2.tree/etc/prelink.conf <<EOF +-b *.sh +-b *.py +-b b*11*r[hijk]*t quick2.tree/usr/bin quick2.tree/lib quick2.tree/usr/lib |