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