1 /* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007 Red Hat, Inc.
2 Written by Jakub Jelinek <jakub@redhat.com>, 2001.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
33 #include "prelinktab.h"
36 #ifndef HAVE_FTW_ACTIONRETVAL
37 # define FTW_ACTIONRETVAL 0
38 # define FTW_CONTINUE 0
42 static int gather_lib (struct prelink_entry *ent);
45 static struct prelink_dir *dirs;
46 static struct prelink_dir *blacklist;
47 #ifndef HAVE_FTW_ACTIONRETVAL
48 static char *blacklist_dir;
49 static size_t blacklist_dir_len;
51 static struct extension
57 static int blacklist_next;
60 gather_deps (DSO *dso, struct prelink_entry *ent)
66 char *line = NULL, *p, *q = NULL;
67 const char **depends = NULL;
68 size_t ndepends = 0, ndepends_alloced = 0;
73 Elf32_Lib *liblist = NULL;
76 const char *ent_filename;
81 ent->type = ET_UNPRELINKABLE;
85 ent->pltgot = dso->info[DT_PLTGOT];
86 ent->soname = strdup (dso->soname);
87 ent->flags = (dso->arch->class == ELFCLASS64 ? PCF_ELF64 : 0)
88 | (dso->arch->machine & PCF_MACHINE);
89 if (ent->soname == NULL)
91 error (0, ENOMEM, "%s: Could not record SONAME", ent->filename);
95 dl = dynamic_linker ?: dso->arch->dynamic_linker;
96 if (strcmp (dso->filename, dl) == 0
97 || is_ldso_soname (dso->soname))
99 if (dynamic_info_is_set (dso, DT_GNU_PRELINKED_BIT)
100 && dynamic_info_is_set (dso, DT_CHECKSUM_BIT))
102 if (! undo && dso->arch->read_opd)
103 dso->arch->read_opd (dso, ent);
110 for (i = 1; i < dso->ehdr.e_shnum; ++i)
113 if (dso->shdr[i].sh_type == SHT_GNU_LIBLIST
114 && (name = strptr (dso, dso->ehdr.e_shstrndx, dso->shdr[i].sh_name))
115 && ! strcmp (name, ".gnu.liblist")
116 && (dso->shdr[i].sh_size % sizeof (Elf32_Lib)) == 0)
118 nliblist = dso->shdr[i].sh_size / sizeof (Elf32_Lib);
119 liblist = (Elf32_Lib *) alloca (dso->shdr[i].sh_size);
121 data = elf_getdata (scn, NULL);
122 if (data == NULL || elf_getdata (scn, data)
123 || data->d_buf == NULL || data->d_off
124 || data->d_size != dso->shdr[i].sh_size)
127 memcpy (liblist, data->d_buf, dso->shdr[i].sh_size);
132 && dso->shdr[i].sh_type == SHT_PROGBITS
133 && (name = strptr (dso, dso->ehdr.e_shstrndx,
134 dso->shdr[i].sh_name))
135 && ! strcmp (name, ".gnu.prelink_undo"))
139 if (! undo && dso->arch->read_opd)
140 dso->arch->read_opd (dso, ent);
148 argv[i++] = "--library-path";
149 argv[i++] = ld_library_path;
151 if (strchr (ent->filename, '/') != NULL)
152 ent_filename = ent->filename;
155 size_t flen = strlen (ent->filename);
156 char *tp = alloca (2 + flen + 1);
157 memcpy (tp, "./", 2);
158 memcpy (tp + 2, ent->filename, flen + 1);
161 argv[i++] = ent_filename;
163 envp[0] = "LD_TRACE_LOADED_OBJECTS=1";
164 envp[1] = "LD_TRACE_PRELINKING=1";
165 envp[2] = "LD_WARN=";
167 f = execve_open (dl, (char * const *)argv, (char * const *)envp);
173 n = getline (&line, &len, f);
177 if (line[n - 1] == '\n')
180 p = strstr (line, " => ");
183 q = strstr (p, " (");
184 if (q == NULL && strcmp (p, " => not found") == 0)
186 error (0, 0, "%s: Could not find one of the dependencies",
191 if (p == NULL || q == NULL)
193 if (strstr (line, "statically linked") != NULL)
194 error (0, 0, "%s: Library without dependencies", ent->filename);
197 p = strstr (line, "error while loading shared libraries: ");
200 p += sizeof "error while loading shared libraries: " - 1;
201 q = strstr (line, "cannot open shared object file: "
202 "No such file or directory");
206 "%s: Could not find one of the dependencies",
211 error (0, 0, "%s: Could not parse `%s'", ent->filename, line);
217 p += sizeof " => " - 1;
219 if (! strcmp (p, ent_filename))
224 if (ndepends == ndepends_alloced)
226 ndepends_alloced += 10;
228 (const char **) realloc (depends,
229 ndepends_alloced * sizeof (char *));
232 error (0, ENOMEM, "%s: Could not record dependencies",
238 depends[ndepends] = strdupa (p);
242 if (execve_close (f))
245 error (0, 0, "%s: Dependency tracing failed", ent->filename);
252 error (0, 0, "%s seen %d times in LD_TRACE_PRELINKING output, expected once",
253 ent->filename, seen);
265 (struct prelink_entry **)
266 malloc (ndepends * sizeof (struct prelink_entry *));
267 if (ent->depends == NULL)
269 error (0, ENOMEM, "%s: Could not record dependencies", ent->filename);
274 ent->ndepends = ndepends;
275 char *cache_dyn_depends = NULL;
278 cache_dyn_depends = alloca (ndepends);
279 memset (cache_dyn_depends, '\0', ndepends);
281 for (i = 0; i < ndepends; ++i)
283 ent->depends[i] = prelink_find_entry (depends [i], NULL, 1);
284 if (ent->depends[i] == NULL)
285 goto error_out_free_depends;
287 if (ent->depends[i]->type == ET_CACHE_DYN)
289 ent->depends[i]->type = ET_NONE;
290 free (ent->depends[i]->depends);
291 ent->depends[i]->depends = NULL;
292 ent->depends[i]->ndepends = 0;
293 cache_dyn_depends[i] = 1;
296 if (ent->depends[i]->type != ET_NONE
297 && ent->depends[i]->type != ET_BAD
298 && ent->depends[i]->type != ET_DYN
299 && ent->depends[i]->type != ET_UNPRELINKABLE)
301 error (0, 0, "%s is not a shared library", depends [i]);
302 error_out_regather_libs:
303 for (i = 0; i < ndepends; ++i)
305 if (cache_dyn_depends[i] && ent->depends[i]->type == ET_NONE)
306 gather_lib (ent->depends[i]);
308 goto error_out_free_depends;
315 for (i = 0; i < ndepends; ++i)
316 if (ent->depends[i]->type == ET_NONE
317 && gather_lib (ent->depends[i]))
319 cache_dyn_depends[i] = 0;
320 goto error_out_regather_libs;
323 for (i = 0; i < ndepends; ++i)
324 for (j = 0; j < ent->depends[i]->ndepends; ++j)
325 if (ent->depends[i]->depends[j] == ent)
327 error (0, 0, "%s has a dependency cycle", ent->canon_filename);
328 goto error_out_free_depends;
331 for (i = 0; i < ndepends; ++i)
332 if (ent->depends[i]->type == ET_UNPRELINKABLE)
334 error (0, 0, "Could not prelink %s because its dependency %s could not be prelinked",
335 ent->filename, ent->depends[i]->filename);
336 ent->type = ET_UNPRELINKABLE;
340 if (! undo && (!nliblist || liblist) && nliblist == ndepends)
342 for (i = 0; i < ndepends; ++i)
343 if (liblist[i].l_time_stamp != ent->depends[i]->timestamp
344 || liblist[i].l_checksum != ent->depends[i]->checksum
345 || ! ent->depends[i]->done)
354 error_out_free_depends:
369 gather_dso (DSO *dso, struct prelink_entry *ent)
374 printf ("Checking shared library %s\n", ent->canon_filename);
376 if (dso->ehdr.e_type != ET_DYN)
378 error (0, 0, "%s is not a shared library", ent->filename);
383 prelinked = (dynamic_info_is_set (dso, DT_GNU_PRELINKED_BIT)
384 && dynamic_info_is_set (dso, DT_CHECKSUM_BIT));
385 ent->timestamp = dso->info_DT_GNU_PRELINKED;
386 ent->checksum = dso->info_DT_CHECKSUM;
387 ent->base = dso->base;
389 if (dso->arch->need_rel_to_rela != NULL && ! prelinked)
391 /* If the library has not been prelinked yet and we need
392 to convert REL to RELA, then make room for it. */
393 struct reloc_info rinfo;
394 GElf_Addr adjust = 0;
395 int sec = dso->ehdr.e_shnum;
397 if (find_reloc_sections (dso, &rinfo))
403 assert (sizeof (Elf32_Rel) * 3 == sizeof (Elf32_Rela) * 2);
404 assert (sizeof (Elf64_Rel) * 3 == sizeof (Elf64_Rela) * 2);
405 if (rinfo.rel_to_rela)
408 adjust = (dso->shdr[rinfo.last].sh_addr
409 + dso->shdr[rinfo.last].sh_size
410 - dso->shdr[rinfo.first].sh_addr) / 2;
412 if (rinfo.rel_to_rela_plt)
416 adjust += dso->shdr[rinfo.plt].sh_size / 2;
420 int align = 0, i, last;
423 for (i = rinfo.plt ? rinfo.plt : rinfo.first;
424 i < dso->ehdr.e_shnum; i++)
426 if (dso->shdr[i].sh_addralign > align)
427 align = dso->shdr[i].sh_addralign;
431 start = dso->shdr[rinfo.plt].sh_addr
432 + dso->shdr[rinfo.plt].sh_size;
434 start = dso->shdr[rinfo.first].sh_addr
435 + dso->shdr[rinfo.first].sh_size;
437 /* Need to make sure that all the remaining sections are properly
440 adjust = (adjust + align - 1) & ~(align - 1);
442 /* Need to make sure adjust doesn't cause different Phdr segments
443 to overlap on the same page. */
445 for (i = 0; i < dso->ehdr.e_phnum; ++i)
446 if (dso->phdr[i].p_type == PT_LOAD
447 && dso->phdr[i].p_vaddr + dso->phdr[i].p_memsz >= start)
450 && (((dso->phdr[last].p_vaddr + dso->phdr[last].p_memsz
451 - 1) ^ dso->phdr[i].p_vaddr)
452 & ~(dso->arch->max_page_size - 1))
453 && !(((dso->phdr[last].p_vaddr + dso->phdr[last].p_memsz
455 ^ (dso->phdr[i].p_vaddr + adjust))
456 & ~(dso->arch->max_page_size - 1)))
458 if (align >= dso->arch->max_page_size)
460 error (0, 0, "%s: Cannot grow reloc sections",
465 adjust = (adjust + dso->arch->max_page_size - 1)
466 & ~(dso->arch->max_page_size - 1);
475 if (gather_deps (dso, ent))
478 if (ent->done && ! prelinked && ! undo)
485 gather_lib (struct prelink_entry *ent)
490 dso = open_dso (ent->filename);
494 return gather_dso (dso, ent);
498 gather_exec (DSO *dso, const struct stat64 *st)
503 struct prelink_entry *ent;
506 printf ("Checking executable %s\n", dso->filename);
508 for (i = 0; i < dso->ehdr.e_phnum; ++i)
509 if (dso->phdr[i].p_type == PT_INTERP)
512 /* If there are no PT_INTERP segments, it is statically linked. */
513 if (i == dso->ehdr.e_phnum)
519 ent = prelink_find_entry (dso->filename, st, 1);
523 assert (ent->type == ET_NONE);
524 ent->type = ET_UNPRELINKABLE;
530 j = addr_to_sec (dso, dso->phdr[i].p_vaddr);
531 if (j == -1 || dso->shdr[j].sh_addr != dso->phdr[i].p_vaddr
532 || dso->shdr[j].sh_type != SHT_PROGBITS)
534 error (0, 0, "%s: PT_INTERP segment not corresponding to .interp section",
536 goto make_unprelinkable;
539 data = elf_getdata (dso->scn[j], NULL);
542 error (0, 0, "%s: Could not read .interp section", dso->filename);
546 i = strnlen (data->d_buf, data->d_size);
547 if (i == data->d_size)
549 error (0, 0, "%s: .interp section not zero terminated", dso->filename);
553 dl = dynamic_linker ?: dso->arch->dynamic_linker;
554 if (strcmp (dl, data->d_buf) != 0)
556 error (0, 0, "%s: Using %s, not %s as dynamic linker", dso->filename,
557 (char *) data->d_buf, dl);
561 ent = prelink_find_entry (dso->filename, st, 1);
565 assert (ent->type == ET_NONE);
568 if (gather_deps (dso, ent))
571 for (i = 0; i < ent->ndepends; ++i)
572 ++ent->depends[i]->refs;
584 add_dir_to_dirlist (const char *name, dev_t dev, int flags)
586 const char *canon_name;
587 struct prelink_dir *dir;
590 canon_name = prelink_canonicalize (name, NULL);
591 if (canon_name == NULL)
593 if (! all && implicit)
595 error (0, errno, "Could not record directory %s", name);
599 len = strlen (canon_name);
601 for (dir = blacklist; dir; dir = dir->next)
602 if (((dir->flags != FTW_CHDIR && len >= dir->len)
603 || (dir->flags == FTW_CHDIR && len == dir->len))
604 && strncmp (dir->dir, canon_name, dir->len) == 0)
606 if (dir->flags == FTW_CHDIR)
608 if ((dir->flags & FTW_MOUNT) && dir->dev != dev)
615 free ((char *) canon_name);
619 dir = malloc (sizeof (struct prelink_dir) + len + 1);
622 error (0, ENOMEM, "Could not record directory %s", name);
623 free ((char *) canon_name);
631 strcpy (dir->dir, canon_name);
632 free ((char *) canon_name);
638 gather_func (const char *name, const struct stat64 *st, int type,
641 unsigned char e_ident [sizeof (Elf64_Ehdr) + sizeof (Elf64_Phdr)];
643 #ifndef HAVE_FTW_ACTIONRETVAL
646 if (strncmp (name, blacklist_dir, blacklist_dir_len) == 0)
648 free (blacklist_dir);
649 blacklist_dir = NULL;
652 if (type == FTW_F && S_ISREG (st->st_mode) && (st->st_mode & 0111))
656 struct prelink_entry *ent;
657 size_t len = strlen (name);
658 const char *base = NULL;
660 for (i = 0; i < blacklist_next; ++i)
661 if (blacklist_ext[i].is_glob)
665 base = strrchr (name, '/');
671 if (fnmatch (blacklist_ext[i].ext, base, FNM_PERIOD) == 0)
674 else if (blacklist_ext[i].len <= len
675 && memcmp (name + len - blacklist_ext[i].len,
676 blacklist_ext[i].ext, blacklist_ext[i].len) == 0)
679 ent = prelink_find_entry (name, st, 0);
680 if (ent != NULL && ent->type != ET_NONE)
684 if (ent->type == ET_CACHE_EXEC || ent->type == ET_CACHE_DYN)
685 printf ("Assuming prelinked %s\n", name);
686 if (ent->type == ET_UNPRELINKABLE)
687 printf ("Assuming non-prelinkable %s\n", name);
693 if (st->st_size < sizeof (e_ident))
696 fd = open (name, O_RDONLY);
700 if (read (fd, e_ident, sizeof (e_ident)) != sizeof (e_ident))
707 /* Quickly find ET_EXEC ELF binaries and most of PIE binaries. */
709 if (memcmp (e_ident, ELFMAG, SELFMAG) != 0)
714 ent = prelink_find_entry (name, st, 1);
717 assert (ent->type == ET_NONE);
718 ent->type = ET_UNPRELINKABLE;
725 switch (e_ident [EI_DATA])
728 if (e_ident [EI_NIDENT + 1] != 0)
729 goto make_unprelinkable;
730 if (e_ident [EI_NIDENT] != ET_EXEC)
732 if (e_ident [EI_NIDENT] != ET_DYN)
733 goto make_unprelinkable;
734 else if (e_ident [EI_CLASS] == ELFCLASS32)
736 if (e_ident [offsetof (Elf32_Ehdr, e_phoff)]
737 == sizeof (Elf32_Ehdr)
738 && memcmp (e_ident + offsetof (Elf32_Ehdr, e_phoff) + 1,
740 && (e_ident [offsetof (Elf32_Ehdr, e_phnum)]
741 || e_ident [offsetof (Elf32_Ehdr, e_phnum) + 1])
742 && e_ident [sizeof (Elf32_Ehdr)
743 + offsetof (Elf32_Phdr, p_type)] == PT_PHDR
744 && memcmp (e_ident + sizeof (Elf32_Ehdr)
745 + offsetof (Elf32_Phdr, p_type) + 1,
749 dso = fdopen_dso (fd, name);
752 if (dynamic_info_is_set (dso, DT_DEBUG))
755 goto make_unprelinkable;
761 else if (e_ident [EI_CLASS] == ELFCLASS64)
763 if (e_ident [offsetof (Elf64_Ehdr, e_phoff)]
764 == sizeof (Elf64_Ehdr)
765 && memcmp (e_ident + offsetof (Elf64_Ehdr, e_phoff) + 1,
766 "\0\0\0\0\0\0\0", 7) == 0
767 && (e_ident [offsetof (Elf64_Ehdr, e_phnum)]
768 || e_ident [offsetof (Elf64_Ehdr, e_phnum) + 1])
769 && e_ident [sizeof (Elf64_Ehdr)
770 + offsetof (Elf64_Phdr, p_type)] == PT_PHDR
771 && memcmp (e_ident + sizeof (Elf64_Ehdr)
772 + offsetof (Elf64_Phdr, p_type) + 1,
778 goto make_unprelinkable;
782 if (e_ident [EI_NIDENT] != 0)
783 goto make_unprelinkable;
784 if (e_ident [EI_NIDENT + 1] != ET_EXEC)
786 if (e_ident [EI_NIDENT + 1] != ET_DYN)
787 goto make_unprelinkable;
788 else if (e_ident [EI_CLASS] == ELFCLASS32)
790 if (e_ident [offsetof (Elf32_Ehdr, e_phoff) + 3]
791 == sizeof (Elf32_Ehdr)
792 && memcmp (e_ident + offsetof (Elf32_Ehdr, e_phoff),
794 && (e_ident [offsetof (Elf32_Ehdr, e_phnum)]
795 || e_ident [offsetof (Elf32_Ehdr, e_phnum) + 1])
796 && e_ident [sizeof (Elf32_Ehdr)
797 + offsetof (Elf32_Phdr, p_type) + 3]
799 && memcmp (e_ident + sizeof (Elf32_Ehdr)
800 + offsetof (Elf32_Phdr, p_type),
805 else if (e_ident [EI_CLASS] == ELFCLASS64)
807 if (e_ident [offsetof (Elf64_Ehdr, e_phoff) + 7]
808 == sizeof (Elf64_Ehdr)
809 && memcmp (e_ident + offsetof (Elf64_Ehdr, e_phoff),
810 "\0\0\0\0\0\0\0", 7) == 0
811 && (e_ident [offsetof (Elf64_Ehdr, e_phnum)]
812 || e_ident [offsetof (Elf64_Ehdr, e_phnum) + 1])
813 && e_ident [sizeof (Elf64_Ehdr)
814 + offsetof (Elf64_Phdr, p_type) + 3]
816 && memcmp (e_ident + sizeof (Elf64_Ehdr)
817 + offsetof (Elf64_Phdr, p_type),
823 goto make_unprelinkable;
827 goto make_unprelinkable;
830 dso = fdopen_dso (fd, name);
834 gather_exec (dso, st);
836 else if (type == FTW_D)
837 switch (add_dir_to_dirlist (name, st->st_dev, FTW_CHDIR))
839 case 0: return FTW_CONTINUE;
840 default: return FTW_STOP;
842 #ifdef HAVE_FTW_ACTIONRETVAL
843 return FTW_SKIP_SUBTREE;
846 blacklist_dir_len = strlen (name) + 1;
847 if (blacklist_dir_len > 1 && name[blacklist_dir_len - 2] == '/')
849 blacklist_dir = malloc (blacklist_dir_len + 1);
850 if (blacklist_dir == NULL)
852 error (0, ENOMEM, "Cannot store blacklisted dir name");
855 memcpy (blacklist_dir, name, blacklist_dir_len - 1);
856 blacklist_dir[blacklist_dir_len - 1] = '/';
857 blacklist_dir[blacklist_dir_len] = '\0';
867 gather_binlib (const char *name, const struct stat64 *st)
869 unsigned char e_ident [EI_NIDENT + 2];
872 struct prelink_entry *ent;
874 if (! S_ISREG (st->st_mode))
876 error (0, 0, "%s is not a regular file", name);
880 ent = prelink_find_entry (name, st, 0);
881 if (ent != NULL && ent->type == ET_UNPRELINKABLE)
888 if (ent != NULL && ent->type != ET_NONE)
894 fd = open (name, O_RDONLY);
897 error (0, errno, "Could not open %s", name);
901 if (read (fd, e_ident, sizeof (e_ident)) != sizeof (e_ident))
903 error (0, errno, "Could not read ELF header from %s", name);
908 /* Quickly find ET_EXEC/ET_DYN ELF binaries/libraries only. */
910 if (memcmp (e_ident, ELFMAG, SELFMAG) != 0)
912 error (0, 0, "%s is not an ELF object", name);
917 switch (e_ident [EI_DATA])
920 if (e_ident [EI_NIDENT + 1] != 0)
921 goto unsupported_type;
922 type = e_ident [EI_NIDENT];
925 if (e_ident [EI_NIDENT] != 0)
926 goto unsupported_type;
927 type = e_ident [EI_NIDENT + 1];
930 goto unsupported_type;
933 if (type != ET_EXEC && type != ET_DYN)
936 error (0, 0, "%s is neither ELF executable nor ELF shared library", name);
941 dso = fdopen_dso (fd, name);
949 for (i = 0; i < dso->ehdr.e_phnum; ++i)
950 if (dso->phdr[i].p_type == PT_INTERP)
953 /* If there are no PT_INTERP segments, it is statically linked. */
954 if (i == dso->ehdr.e_phnum)
956 error (0, 0, "%s is statically linked", name);
961 return gather_exec (dso, st);
964 ent = prelink_find_entry (name, st, 1);
971 assert (ent->type == ET_NONE);
974 return gather_dso (dso, ent);
978 gather_object (const char *name, int deref, int onefs)
982 if (stat64 (name, &st) < 0)
986 error (0, errno, "Could not stat %s", name);
990 if (S_ISDIR (st.st_mode))
993 if (! deref) flags |= FTW_PHYS;
994 if (onefs) flags |= FTW_MOUNT;
996 if (implicit && ! deref)
998 ret = add_dir_to_dirlist (name, st.st_dev, flags);
1000 return ret == 2 ? 0 : 1;
1002 if (!all && implicit && ! deref)
1005 ret = nftw64 (name, gather_func, 20, flags | FTW_ACTIONRETVAL);
1008 error (0, errno, "Failed searching %s", name);
1009 #ifndef HAVE_FTW_ACTIONRETVAL
1010 free (blacklist_dir);
1011 blacklist_dir = NULL;
1016 return gather_binlib (name, &st);
1019 static struct config_line
1021 struct config_line *next;
1023 } *config_lines, **config_end = &config_lines;
1026 read_config (const char *config)
1028 FILE *file = fopen (config, "r");
1032 struct config_line *c;
1036 error (0, errno, "Can't open configuration file %s", config);
1042 ssize_t i = getline (&line, &len, file);
1048 if (line[i - 1] == '\n')
1051 p = strchr (line, '#');
1055 p = line + strspn (line, " \t");
1056 if (p[0] == '-' && p[1] == 'c' && (p[2] == ' ' || p[2] == '\t'))
1059 p += 2 + strspn (p + 2, " \t");
1061 if (!glob (p, GLOB_BRACE, NULL, &g))
1065 for (n = 0; n < g.gl_pathc; ++n)
1066 if (read_config (g.gl_pathv[n]))
1080 c = malloc (sizeof (*c) + llen);
1083 error (0, ENOMEM, "Could not cache config file");
1089 memcpy (c->line, p, llen + 1);
1091 config_end = &c->next;
1093 while (!feof (file));
1101 gather_config (void)
1103 struct config_line *c;
1107 for (c = config_lines; c; c = c->next)
1117 case 'h': deref = 1; break;
1118 case 'l': onefs = 1; break;
1119 case 'b': p = ""; continue;
1121 error (0, 0, "Unknown directory option `%s'\n", p);
1124 p = p + 2 + strspn (p + 2, " \t");
1130 if (strpbrk (p, "*?[{") == NULL)
1132 ret = gather_object (p, deref, onefs);
1143 if (!glob (p, GLOB_BRACE, NULL, &g))
1147 for (n = 0; n < g.gl_pathc; ++n)
1149 ret = gather_object (g.gl_pathv[n], deref, onefs);
1169 gather_check_lib (void **p, void *info)
1171 struct prelink_entry *e = * (struct prelink_entry **) p;
1173 if (e->type != ET_DYN)
1176 if (! e->u.explicit)
1178 struct prelink_dir *dir;
1182 name = strrchr (e->canon_filename, '/');
1184 name = e->canon_filename;
1185 len = name - e->canon_filename;
1187 for (dir = blacklist; dir; dir = dir->next)
1188 if (((dir->flags != FTW_CHDIR && len >= dir->len)
1189 || (dir->flags == FTW_CHDIR && len == dir->len))
1190 && strncmp (dir->dir, e->canon_filename, dir->len) == 0)
1192 if (dir->flags == FTW_CHDIR)
1194 if ((dir->flags & FTW_MOUNT) && dir->dev != e->dev)
1201 error (0, 0, "%s is present in a blacklisted directory %s",
1202 e->canon_filename, dir->dir);
1207 for (dir = dirs; dir; dir = dir->next)
1208 if (((dir->flags != FTW_CHDIR && len >= dir->len)
1209 || (dir->flags == FTW_CHDIR && len == dir->len))
1210 && strncmp (dir->dir, e->canon_filename, dir->len) == 0)
1212 if (dir->flags == FTW_CHDIR)
1214 if ((dir->flags & FTW_MOUNT) && dir->dev != e->dev)
1221 error (0, 0, "%s is not present in any config file directories, nor was specified on command line",
1232 gather_check_libs (void)
1234 struct prelink_dir *dir;
1237 htab_traverse (prelink_filename_htab, gather_check_lib, NULL);
1261 add_to_blacklist (const char *name, int deref, int onefs)
1263 const char *canon_name;
1264 struct prelink_dir *path;
1268 if (stat64 (name, &st) < 0)
1272 error (0, errno, "Could not stat %s", name);
1276 if (!S_ISDIR (st.st_mode))
1278 struct prelink_entry *ent;
1280 ent = prelink_find_entry (name, &st, 1);
1285 ent->u.explicit = 1;
1289 canon_name = prelink_canonicalize (name, NULL);
1290 if (canon_name == NULL)
1294 error (0, errno, "Could not canonicalize %s", name);
1298 len = strlen (canon_name);
1299 path = malloc (sizeof (struct prelink_dir) + len + 1);
1302 error (0, ENOMEM, "Could not record path %s", name);
1303 free ((char *) canon_name);
1307 path->next = blacklist;
1309 if (! deref) path->flags |= FTW_PHYS;
1310 if (onefs) path->flags |= FTW_MOUNT;
1313 strcpy (path->dir, canon_name);
1314 free ((char *) canon_name);
1320 add_blacklist_ext (const char *ext)
1322 blacklist_ext = realloc (blacklist_ext,
1323 (blacklist_next + 1) * sizeof (*blacklist_ext));
1324 if (blacklist_ext == NULL)
1325 error (EXIT_FAILURE, errno, "can't create blacklist extension list");
1326 if (*ext == '*' && strpbrk (ext + 1, "*?[{") == NULL)
1328 blacklist_ext[blacklist_next].is_glob = 0;
1332 blacklist_ext[blacklist_next].is_glob = 1;
1333 blacklist_ext[blacklist_next].ext = strdup (ext);
1334 if (blacklist_ext[blacklist_next].ext == NULL)
1335 error (EXIT_FAILURE, errno, "can't create blacklist extension list");
1336 blacklist_ext[blacklist_next].len = strlen (ext);
1341 blacklist_from_config (void)
1343 struct config_line *c;
1347 for (c = config_lines; c; c = c->next)
1358 case 'h': deref = 1; break;
1359 case 'l': onefs = 1; break;
1360 case 'b': blacklist = 1; break;
1362 p = p + 2 + strspn (p + 2, " \t");
1365 if (*p == '\0' || !blacklist)
1368 if (strchr (p, '/') == NULL)
1370 add_blacklist_ext (p);
1374 if (strpbrk (p, "*?[{") == NULL)
1376 ret = add_to_blacklist (p, deref, onefs);
1387 if (!glob (p, GLOB_BRACE | GLOB_PERIOD, NULL, &g))
1391 for (n = 0; n < g.gl_pathc; ++n)
1393 ret = add_to_blacklist (g.gl_pathv[n], deref, onefs);