Update.
[platform/upstream/glibc.git] / elf / ldconfig.c
1 /* Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Andreas Jaeger <aj@suse.de>, 1999.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Library General Public License as
7    published by the Free Software Foundation; either version 2 of the
8    License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Library General Public License for more details.
14
15    You should have received a copy of the GNU Library General Public
16    License along with the GNU C Library; see the file COPYING.LIB.  If not,
17    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18    Boston, MA 02111-1307, USA.  */
19
20 #include <alloca.h>
21 #include <argp.h>
22 #include <dirent.h>
23 #include <elf.h>
24 #include <error.h>
25 #include <errno.h>
26 #include <inttypes.h>
27 #include <libintl.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <unistd.h>
32 #include <sys/fcntl.h>
33 #include <sys/mman.h>
34 #include <sys/stat.h>
35 #include <sys/types.h>
36
37 #include "ldconfig.h"
38 #include "dl-cache.h"
39
40 #include "dl-procinfo.h"
41
42 #ifndef LD_SO_CONF
43 # define LD_SO_CONF SYSCONFDIR "/ld.so.conf"
44 #endif
45
46 /* Get libc version number.  */
47 #include <version.h>
48
49 #define PACKAGE _libc_intl_domainname
50
51 struct lib_entry
52   {
53     int flags;
54     uint64_t hwcap;
55     char *lib;
56     char *path;
57   };
58
59 static const struct
60 {
61   const char *name;
62   int flag;
63 } lib_types [] =
64 {
65   {"libc4", FLAG_LIBC4},
66   {"libc5", FLAG_ELF_LIBC5},
67   {"libc6", FLAG_ELF_LIBC6},
68   {"glibc2", FLAG_ELF_LIBC6}
69 };
70
71
72 /* List of directories to handle.  */
73 struct dir_entry
74 {
75   char *path;
76   int flag;
77   struct dir_entry *next;
78 };
79
80 /* The list is unsorted, contains no duplicates.  Entries are added at
81    the end.  */
82 static struct dir_entry *dir_entries;
83
84 /* Flags for different options.  */
85 /* Print Cache.  */
86 static int opt_print_cache = 0;
87
88 /* Be verbose.  */
89 int opt_verbose = 0;
90
91 /* Format to support.  */
92 /* 0: only libc5/glibc2; 1: both; 2: only glibc 2.2.  */
93 int opt_format = 1;
94
95 /* Build cache.  */
96 static int opt_build_cache = 1;
97
98 /* Generate links.  */
99 static int opt_link = 1;
100
101 /* Only process directories specified on the command line.  */
102 static int opt_only_cline = 0;
103
104 /* Path to root for chroot.  */
105 static char *opt_chroot;
106
107 /* Manually link given shared libraries.  */
108 static int opt_manual_link = 0;
109
110 /* Cache file to use.  */
111 static char *cache_file;
112
113 /* Configuration file.  */
114 static const char *config_file;
115
116 /* Name and version of program.  */
117 static void print_version (FILE *stream, struct argp_state *state);
118 void (*argp_program_version_hook) (FILE *, struct argp_state *)
119      = print_version;
120
121 /* Definitions of arguments for argp functions.  */
122 static const struct argp_option options[] =
123 {
124   { "print-cache", 'p', NULL, 0, N_("Print cache"), 0},
125   { "verbose", 'v', NULL, 0, N_("Generate verbose messages"), 0},
126   { NULL, 'N', NULL, 0, N_("Don't build cache"), 0},
127   { NULL, 'X', NULL, 0, N_("Don't generate links"), 0},
128   { NULL, 'r', "ROOT", 0, N_("Change to and use ROOT as root directory"), 0},
129   { NULL, 'C', "CACHE", 0, N_("Use CACHE as cache file"), 0},
130   { NULL, 'f', "CONF", 0, N_("Use CONF as configuration file"), 0},
131   { NULL, 'n', NULL, 0, N_("Only process directories specified on the command line.  Don't build cache."), 0},
132   { NULL, 'l', NULL, 0, N_("Manually link individual libraries."), 0},
133   { "format", 'c', "FORMAT", 0, N_("Format to use: new, old or compat (default)"), 0},
134   { NULL, 0, NULL, 0, NULL, 0 }
135 };
136
137 /* Short description of program.  */
138 static const char doc[] = N_("Configure Dynamic Linker Run Time Bindings.");
139
140 /* Prototype for option handler.  */
141 static error_t parse_opt (int key, char *arg, struct argp_state *state);
142
143 /* Data structure to communicate with argp functions.  */
144 static struct argp argp =
145 {
146   options, parse_opt, NULL, doc, NULL, NULL, NULL
147 };
148
149 /* Check if string corresponds to an important hardware capability or
150    a platform.  */
151 static int
152 is_hwcap_platform (const char *name)
153 {
154   int hwcap_idx = _dl_string_hwcap (name);
155
156   if (hwcap_idx != -1 && ((1 << hwcap_idx) & HWCAP_IMPORTANT))
157     return 1;
158
159   hwcap_idx = _dl_string_platform (name);
160   if (hwcap_idx != -1)
161     return 1;
162
163   return 0;
164 }
165
166 /* Get hwcap (including platform) encoding of path.  */
167 static uint64_t
168 path_hwcap (const char *path)
169 {
170   char *str = xstrdup (path);
171   char *ptr;
172   uint64_t hwcap = 0;
173   uint64_t h;
174
175   size_t len;
176
177   len = strlen (str);
178   if (str[len] == '/')
179     str[len] = '\0';
180
181   /* Search pathname from the end and check for hwcap strings.  */
182   for (;;)
183     {
184       ptr = strrchr (str, '/');
185
186       if (ptr == NULL)
187         break;
188
189       h = _dl_string_hwcap (ptr + 1);
190
191       if (h == (uint64_t) -1)
192         {
193           h = _dl_string_platform (ptr + 1);
194           if (h == (uint64_t) -1)
195             break;
196         }
197       hwcap += 1ULL << h;
198
199       /* Search the next part of the path.  */
200       *ptr = '\0';
201     }
202
203   free (str);
204   return hwcap;
205 }
206
207 /* Handle program arguments.  */
208 static error_t
209 parse_opt (int key, char *arg, struct argp_state *state)
210 {
211   switch (key)
212     {
213     case 'C':
214       cache_file = arg;
215       break;
216     case 'f':
217       config_file = arg;
218       break;
219     case 'l':
220       opt_manual_link = 1;
221       break;
222     case 'N':
223       opt_build_cache = 0;
224       break;
225     case 'n':
226       opt_build_cache = 0;
227       opt_only_cline = 1;
228       break;
229     case 'p':
230       opt_print_cache = 1;
231       break;
232     case 'r':
233       opt_chroot = arg;
234       break;
235     case 'v':
236       opt_verbose = 1;
237       break;
238     case 'X':
239       opt_link = 0;
240       break;
241     case 'c':
242       if (strcmp (arg, "old") == 0)
243         opt_format = 0;
244       else if (strcmp (arg, "compat") == 0)
245         opt_format = 1;
246       else if (strcmp (arg, "new") == 0)
247         opt_format = 2;
248       break;
249     default:
250       return ARGP_ERR_UNKNOWN;
251     }
252
253   return 0;
254 }
255
256 /* Print the version information.  */
257 static void
258 print_version (FILE *stream, struct argp_state *state)
259 {
260   fprintf (stream, "ldconfig (GNU %s) %s\n", PACKAGE, VERSION);
261   fprintf (stream, gettext ("\
262 Copyright (C) %s Free Software Foundation, Inc.\n\
263 This is free software; see the source for copying conditions.  There is NO\n\
264 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
265 "), "2001");
266   fprintf (stream, gettext ("Written by %s.\n"),
267            "Andreas Jaeger");
268 }
269
270 /* Add a single directory entry.  */
271 static void
272 add_single_dir (struct dir_entry *entry, int verbose)
273 {
274   struct dir_entry *ptr, *prev;
275
276   ptr = dir_entries;
277   prev = ptr;
278   while (ptr != NULL)
279     {
280       /* Check for duplicates.  */
281       if (strcmp (ptr->path, entry->path) == 0)
282         {
283           if (opt_verbose && verbose)
284             error (0, 0, _("Path `%s' given more than once"), entry->path);
285           /* Use the newer information.  */
286           ptr->flag = entry->flag;
287           free (entry);
288           break;
289         }
290       prev = ptr;
291       ptr = ptr->next;
292     }
293   /* Is this the first entry?  */
294   if (ptr == NULL && dir_entries == NULL)
295     dir_entries = entry;
296   else if (ptr == NULL)
297     prev->next = entry;
298 }
299
300 /* Add one directory to the list of directories to process.  */
301 static void
302 add_dir (const char *line)
303 {
304   char *equal_sign;
305   struct dir_entry *entry;
306   unsigned int i;
307
308   entry = xmalloc (sizeof (struct dir_entry));
309   entry->next = NULL;
310
311   /* Search for an '=' sign.  */
312   entry->path = xstrdup (line);
313   equal_sign = strchr (entry->path, '=');
314   if (equal_sign)
315     {
316       *equal_sign = '\0';
317       ++equal_sign;
318       entry->flag = FLAG_ANY;
319       for (i = 0; i < sizeof (lib_types) / sizeof (lib_types [0]); ++i)
320         if (strcmp (equal_sign, lib_types[i].name) == 0)
321           {
322             entry->flag = lib_types[i].flag;
323             break;
324           }
325       if (entry->flag == FLAG_ANY)
326         error (0, 0, _("%s is not a known library type"), equal_sign);
327     }
328   else
329     {
330       entry->flag = FLAG_ANY;
331     }
332
333   /* Canonify path: for now only remove trailing slashes.  */
334   i = strlen (entry->path) - 1;
335   while (entry->path[i] == '/' && i > 0)
336     {
337       entry->path [i] = '\0';
338       --i;
339     }
340
341   add_single_dir (entry, 1);
342 }
343
344
345 static int
346 chroot_stat (const char *real_path, const char *path, struct stat64 *st)
347 {
348   int ret;
349   char *canon_path;
350
351   if (!opt_chroot)
352     return stat64 (real_path, st);
353
354   ret = lstat64 (real_path, st);
355   if (ret || !S_ISLNK (st->st_mode))
356     return ret;
357
358   canon_path = chroot_canon (opt_chroot, path);
359   if (canon_path == NULL)
360     return -1;
361
362   ret = stat64 (canon_path, st);
363   free (canon_path);
364   return ret;
365 }
366
367 /* Create a symbolic link from soname to libname in directory path.  */
368 static void
369 create_links (const char *real_path, const char *path, const char *libname,
370               const char *soname)
371 {
372   char *full_libname, *full_soname;
373   char *real_full_libname, *real_full_soname;
374   struct stat64 stat_lib, stat_so, lstat_so;
375   int do_link = 1;
376   int do_remove = 1;
377   /* XXX: The logics in this function should be simplified.  */
378
379   /* Get complete path.  */
380   full_libname = alloca (strlen (path) + strlen (libname) + 2);
381   full_soname = alloca (strlen (path) + strlen (soname) + 2);
382   sprintf (full_libname, "%s/%s", path, libname);
383   sprintf (full_soname, "%s/%s", path, soname);
384   if (opt_chroot)
385     {
386       real_full_libname = alloca (strlen (real_path) + strlen (libname) + 2);
387       real_full_soname = alloca (strlen (real_path) + strlen (soname) + 2);
388       sprintf (real_full_libname, "%s/%s", real_path, libname);
389       sprintf (real_full_soname, "%s/%s", real_path, soname);
390     }
391   else
392     {
393       real_full_libname = full_libname;
394       real_full_soname = full_soname;
395     }
396
397   /* Does soname already exist and point to the right library?  */
398   if (chroot_stat (real_full_soname, full_soname, &stat_so) == 0)
399     {
400       if (chroot_stat (real_full_libname, full_libname, &stat_lib))
401         {
402           error (0, 0, _("Can't stat %s\n"), full_libname);
403           return;
404         }
405       if (stat_lib.st_dev == stat_so.st_dev
406           && stat_lib.st_ino == stat_so.st_ino)
407         /* Link is already correct.  */
408         do_link = 0;
409       else if (lstat64 (full_soname, &lstat_so) == 0
410                && !S_ISLNK (lstat_so.st_mode))
411         {
412           error (0, 0, _("%s is not a symbolic link\n"), full_soname);
413           do_link = 0;
414           do_remove = 0;
415         }
416     }
417   else if (lstat64 (real_full_soname, &lstat_so) != 0
418            || !S_ISLNK (lstat_so.st_mode))
419     /* Unless it is a stale symlink, there is no need to remove.  */
420     do_remove = 0;
421
422   if (opt_verbose)
423     printf ("\t%s -> %s", soname, libname);
424
425   if (do_link && opt_link)
426     {
427       /* Remove old link.  */
428       if (do_remove)
429         if (unlink (real_full_soname))
430           {
431             error (0, 0, _("Can't unlink %s"), full_soname);
432             do_link = 0;
433           }
434       /* Create symbolic link.  */
435       if (do_link && symlink (libname, real_full_soname))
436         {
437           error (0, 0, _("Can't link %s to %s"), full_soname, libname);
438           do_link = 0;
439         }
440       if (opt_verbose)
441         {
442           if (do_link)
443             fputs (_(" (changed)\n"), stdout);
444           else
445             fputs (_(" (SKIPPED)\n"), stdout);
446         }
447     }
448   else if (opt_verbose)
449     fputs ("\n", stdout);
450 }
451
452 /* Manually link the given library.  */
453 static void
454 manual_link (char *library)
455 {
456   char *path;
457   char *real_path;
458   char *real_library;
459   char *libname;
460   char *soname;
461   struct stat64 stat_buf;
462   int flag;
463
464   /* Prepare arguments for create_links call.  Split library name in
465      directory and filename first.  Since path is allocated, we've got
466      to be careful to free at the end.  */
467   path = xstrdup (library);
468   libname = strrchr (path, '/');
469
470   if (libname)
471     {
472       /* Successfully split names.  Check if path is just "/" to avoid
473          an empty path.  */
474       if (libname == path)
475         {
476           libname = library + 1;
477           path = xrealloc (path, 2);
478           strcpy (path, "/");
479         }
480       else
481         {
482           *libname = '\0';
483           ++libname;
484         }
485     }
486   else
487     {
488       /* There's no path, construct one. */
489       libname = library;
490       path = xrealloc (path, 2);
491       strcpy (path, ".");
492     }
493
494   if (opt_chroot)
495     {
496       real_path = chroot_canon (opt_chroot, path);
497       if (real_path == NULL)
498         {
499           error (0, errno, _("Can't find %s"), path);
500           free (path);
501           return;
502         }
503       real_library = alloca (strlen (real_path) + strlen (libname) + 2);
504       sprintf (real_library, "%s/%s", real_path, libname);
505     }
506   else
507     {
508       real_path = path;
509       real_library = library;
510     }
511
512   /* Do some sanity checks first.  */
513   if (lstat64 (real_library, &stat_buf))
514     {
515       error (0, errno, _("Can't lstat %s"), library);
516       free (path);
517       return;
518     }
519   /* We don't want links here!  */
520   else if (!S_ISREG (stat_buf.st_mode))
521     {
522       error (0, 0, _("Ignored file %s since it is not a regular file."),
523              library);
524       free (path);
525       return;
526     }
527   if (process_file (real_library, library, libname, &flag, &soname, 0))
528     {
529       error (0, 0, _("No link created since soname could not be found for %s"),
530              library);
531       free (path);
532       return;
533     }
534   create_links (real_path, path, libname, soname);
535   free (soname);
536   free (path);
537 }
538
539
540 /* Read a whole directory and search for libraries.
541    The purpose is two-fold:
542    - search for libraries which will be added to the cache
543    - create symbolic links to the soname for each library
544
545    This has to be done separatly for each directory.
546
547    To keep track of which libraries to add to the cache and which
548    links to create, we save a list of all libraries.
549
550    The algorithm is basically:
551    for all libraries in the directory do
552      get soname of library
553      if soname is already in list
554        if new library is newer, replace entry
555        otherwise ignore this library
556      otherwise add library to list
557
558    For example, if the two libraries libxy.so.1.1 and libxy.so.1.2
559    exist and both have the same soname, e.g. libxy.so, a symbolic link
560    is created from libxy.so.1.2 (the newer one) to libxy.so.
561    libxy.so.1.2 and libxy.so are added to the cache - but not
562    libxy.so.1.1.  */
563
564 /* Information for one library.  */
565 struct dlib_entry
566 {
567   char *name;
568   char *soname;
569   int flag;
570   int is_link;
571   struct dlib_entry *next;
572 };
573
574
575 static void
576 search_dir (const struct dir_entry *entry)
577 {
578   DIR *dir;
579   struct dirent *direntry;
580   char *file_name, *dir_name, *real_file_name, *real_name;
581   int file_name_len, real_file_name_len, len;
582   char *soname;
583   struct dlib_entry *dlibs;
584   struct dlib_entry *dlib_ptr;
585   struct stat64 stat_buf;
586   int is_link;
587   uint64_t hwcap = path_hwcap (entry->path);
588
589   file_name_len = PATH_MAX;
590   file_name = alloca (file_name_len);
591
592   dlibs = NULL;
593
594   if (opt_verbose)
595     {
596       if (hwcap != 0)
597         printf ("%s: (hwcap: 0x%" PRIx64 ")\n", entry->path, hwcap);
598       else
599         printf ("%s:\n", entry->path);
600     }
601
602   if (opt_chroot)
603     {
604       dir_name = chroot_canon (opt_chroot, entry->path);
605       real_file_name_len = PATH_MAX;
606       real_file_name = alloca (real_file_name_len);
607     }
608   else
609     {
610       dir_name = entry->path;
611       real_file_name_len = 0;
612       real_file_name = file_name;
613     }
614
615   if (dir_name == NULL || (dir = opendir (dir_name)) == NULL)
616     {
617       if (opt_verbose)
618         error (0, errno, _("Can't open directory %s"), entry->path);
619       if (opt_chroot && dir_name)
620         free (dir_name);
621       return;
622     }
623
624   while ((direntry = readdir (dir)) != NULL)
625     {
626       int flag;
627 #ifdef _DIRENT_HAVE_D_TYPE
628       /* We only look at links and regular files.  */
629       if (direntry->d_type != DT_UNKNOWN
630           && direntry->d_type != DT_LNK
631           && direntry->d_type != DT_REG
632           && direntry->d_type != DT_DIR)
633         continue;
634 #endif /* _DIRENT_HAVE_D_TYPE  */
635       /* Does this file look like a shared library or is it a hwcap
636          subdirectory?  The dynamic linker is also considered as
637          shared library.  */
638       if (((strncmp (direntry->d_name, "lib", 3) != 0
639             && strncmp (direntry->d_name, "ld-", 3) != 0)
640            || strstr (direntry->d_name, ".so") == NULL)
641           && !is_hwcap_platform (direntry->d_name))
642         continue;
643       len = strlen (entry->path) + strlen (direntry->d_name);
644       if (len > file_name_len)
645         {
646           file_name_len = len + 1;
647           file_name = alloca (file_name_len);
648           if (!opt_chroot)
649             real_file_name = file_name;
650         }
651       sprintf (file_name, "%s/%s", entry->path, direntry->d_name);
652       if (opt_chroot)
653         {
654           len = strlen (dir_name) + strlen (direntry->d_name);
655           if (len > real_file_name_len)
656             {
657               real_file_name_len = len + 1;
658               real_file_name = alloca (real_file_name_len);
659             }
660           sprintf (real_file_name, "%s/%s", dir_name, direntry->d_name);
661         }
662 #ifdef _DIRENT_HAVE_D_TYPE
663       if (direntry->d_type != DT_UNKNOWN)
664         stat_buf.st_mode = DTTOIF (direntry->d_type);
665       else
666 #endif
667         if (lstat64 (real_file_name, &stat_buf))
668           {
669             error (0, errno, _("Can't lstat %s"), file_name);
670             continue;
671           }
672
673       if (S_ISDIR (stat_buf.st_mode) && is_hwcap_platform (direntry->d_name))
674         {
675           /* Handle subdirectory later.  */
676           struct dir_entry *new_entry;
677
678           new_entry = xmalloc (sizeof (struct dir_entry));
679           new_entry->path = xstrdup (file_name);
680           new_entry->flag = entry->flag;
681           new_entry->next = NULL;
682           add_single_dir (new_entry, 0);
683           continue;
684         }
685       else if (!S_ISREG (stat_buf.st_mode) && !S_ISLNK (stat_buf.st_mode))
686         continue;
687
688       is_link = S_ISLNK (stat_buf.st_mode);
689       if (opt_chroot && is_link)
690         {
691           real_name = chroot_canon (opt_chroot, file_name);
692           if (real_name == NULL)
693             {
694               if (strstr (file_name, ".so") == NULL)
695                 error (0, 0, _("Input file %s not found.\n"), file_name);
696               continue;
697             }
698         }
699       else
700         real_name = real_file_name;
701
702       if (process_file (real_name, file_name, direntry->d_name, &flag,
703                         &soname, is_link))
704         {
705           if (real_name != real_file_name)
706             free (real_name);
707           continue;
708         }
709
710       if (real_name != real_file_name)
711         free (real_name);
712
713       /* Links will just point to itself.  */
714       if (is_link)
715         {
716           free (soname);
717           soname = xstrdup (direntry->d_name);
718         }
719
720       if (flag == FLAG_ELF
721           && (entry->flag == FLAG_ELF_LIBC5
722               || entry->flag == FLAG_ELF_LIBC6))
723         flag = entry->flag;
724       /* Some sanity checks to print warnings.  */
725       if (opt_verbose)
726         {
727           if (flag == FLAG_ELF_LIBC5 && entry->flag != FLAG_ELF_LIBC5
728               && entry->flag != FLAG_ANY)
729             error (0, 0, _("libc5 library %s in wrong directory"), file_name);
730           if (flag == FLAG_ELF_LIBC6 && entry->flag != FLAG_ELF_LIBC6
731               && entry->flag != FLAG_ANY)
732             error (0, 0, _("libc6 library %s in wrong directory"), file_name);
733           if (flag == FLAG_LIBC4 && entry->flag != FLAG_LIBC4
734               && entry->flag != FLAG_ANY)
735             error (0, 0, _("libc4 library %s in wrong directory"), file_name);
736         }
737
738       /* Add library to list.  */
739       for (dlib_ptr = dlibs; dlib_ptr != NULL; dlib_ptr = dlib_ptr->next)
740         {
741           /* Is soname already in list?  */
742           if (strcmp (dlib_ptr->soname, soname) == 0)
743             {
744               /* Prefer a file to a link, otherwise check which one
745                  is newer.  */
746               if ((!is_link && dlib_ptr->is_link)
747                   || (is_link == dlib_ptr->is_link
748                       && _dl_cache_libcmp (dlib_ptr->name, direntry->d_name) < 0))
749                 {
750                   /* It's newer - add it.  */
751                   /* Flag should be the same - sanity check.  */
752                   if (dlib_ptr->flag != flag)
753                     {
754                       if (dlib_ptr->flag == FLAG_ELF
755                           && (flag == FLAG_ELF_LIBC5 || flag == FLAG_ELF_LIBC6))
756                         dlib_ptr->flag = flag;
757                       else if ((dlib_ptr->flag == FLAG_ELF_LIBC5
758                                 || dlib_ptr->flag == FLAG_ELF_LIBC6)
759                                && flag == FLAG_ELF)
760                         dlib_ptr->flag = flag;
761                       else
762                         error (0, 0, _("libraries %s and %s in directory %s have same soname but different type."),
763                                dlib_ptr->name, direntry->d_name, entry->path);
764                     }
765                   free (dlib_ptr->name);
766                   dlib_ptr->name = xstrdup (direntry->d_name);
767                   dlib_ptr->is_link = is_link;
768                 }
769               /* Don't add this library, abort loop.  */
770               /* Also free soname, since it's dynamically allocated.  */
771               free (soname);
772               break;
773             }
774         }
775       /* Add the library if it's not already in.  */
776       if (dlib_ptr == NULL)
777         {
778           dlib_ptr = (struct dlib_entry *)xmalloc (sizeof (struct dlib_entry));
779           dlib_ptr->name = xstrdup (direntry->d_name);
780           dlib_ptr->flag = flag;
781           dlib_ptr->soname = soname;
782           dlib_ptr->is_link = is_link;
783           /* Add at head of list.  */
784           dlib_ptr->next = dlibs;
785           dlibs = dlib_ptr;
786         }
787     }
788
789   closedir (dir);
790
791   /* Now dlibs contains a list of all libs - add those to the cache
792      and created all symbolic links.  */
793   for (dlib_ptr = dlibs; dlib_ptr != NULL; dlib_ptr = dlib_ptr->next)
794     {
795       /* Don't create links to links.  */
796       if (dlib_ptr->is_link == 0)
797         create_links (dir_name, entry->path, dlib_ptr->name,
798                       dlib_ptr->soname);
799       if (opt_build_cache)
800         add_to_cache (entry->path, dlib_ptr->soname, dlib_ptr->flag, hwcap);
801     }
802
803   /* Free all resources.  */
804   while (dlibs)
805     {
806       dlib_ptr = dlibs;
807       free (dlib_ptr->soname);
808       free (dlib_ptr->name);
809       dlibs = dlibs->next;
810       free (dlib_ptr);
811     }
812
813   if (opt_chroot && dir_name)
814     free (dir_name);
815 }
816
817 /* Search through all libraries.  */
818 static void
819 search_dirs (void)
820 {
821   struct dir_entry *entry;
822
823   for (entry = dir_entries; entry != NULL; entry = entry->next)
824     search_dir (entry);
825
826   /* Free all allocated memory.  */
827   while (dir_entries)
828     {
829       entry = dir_entries;
830       dir_entries = dir_entries->next;
831       free (entry->path);
832       free (entry);
833     }
834 }
835
836
837 /* Parse configuration file.  */
838 static void
839 parse_conf (const char *filename)
840 {
841   FILE *file = NULL;
842   char *line = NULL;
843   const char *canon;
844   size_t len = 0;
845
846   if (opt_chroot)
847     {
848       canon = chroot_canon (opt_chroot, filename);
849       if (canon)
850         file = fopen (canon, "r");
851       else
852         canon = filename;
853     }
854   else
855     {
856       canon = filename;
857       file = fopen (filename, "r");
858     }
859
860   if (file == NULL)
861     {
862       error (0, errno, _("Can't open configuration file %s"), canon);
863       if (canon != filename)
864         free ((char *) canon);
865       return;
866     }
867
868   if (canon != filename)
869     free ((char *) canon);
870
871   do
872     {
873       ssize_t n = getline (&line, &len, file);
874       if (n < 0)
875         break;
876
877       if (line[n - 1] == '\n')
878         line[n - 1] = '\0';
879
880       /* Because the file format does not know any form of quoting we
881          can search forward for the next '#' character and if found
882          make it terminating the line.  */
883       *strchrnul (line, '#') = '\0';
884
885       /* If the line is blank it is ignored.  */
886       if (line[0] == '\0')
887         continue;
888
889       add_dir (line);
890     } while (!feof (file));
891
892   /* Free buffer and close file.  */
893   free (line);
894   fclose (file);
895 }
896
897
898 int
899 main (int argc, char **argv)
900 {
901   int remaining;
902
903   /* Parse and process arguments.  */
904   argp_parse (&argp, argc, argv, 0, &remaining, NULL);
905
906   /* Remaining arguments are additional libraries if opt_manual_link
907      is not set.  */
908   if (remaining != argc && !opt_manual_link)
909     {
910       int i;
911       for (i = remaining; i < argc; ++i)
912         add_dir (argv [i]);
913     }
914
915   if (opt_chroot)
916     {
917       /* Normalize the path a bit, we might need it for printing later.  */
918       char *endp = strchr (opt_chroot, '\0');
919       while (endp > opt_chroot && endp[-1] == '/')
920         --endp;
921       *endp = '\0';
922       if (endp == opt_chroot)
923         opt_chroot = NULL;
924
925       if (opt_chroot)
926         {
927           /* It is faster to use chroot if we can.  */
928           if (!chroot (opt_chroot))
929             {
930               if (chdir ("/"))
931                 error (EXIT_FAILURE, errno, _("Can't chdir to /"));
932               opt_chroot = NULL;
933             }
934         }
935     }
936
937   if (cache_file == NULL)
938     {
939       cache_file = alloca (strlen (LD_SO_CACHE) + 1);
940       strcpy (cache_file, LD_SO_CACHE);
941     }
942
943   if (config_file == NULL)
944     config_file = LD_SO_CONF;
945
946   if (opt_print_cache)
947     {
948       if (opt_chroot)
949         {
950           char *p = chroot_canon (opt_chroot, cache_file);
951           if (p == NULL)
952             error (EXIT_FAILURE, errno, _("Can't open cache file %s\n"),
953                    cache_file);
954           cache_file = p;
955         }
956       print_cache (cache_file);
957       if (opt_chroot)
958         free (cache_file);
959       exit (0);
960     }
961
962   if (opt_chroot)
963     {
964       /* Canonicalize the directory name of cache_file, not cache_file,
965          because we'll rename a temporary cache file to it.  */
966       char *p = strrchr (cache_file, '/');
967       char *canon = chroot_canon (opt_chroot,
968                                   p ? (*p = '\0', cache_file) : "/");
969
970       if (canon == NULL)
971         {
972           error (EXIT_FAILURE, errno,
973                  _("Can't open cache file directory %s\n"),
974                  p ? cache_file : "/");
975         }
976
977       if (p)
978         ++p;
979       else
980         p = cache_file;
981
982       cache_file = alloca (strlen (canon) + strlen (p) + 2);
983       sprintf (cache_file, "%s/%s", canon, p);
984       free (canon);
985     }
986
987   if (opt_manual_link)
988     {
989       /* Link all given libraries manually.  */
990       int i;
991
992       for (i = remaining; i < argc; ++i)
993         manual_link (argv [i]);
994
995       exit (0);
996     }
997
998
999   if (opt_build_cache)
1000     init_cache ();
1001
1002   if (!opt_only_cline)
1003     {
1004       /* Always add the standard search paths.  */
1005       add_dir (SLIBDIR);
1006       if (strcmp (SLIBDIR, LIBDIR))
1007         add_dir (LIBDIR);
1008
1009       parse_conf (config_file);
1010     }
1011
1012   search_dirs ();
1013
1014   if (opt_build_cache)
1015     save_cache (cache_file);
1016
1017   return 0;
1018 }