aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/prelink.conf22
-rw-r--r--src/cache.c2
-rw-r--r--src/gather.c88
-rwxr-xr-xtestsuite/quick2.sh33
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