Update.
[platform/upstream/glibc.git] / elf / ldconfig.c
1 /* Copyright (C) 1999 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 <argp.h>
21 #include <dirent.h>
22 #include <error.h>
23 #include <errno.h>
24 #include <libintl.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <sys/fcntl.h>
30 #include <sys/mman.h>
31 #include <sys/stat.h>
32 #include <sys/types.h>
33
34 #include "ldconfig.h"
35
36 #ifndef LD_SO_CACHE
37 # define LD_SO_CACHE "/etc/ld.so.cache"
38 #endif
39
40 #ifndef LD_SO_CONF
41 # define LD_SO_CONF "/etc/ld.so.conf"
42 #endif
43
44 /* Get libc version number.  */
45 #include <version.h>
46
47 #define PACKAGE _libc_intl_domainname
48
49 struct lib_entry
50   {
51     int flags;
52     char *lib;
53     char *path;
54   };
55
56 static const struct
57 {
58   const char *name;
59   int flag;
60 } lib_types [] =
61 {
62   {"libc4", FLAG_LIBC4},
63   {"libc5", FLAG_ELF_LIBC5},
64   {"libc6", FLAG_ELF_LIBC6},
65   {"glibc2", FLAG_ELF_LIBC6}
66 };  
67
68
69 /* List of directories to handle.  */
70 struct dir_entry
71 {
72   char *path;
73   int flag;
74   struct dir_entry *next;
75 };
76
77 /* The list is unsorted, contains no duplicates.  Entries are added at
78    the end.  */
79 static struct dir_entry *dir_entries;
80
81 /* Flags for different options.  */
82 /* Print Cache.  */
83 static int opt_print_cache = 0;
84
85 /* Be verbose.  */
86 int opt_verbose = 0;
87
88 /* Build cache.  */
89 static int opt_build_cache = 1;
90
91 /* Generate links.  */
92 static int opt_link = 1;
93
94 /* Only process directories specified on the command line.  */
95 static int opt_only_cline = 0;
96
97 /* Path to root for chroot.  */
98 static char *opt_chroot;
99
100 /* Manually link given shared libraries.  */
101 static int opt_manual_link = 0;
102
103 /* Cache file to use.  */
104 static const char *cache_file;
105
106 /* Configuration file.  */
107 static const char *config_file;
108
109 /* Name and version of program.  */
110 static void print_version (FILE *stream, struct argp_state *state);
111 void (*argp_program_version_hook) (FILE *, struct argp_state *)
112      = print_version;
113
114 /* Definitions of arguments for argp functions.  */
115 static const struct argp_option options[] =
116 {
117   { "print-cache", 'p', NULL, 0, N_("Print cache"), 0},
118   { "verbose", 'v', NULL, 0, N_("Generate verbose messages"), 0},
119   { NULL, 'N', NULL, 0, N_("Don't build cache"), 0},
120   { NULL, 'X', NULL, 0, N_("Don't generate links"), 0},
121   { NULL, 'r', "ROOT", 0, N_("Change to and use ROOT as root directory"), 0},
122   { NULL, 'C', "CACHE", 0, N_("Use CACHE as cache file"), 0},
123   { NULL, 'f', "CONF", 0, N_("Use CONF as configuration file"), 0},
124   { NULL, 'n', NULL, 0, N_("Only process directories specified on the command line.  Don't build cache."), 0},
125   { NULL, 'l', NULL, 0, N_("Manually link individual libraries."), 0},
126   { NULL, 0, NULL, 0, NULL, 0 }
127 };
128
129 /* Short description of program.  */
130 static const char doc[] = N_("Configure Dynamic Linker Run Time Bindings.");
131
132 /* Prototype for option handler.  */
133 static error_t parse_opt (int key, char *arg, struct argp_state *state);
134
135 /* Data structure to communicate with argp functions.  */
136 static struct argp argp =
137 {
138   options, parse_opt, NULL, doc, NULL, NULL, NULL
139 };
140
141
142
143 /* Handle program arguments.  */
144 static error_t
145 parse_opt (int key, char *arg, struct argp_state *state)
146 {
147   switch (key)
148     {
149     case 'C':
150       cache_file = arg;
151       break;
152     case 'f':
153       config_file = arg;
154       break;
155     case 'l':
156       opt_manual_link = 1;
157       break;
158     case 'N':
159       opt_build_cache = 0;
160       break;
161     case 'n':
162       opt_build_cache = 0;
163       opt_only_cline = 1;
164       break;
165     case 'p':
166       opt_print_cache = 1;
167       break;
168     case 'r':
169       opt_chroot = arg;
170       break;
171     case 'v':
172       opt_verbose = 1;
173       break;
174     case 'X':
175       opt_link = 0;
176       break;
177     default:
178       return ARGP_ERR_UNKNOWN;
179     }
180
181   return 0;
182 }
183
184 /* Print the version information.  */
185 static void
186 print_version (FILE *stream, struct argp_state *state)
187 {
188   fprintf (stream, "ldconfig (GNU %s) %s\n", PACKAGE, VERSION);
189   fprintf (stream, gettext ("\
190 Copyright (C) %s Free Software Foundation, Inc.\n\
191 This is free software; see the source for copying conditions.  There is NO\n\
192 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
193 "), "1999");
194   fprintf (stream, gettext ("Written by %s.\n"),
195            "Andreas Jaeger");
196 }
197
198 /* Add one directory to the list of directories to process.  */
199 static void
200 add_dir (const char *line)
201 {
202   char *equal_sign;
203   struct dir_entry *entry, *ptr, *prev;
204   unsigned int i;
205   
206   entry = xmalloc (sizeof (struct dir_entry));
207   entry->next = NULL;
208   
209   /* Search for an '=' sign.  */
210   entry->path = xstrdup (line);
211   equal_sign = strchr (entry->path, '=');
212   if (equal_sign)
213     {
214       *equal_sign = '\0';
215       ++equal_sign;
216       entry->flag = FLAG_ANY;
217       for (i = 0; i < sizeof (lib_types) / sizeof (lib_types [0]); ++i)
218         if (strcmp (equal_sign, lib_types[i].name) == 0)
219           {
220             entry->flag = lib_types[i].flag;
221             break;
222           }
223       if (entry->flag == FLAG_ANY)
224         error (0, 0, _("%s is not a known library type"), equal_sign);
225     }
226   else
227     {
228       entry->flag = FLAG_ANY;
229     }
230
231   /* Canonify path: for now only remove trailing slashes.  */
232   i = strlen (entry->path) - 1;
233   while (entry->path[i] == '/' && i > 0)
234     {
235       entry->path [i] = '\0';
236       --i;
237     }
238   
239   ptr = dir_entries;
240   prev = ptr;
241   while (ptr != NULL)
242     {
243       /* Check for duplicates.  */
244       if (strcmp (ptr->path, entry->path) == 0)
245         {
246           if (opt_verbose)
247             error (0, 0, _("Path `%s' given more than once"), entry->path);
248           /* Use the newer information.  */
249           ptr->flag = entry->flag;
250           free (entry);
251           break;
252         }
253       prev = ptr;
254       ptr = ptr->next;
255     }
256   /* Is this the first entry?  */
257   if (ptr == NULL && dir_entries == NULL)
258     dir_entries = entry;
259   else if (ptr == NULL)
260     prev->next = entry;
261 }
262
263
264 /* Create a symbolic link from soname to libname in directory path.  */
265 static void
266 create_links (const char *path, const char *libname, const char *soname)
267 {
268   char full_libname [PATH_MAX], full_soname [PATH_MAX];
269   struct stat stat_lib, stat_so, lstat_so;
270   int do_link = 1;
271   int do_remove = 1;
272   /* XXX: The logics in this function should be simplified.  */
273   
274   /* Get complete path.  */
275   snprintf (full_libname, sizeof full_libname, "%s/%s", path, libname);
276   snprintf (full_soname, sizeof full_soname, "%s/%s", path, soname);
277
278   /* Does soname already exist and point to the right library?  */
279   if (stat (full_soname, &stat_so) == 0)
280     {
281       if (stat (full_libname, &stat_lib))
282         {
283           error (0, 0, _("Can't stat %s\n"), full_libname);
284           return;
285         }
286       if (stat_lib.st_dev == stat_so.st_dev
287           && stat_lib.st_ino == stat_so.st_ino)
288         /* Link is already correct.  */
289         do_link = 0;
290       else if (lstat (full_soname, &lstat_so) == 0
291                && !S_ISLNK (lstat_so.st_mode))
292         {
293           error (0, 0, _("%s is not a symbolic link\n"), full_soname);
294           do_link = 0;
295           do_remove = 0;
296         }
297     }
298   else if (lstat (full_soname, &lstat_so) != 0
299            || !S_ISLNK (lstat_so.st_mode))
300     /* Unless it is a stale symlink, there is no need to remove.  */
301     do_remove = 0;
302
303   if (opt_verbose)
304     printf ("\t%s -> %s", soname, libname);
305
306   if (do_link && opt_link)
307     {
308       /* Remove old link.  */
309       if (do_remove)
310         if (unlink (full_soname))
311           {
312             error (0, 0, _("Can't unlink %s"), full_soname);
313             do_link = 0;
314           }
315       /* Create symbolic link.  */
316       if (do_link && symlink (libname, full_soname))
317         {
318           error (0, 0, _("Can't link %s to %s"), full_soname, libname);
319           do_link = 0;
320         }
321       if (opt_verbose)
322         {
323           if (do_link)
324             fputs (_(" (changed)\n"), stdout);
325           else
326             fputs (_(" (SKIPPED)\n"), stdout);
327         }
328     }
329   else if (opt_verbose)
330     fputs ("\n", stdout);
331 }
332
333 /* Manually link the given library.  */
334 static void
335 manual_link (char *library)
336 {
337   char *path;
338   char *libname;
339   char *soname;
340   struct stat stat_buf;
341   int flag;
342
343   /* Prepare arguments for create_links call.  Split library name in
344      directory and filename first.  Since path is allocated, we've got
345      to be careful to free at the end.  */
346   path = xstrdup (library);
347   libname = strrchr (path, '/');
348
349   if (libname)
350     {
351       /* Successfully split names.  Check if path is just "/" to avoid
352          an empty path.  */
353       if (libname == path)
354         {
355           libname = library + 1;
356           path = xrealloc (path, 2);
357           strcpy (path, "/");
358         }
359       else
360         {
361           *libname = '\0';
362           ++libname;
363         }
364     }
365   else
366     {
367       /* There's no path, construct one. */
368       libname = library;
369       path = xrealloc (path, 2);
370       strcpy (path, ".");
371     }
372
373   /* Do some sanity checks first.  */
374   if (lstat (library, &stat_buf))
375     {
376       error (0, errno, _("Can't lstat %s"), library);
377       free (path);
378       return;
379     }
380   /* We don't want links here!  */
381   else if (!S_ISREG (stat_buf.st_mode))
382     {
383       error (0, 0, _("Ignored file %s since it is not a regular file."),
384              library);
385       free (path);
386       return;
387     }
388   libname = basename (library);
389   if (process_file (library, libname, &flag, &soname, 0))
390     {
391       error (0, 0, _("No link created since soname could not be found for %s"),
392              library);
393       free (path);
394       return;
395     }
396   create_links (path, libname, soname);
397   free (soname);
398   free (path);
399 }
400
401
402 /* Read a whole directory and search for libraries.
403    The purpose is two-fold:
404    - search for libraries which will be added to the cache
405    - create symbolic links to the soname for each library
406
407    This has to be done separatly for each directory.
408    
409    To keep track of which libraries to add to the cache and which
410    links to create, we save a list of all libraries.
411
412    The algorithm is basically:
413    for all libraries in the directory do
414      get soname of library
415      if soname is already in list
416        if new library is newer, replace entry
417        otherwise ignore this library
418      otherwise add library to list
419    
420    For example, if the two libraries libxy.so.1.1 and libxy.so.1.2
421    exist and both have the same soname, e.g. libxy.so, a symbolic link
422    is created from libxy.so.1.2 (the newer one) to libxy.so.
423    libxy.so.1.2 and libxy.so are added to the cache - but not
424    libxy.so.1.1.  */
425
426 /* Information for one library.  */
427 struct dlib_entry 
428 {
429   char *name;
430   char *soname;
431   int flag;
432   int is_link;
433   struct dlib_entry *next;
434 };
435
436
437 static void
438 search_dir (const struct dir_entry *entry)
439 {
440   DIR *dir;
441   struct dirent *direntry;
442   char buf [PATH_MAX];
443   char *soname;
444   struct dlib_entry *dlibs;
445   struct dlib_entry *dlib_ptr;
446   int nchars;
447   struct stat stat_buf;
448   int is_link;
449   
450   dlibs = NULL;
451
452   if (opt_verbose)
453     printf ("%s:\n", entry->path);
454   
455   dir = opendir (entry->path);
456   if (dir == NULL)
457     {
458       if (opt_verbose)
459         error (0, errno, _("Can't open directory %s"), entry->path);
460       return;
461     }
462   
463
464   while ((direntry = readdir (dir)) != NULL)
465     {
466       int flag;
467 #ifdef _DIRENT_HAVE_D_TYPE
468       /* We only look at links and regular files.  */
469       if (direntry->d_type != DT_UNKNOWN
470           && direntry->d_type != DT_LNK
471           && direntry->d_type != DT_REG)
472         continue;
473 #endif /* _DIRENT_HAVE_D_TYPE  */
474
475       /* Does this file look like a shared library?  The dynamic
476          linker is also considered as shared library.  */
477       if ((strncmp (direntry->d_name, "lib", 3) != 0
478            && strncmp (direntry->d_name, "ld-", 3) != 0)
479           || strstr (direntry->d_name, ".so") == NULL)
480         continue;
481       nchars = snprintf (buf, sizeof (buf), "%s/%s", entry->path,
482                          direntry->d_name);
483       /* Check for overflow.  */
484       if (nchars >= (int) sizeof (buf))
485         {
486           error (0, 0, _("buffer for snprintf too small for %s/%s--file is ignored\n"),
487                  entry->path, direntry->d_name);
488           continue;
489         }
490       if (lstat (buf, &stat_buf))
491         {
492           error (0, errno, _("Can't lstat %s"), buf);
493           continue;
494         }
495       else if (!S_ISREG (stat_buf.st_mode) && !S_ISLNK (stat_buf.st_mode))
496         continue;
497
498       is_link = S_ISLNK (stat_buf.st_mode);
499
500       if (process_file (buf, direntry->d_name, &flag, &soname, is_link))
501         continue;
502
503       /* Links will just point to itself.  */
504       if (is_link)
505         {
506           free (soname);
507           soname = xstrdup (direntry->d_name);
508         }
509       
510       if (flag == FLAG_ELF
511           && (entry->flag == FLAG_ELF_LIBC5
512               || entry->flag == FLAG_ELF_LIBC6))
513         flag = entry->flag;
514       /* Some sanity checks to print warnings.  */
515       if (opt_verbose)
516         {
517           if (flag == FLAG_ELF_LIBC5 && entry->flag != FLAG_ELF_LIBC5
518               && entry->flag != FLAG_ANY)
519             error (0, 0, _("libc5 library %s in wrong directory"), buf);
520           if (flag == FLAG_ELF_LIBC6 && entry->flag != FLAG_ELF_LIBC6
521               && entry->flag != FLAG_ANY)
522             error (0, 0, _("libc6 library %s in wrong directory"), buf);
523           if (flag == FLAG_LIBC4 && entry->flag != FLAG_LIBC4
524               && entry->flag != FLAG_ANY)
525             error (0, 0, _("libc4 library %s in wrong directory"), buf);
526         }
527       
528       /* Add library to list.  */
529       for (dlib_ptr = dlibs; dlib_ptr != NULL; dlib_ptr = dlib_ptr->next)
530         {
531           /* Is soname already in list?  */
532           if (strcmp (dlib_ptr->soname, soname) == 0)
533             {
534               /* Prefer a file to a link, otherwise check which one
535                  is newer.  */
536               if ((!is_link && dlib_ptr->is_link)
537                   || (is_link == dlib_ptr->is_link
538                       && cache_libcmp (dlib_ptr->name, direntry->d_name) < 0))
539                 {
540                   /* It's newer - add it.  */
541                   /* Flag should be the same - sanity check.  */
542                   if (dlib_ptr->flag != flag)
543                     {
544                       if (dlib_ptr->flag == FLAG_ELF
545                           && (flag == FLAG_ELF_LIBC5 || flag == FLAG_ELF_LIBC6))
546                         dlib_ptr->flag = flag;
547                       else if ((dlib_ptr->flag == FLAG_ELF_LIBC5
548                                 || dlib_ptr->flag == FLAG_ELF_LIBC6)
549                                && flag == FLAG_ELF)
550                         dlib_ptr->flag = flag;
551                       else
552                         error (0, 0, _("libraries %s and %s in directory %s have same soname but different type."),
553                                dlib_ptr->name, direntry->d_name, entry->path);
554                     }
555                   free (dlib_ptr->name);
556                   dlib_ptr->name = xstrdup (direntry->d_name);
557                   dlib_ptr->is_link = is_link;
558                 }
559               /* Don't add this library, abort loop.  */
560               /* Also free soname, since it's dynamically allocated.  */
561               free (soname);
562               break;
563             }
564         }
565       /* Add the library if it's not already in.  */
566       if (dlib_ptr == NULL)
567         {
568           dlib_ptr = (struct dlib_entry *)xmalloc (sizeof (struct dlib_entry));
569           dlib_ptr->name = xstrdup (direntry->d_name);
570           dlib_ptr->flag = flag;
571           dlib_ptr->soname = soname;
572           dlib_ptr->is_link = is_link;
573           /* Add at head of list.  */
574           dlib_ptr->next = dlibs;
575           dlibs = dlib_ptr;
576         }
577     }
578
579   closedir (dir);
580
581   /* Now dlibs contains a list of all libs - add those to the cache
582      and created all symbolic links.  */
583   for (dlib_ptr = dlibs; dlib_ptr != NULL; dlib_ptr = dlib_ptr->next)
584     {
585       /* Don't create links to links.  */
586       if (dlib_ptr->is_link == 0)
587         create_links (entry->path, dlib_ptr->name, dlib_ptr->soname);
588       if (opt_build_cache)
589         add_to_cache (entry->path, dlib_ptr->soname, dlib_ptr->flag);
590     }
591
592   /* Free all resources.  */
593   while (dlibs) 
594     {
595       dlib_ptr = dlibs;
596       free (dlib_ptr->soname);
597       free (dlib_ptr->name);
598       dlibs = dlibs->next;
599       free (dlib_ptr);
600     }
601 }
602
603 /* Search through all libraries.  */
604 static void
605 search_dirs (void)
606 {
607   struct dir_entry *entry;
608
609   for (entry = dir_entries; entry != NULL; entry = entry->next)
610     search_dir (entry);
611
612   /* Free all allocated memory.  */
613   while (dir_entries)
614     {
615       entry = dir_entries;
616       dir_entries = dir_entries->next;
617       free (entry->path);
618       free (entry);
619     }
620 }
621
622
623 /* Parse configuration file.  */
624 static void
625 parse_conf (const char *filename)
626 {
627   FILE *file;
628   char *line = NULL;
629   size_t len = 0;
630   
631   file = fopen (filename, "r");
632
633   if (file == NULL)
634     {
635       error (0, errno, _("Can't open configuration file %s"), filename);
636       return;
637     }
638
639   do
640     {
641       ssize_t n = getline (&line, &len, file);
642       if (n < 0)
643         break;
644
645       if (line[n - 1] == '\n')
646         line[n - 1] = '\0';
647
648       /* Because the file format does not know any form of quoting we
649          can search forward for the next '#' character and if found
650          make it terminating the line.  */
651       *strchrnul (line, '#') = '\0';
652
653       /* If the line is blank it is ignored.  */
654       if (line[0] == '\0')
655         continue;
656
657       add_dir (line);
658     } while (!feof (file));
659
660   /* Free buffer and close file.  */
661   free (line);
662   fclose (file);
663 }
664
665
666 int
667 main (int argc, char **argv)
668 {
669   int remaining;
670   
671   /* Parse and process arguments.  */
672   argp_parse (&argp, argc, argv, 0, &remaining, NULL);
673
674   /* Remaining arguments are additional libraries if opt_manual_link
675      is not set.  */
676   if (remaining != argc && !opt_manual_link)
677     {
678       int i;
679       for (i = remaining; i < argc; ++i)
680         add_dir (argv [i]);
681     }
682
683   if (cache_file == NULL)
684     cache_file = LD_SO_CACHE;
685
686   if (config_file == NULL)
687     config_file = LD_SO_CONF;
688   
689   /* Chroot first.  */
690   if (opt_chroot)
691     {
692       if (chroot (opt_chroot))
693         /* Report failure and exit program.  */
694         error (EXIT_FAILURE, errno, _("Can't chroot to %s"), opt_chroot);
695       /* chroot doesn't change the working directory, let's play safe.  */
696       if (chdir ("/"))
697         error (EXIT_FAILURE, errno, _("Can't chdir to /"));
698     }
699
700   if (opt_print_cache)
701     {
702       print_cache (cache_file);
703       exit (0);
704     }
705
706   if (opt_manual_link)
707     {
708       /* Link all given libraries manually.  */
709       int i;
710
711       for (i = remaining; i < argc; ++i)
712         manual_link (argv [i]);
713
714       exit (0);
715     }
716   
717   
718   if (opt_build_cache)
719     init_cache ();
720
721   if (!opt_only_cline)
722     {
723       /* Always add the standard search paths.  */
724       add_dir ("/lib");
725       add_dir ("/usr/lib");
726
727       parse_conf (config_file);
728     }
729   
730   search_dirs ();
731
732   if (opt_build_cache)
733     save_cache (cache_file);
734
735   return 0;
736 }