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