]> sourceware.org Git - glibc.git/blame - elf/ldconfig.c
Update.
[glibc.git] / elf / ldconfig.c
CommitLineData
45eca4d1 1/* Copyright (C) 1999, 2000 Free Software Foundation, Inc.
591e1ffb
UD
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
7b0d235c 20#include <alloca.h>
591e1ffb
UD
21#include <argp.h>
22#include <dirent.h>
9c95d361 23#include <elf.h>
591e1ffb
UD
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"
45eca4d1 37#include "dl-cache.h"
591e1ffb 38
45eca4d1
UD
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"
591e1ffb
UD
43
44#ifndef LD_SO_CONF
8ca91b36 45# define LD_SO_CONF SYSCONFDIR "/ld.so.conf"
591e1ffb
UD
46#endif
47
48/* Get libc version number. */
49#include <version.h>
50
51#define PACKAGE _libc_intl_domainname
52
53struct lib_entry
54 {
55 int flags;
45eca4d1 56 unsigned long int hwcap;
591e1ffb
UD
57 char *lib;
58 char *path;
59 };
60
61static 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}
45eca4d1 71};
591e1ffb
UD
72
73
74/* List of directories to handle. */
75struct 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. */
84static struct dir_entry *dir_entries;
85
86/* Flags for different options. */
87/* Print Cache. */
88static int opt_print_cache = 0;
89
90/* Be verbose. */
91int opt_verbose = 0;
92
45eca4d1
UD
93/* Format to support. */
94/* 0: only libc5/glibc2; 1: both; 2: only glibc 2.2. */
95int opt_format = 1;
96
591e1ffb
UD
97/* Build cache. */
98static int opt_build_cache = 1;
99
100/* Generate links. */
101static int opt_link = 1;
102
103/* Only process directories specified on the command line. */
104static int opt_only_cline = 0;
105
106/* Path to root for chroot. */
107static char *opt_chroot;
108
b85697f6
UD
109/* Manually link given shared libraries. */
110static int opt_manual_link = 0;
111
591e1ffb
UD
112/* Cache file to use. */
113static const char *cache_file;
114
115/* Configuration file. */
116static const char *config_file;
117
118/* Name and version of program. */
119static void print_version (FILE *stream, struct argp_state *state);
120void (*argp_program_version_hook) (FILE *, struct argp_state *)
121 = print_version;
122
123/* Definitions of arguments for argp functions. */
124static 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},
b85697f6 134 { NULL, 'l', NULL, 0, N_("Manually link individual libraries."), 0},
45eca4d1 135 { "format", 'c', "FORMAT", 0, N_("Format to use: new, old or compat (default)"), 0},
591e1ffb
UD
136 { NULL, 0, NULL, 0, NULL, 0 }
137};
138
139/* Short description of program. */
140static const char doc[] = N_("Configure Dynamic Linker Run Time Bindings.");
141
142/* Prototype for option handler. */
143static error_t parse_opt (int key, char *arg, struct argp_state *state);
144
145/* Data structure to communicate with argp functions. */
146static struct argp argp =
147{
148 options, parse_opt, NULL, doc, NULL, NULL, NULL
149};
150
45eca4d1
UD
151/* Check if string corresponds to an important hardware capability. */
152static int
153is_hwcap (const char *name)
154{
155 int hwcap_idx = _dl_string_hwcap (name);
8ca91b36 156
45eca4d1
UD
157 if (hwcap_idx != -1 && ((1 << hwcap_idx) & HWCAP_IMPORTANT))
158 return 1;
159 return 0;
160}
161
162/* Get hwcap encoding of path. */
163static unsigned long int
164path_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;
591e1ffb 190
45eca4d1
UD
191 /* Search the next part of the path. */
192 *ptr = '\0';
193 }
194
195 free (str);
196 return hwcap;
197}
591e1ffb
UD
198
199/* Handle program arguments. */
200static error_t
201parse_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;
b85697f6
UD
211 case 'l':
212 opt_manual_link = 1;
213 break;
591e1ffb
UD
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;
45eca4d1
UD
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;
591e1ffb
UD
241 default:
242 return ARGP_ERR_UNKNOWN;
243 }
244
245 return 0;
246}
247
248/* Print the version information. */
249static void
250print_version (FILE *stream, struct argp_state *state)
251{
252 fprintf (stream, "ldconfig (GNU %s) %s\n", PACKAGE, VERSION);
253 fprintf (stream, gettext ("\
254Copyright (C) %s Free Software Foundation, Inc.\n\
255This is free software; see the source for copying conditions. There is NO\n\
256warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
45eca4d1 257"), "2000");
591e1ffb
UD
258 fprintf (stream, gettext ("Written by %s.\n"),
259 "Andreas Jaeger");
260}
261
a8fd59b0
AJ
262/* Add a single directory entry. */
263static void
264add_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
591e1ffb
UD
292/* Add one directory to the list of directories to process. */
293static void
294add_dir (const char *line)
295{
296 char *equal_sign;
a8fd59b0 297 struct dir_entry *entry;
591e1ffb 298 unsigned int i;
45eca4d1 299
591e1ffb
UD
300 entry = xmalloc (sizeof (struct dir_entry));
301 entry->next = NULL;
45eca4d1 302
591e1ffb
UD
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 }
45eca4d1 332
a8fd59b0 333 add_single_dir (entry, 1);
591e1ffb
UD
334}
335
336
337/* Create a symbolic link from soname to libname in directory path. */
338static void
339create_links (const char *path, const char *libname, const char *soname)
340{
7b0d235c 341 char *full_libname, *full_soname;
591e1ffb
UD
342 struct stat stat_lib, stat_so, lstat_so;
343 int do_link = 1;
344 int do_remove = 1;
345 /* XXX: The logics in this function should be simplified. */
45eca4d1 346
591e1ffb 347 /* Get complete path. */
7b0d235c
AJ
348 full_libname = alloca (strlen (path) + strlen (libname) + 2);
349 full_soname = alloca (strlen (path) + strlen (libname) + 2);
350 sprintf (full_libname, "%s/%s", path, libname);
351 sprintf (full_soname, "%s/%s", path, soname);
591e1ffb
UD
352
353 /* Does soname already exist and point to the right library? */
354 if (stat (full_soname, &stat_so) == 0)
355 {
356 if (stat (full_libname, &stat_lib))
357 {
358 error (0, 0, _("Can't stat %s\n"), full_libname);
359 return;
360 }
361 if (stat_lib.st_dev == stat_so.st_dev
362 && stat_lib.st_ino == stat_so.st_ino)
363 /* Link is already correct. */
364 do_link = 0;
365 else if (lstat (full_soname, &lstat_so) == 0
366 && !S_ISLNK (lstat_so.st_mode))
367 {
368 error (0, 0, _("%s is not a symbolic link\n"), full_soname);
369 do_link = 0;
370 do_remove = 0;
371 }
372 }
373 else if (lstat (full_soname, &lstat_so) != 0
374 || !S_ISLNK (lstat_so.st_mode))
375 /* Unless it is a stale symlink, there is no need to remove. */
376 do_remove = 0;
377
378 if (opt_verbose)
379 printf ("\t%s -> %s", soname, libname);
380
381 if (do_link && opt_link)
382 {
383 /* Remove old link. */
384 if (do_remove)
385 if (unlink (full_soname))
386 {
387 error (0, 0, _("Can't unlink %s"), full_soname);
388 do_link = 0;
389 }
390 /* Create symbolic link. */
391 if (do_link && symlink (libname, full_soname))
392 {
393 error (0, 0, _("Can't link %s to %s"), full_soname, libname);
394 do_link = 0;
395 }
396 if (opt_verbose)
397 {
398 if (do_link)
399 fputs (_(" (changed)\n"), stdout);
400 else
401 fputs (_(" (SKIPPED)\n"), stdout);
402 }
403 }
404 else if (opt_verbose)
405 fputs ("\n", stdout);
406}
407
b85697f6
UD
408/* Manually link the given library. */
409static void
410manual_link (char *library)
411{
412 char *path;
413 char *libname;
414 char *soname;
415 struct stat stat_buf;
416 int flag;
417
418 /* Prepare arguments for create_links call. Split library name in
419 directory and filename first. Since path is allocated, we've got
420 to be careful to free at the end. */
421 path = xstrdup (library);
422 libname = strrchr (path, '/');
423
424 if (libname)
425 {
426 /* Successfully split names. Check if path is just "/" to avoid
427 an empty path. */
428 if (libname == path)
429 {
430 libname = library + 1;
431 path = xrealloc (path, 2);
432 strcpy (path, "/");
433 }
434 else
435 {
436 *libname = '\0';
437 ++libname;
438 }
439 }
440 else
441 {
442 /* There's no path, construct one. */
443 libname = library;
444 path = xrealloc (path, 2);
445 strcpy (path, ".");
446 }
447
448 /* Do some sanity checks first. */
449 if (lstat (library, &stat_buf))
450 {
451 error (0, errno, _("Can't lstat %s"), library);
452 free (path);
453 return;
454 }
455 /* We don't want links here! */
456 else if (!S_ISREG (stat_buf.st_mode))
457 {
458 error (0, 0, _("Ignored file %s since it is not a regular file."),
459 library);
460 free (path);
461 return;
462 }
463 libname = basename (library);
464 if (process_file (library, libname, &flag, &soname, 0))
465 {
466 error (0, 0, _("No link created since soname could not be found for %s"),
467 library);
468 free (path);
469 return;
470 }
471 create_links (path, libname, soname);
472 free (soname);
473 free (path);
474}
475
476
591e1ffb
UD
477/* Read a whole directory and search for libraries.
478 The purpose is two-fold:
479 - search for libraries which will be added to the cache
480 - create symbolic links to the soname for each library
481
482 This has to be done separatly for each directory.
45eca4d1 483
591e1ffb
UD
484 To keep track of which libraries to add to the cache and which
485 links to create, we save a list of all libraries.
486
487 The algorithm is basically:
488 for all libraries in the directory do
489 get soname of library
490 if soname is already in list
491 if new library is newer, replace entry
492 otherwise ignore this library
493 otherwise add library to list
45eca4d1 494
591e1ffb
UD
495 For example, if the two libraries libxy.so.1.1 and libxy.so.1.2
496 exist and both have the same soname, e.g. libxy.so, a symbolic link
497 is created from libxy.so.1.2 (the newer one) to libxy.so.
498 libxy.so.1.2 and libxy.so are added to the cache - but not
499 libxy.so.1.1. */
500
501/* Information for one library. */
45eca4d1 502struct dlib_entry
591e1ffb
UD
503{
504 char *name;
505 char *soname;
506 int flag;
507 int is_link;
508 struct dlib_entry *next;
509};
510
511
512static void
513search_dir (const struct dir_entry *entry)
514{
515 DIR *dir;
516 struct dirent *direntry;
7b0d235c
AJ
517 char *file_name;
518 int file_name_len, len;
591e1ffb
UD
519 char *soname;
520 struct dlib_entry *dlibs;
521 struct dlib_entry *dlib_ptr;
591e1ffb
UD
522 struct stat stat_buf;
523 int is_link;
45eca4d1
UD
524 unsigned long int hwcap = path_hwcap (entry->path);
525
7b0d235c
AJ
526 file_name_len = PATH_MAX;
527 file_name = alloca (file_name_len);
f0189a54 528
591e1ffb
UD
529 dlibs = NULL;
530
531 if (opt_verbose)
45eca4d1
UD
532 {
533 if (hwcap != 0)
534 printf ("%s: (hwcap: 0x%lx)\n", entry->path, hwcap);
535 else
536 printf ("%s:\n", entry->path);
537 }
538
591e1ffb
UD
539 dir = opendir (entry->path);
540 if (dir == NULL)
541 {
542 if (opt_verbose)
543 error (0, errno, _("Can't open directory %s"), entry->path);
544 return;
545 }
45eca4d1 546
591e1ffb
UD
547
548 while ((direntry = readdir (dir)) != NULL)
549 {
550 int flag;
551#ifdef _DIRENT_HAVE_D_TYPE
552 /* We only look at links and regular files. */
553 if (direntry->d_type != DT_UNKNOWN
554 && direntry->d_type != DT_LNK
45eca4d1
UD
555 && direntry->d_type != DT_REG
556 && direntry->d_type != DT_DIR)
591e1ffb
UD
557 continue;
558#endif /* _DIRENT_HAVE_D_TYPE */
45eca4d1
UD
559 /* Does this file look like a shared library or is it a hwcap
560 subdirectory? The dynamic linker is also considered as
561 shared library. */
562 if (((strncmp (direntry->d_name, "lib", 3) != 0
563 && strncmp (direntry->d_name, "ld-", 3) != 0)
564 || strstr (direntry->d_name, ".so") == NULL)
565 && !is_hwcap (direntry->d_name))
591e1ffb 566 continue;
7b0d235c
AJ
567 len = strlen (entry->path) + strlen (direntry->d_name);
568 if (len > file_name_len)
591e1ffb 569 {
7b0d235c
AJ
570 file_name_len = len + 1;
571 file_name = alloca (file_name_len);
591e1ffb 572 }
f0189a54 573 sprintf (file_name , "%s/%s", entry->path, direntry->d_name);
7c3002f0
UD
574#ifdef _DIRENT_HAVE_D_TYPE
575 if (direntry->d_type != DT_UNKNOWN)
576 stat_buf.st_mode = DTTOIF (direntry->d_type);
577 else
578#endif
7b0d235c 579 if (lstat (file_name, &stat_buf))
7c3002f0 580 {
7b0d235c 581 error (0, errno, _("Can't lstat %s"), file_name);
7c3002f0
UD
582 continue;
583 }
584
585 if (S_ISDIR (stat_buf.st_mode) && is_hwcap (direntry->d_name))
45eca4d1 586 {
a8fd59b0
AJ
587 /* Handle subdirectory later. */
588 struct dir_entry *new_entry;
589
590 new_entry = xmalloc (sizeof (struct dir_entry));
7b0d235c 591 new_entry->path = xstrdup (file_name);
a8fd59b0
AJ
592 new_entry->flag = entry->flag;
593 new_entry->next = NULL;
594 add_single_dir (new_entry, 0);
45eca4d1
UD
595 continue;
596 }
591e1ffb
UD
597 else if (!S_ISREG (stat_buf.st_mode) && !S_ISLNK (stat_buf.st_mode))
598 continue;
599
600 is_link = S_ISLNK (stat_buf.st_mode);
601
7b0d235c 602 if (process_file (file_name, direntry->d_name, &flag, &soname, is_link))
591e1ffb
UD
603 continue;
604
605 /* Links will just point to itself. */
606 if (is_link)
607 {
608 free (soname);
609 soname = xstrdup (direntry->d_name);
610 }
45eca4d1 611
591e1ffb
UD
612 if (flag == FLAG_ELF
613 && (entry->flag == FLAG_ELF_LIBC5
614 || entry->flag == FLAG_ELF_LIBC6))
615 flag = entry->flag;
616 /* Some sanity checks to print warnings. */
617 if (opt_verbose)
618 {
619 if (flag == FLAG_ELF_LIBC5 && entry->flag != FLAG_ELF_LIBC5
620 && entry->flag != FLAG_ANY)
7b0d235c 621 error (0, 0, _("libc5 library %s in wrong directory"), file_name);
591e1ffb
UD
622 if (flag == FLAG_ELF_LIBC6 && entry->flag != FLAG_ELF_LIBC6
623 && entry->flag != FLAG_ANY)
7b0d235c 624 error (0, 0, _("libc6 library %s in wrong directory"), file_name);
591e1ffb
UD
625 if (flag == FLAG_LIBC4 && entry->flag != FLAG_LIBC4
626 && entry->flag != FLAG_ANY)
7b0d235c 627 error (0, 0, _("libc4 library %s in wrong directory"), file_name);
591e1ffb 628 }
45eca4d1 629
591e1ffb
UD
630 /* Add library to list. */
631 for (dlib_ptr = dlibs; dlib_ptr != NULL; dlib_ptr = dlib_ptr->next)
632 {
633 /* Is soname already in list? */
634 if (strcmp (dlib_ptr->soname, soname) == 0)
635 {
636 /* Prefer a file to a link, otherwise check which one
637 is newer. */
638 if ((!is_link && dlib_ptr->is_link)
639 || (is_link == dlib_ptr->is_link
45eca4d1 640 && _dl_cache_libcmp (dlib_ptr->name, direntry->d_name) < 0))
591e1ffb
UD
641 {
642 /* It's newer - add it. */
643 /* Flag should be the same - sanity check. */
644 if (dlib_ptr->flag != flag)
645 {
646 if (dlib_ptr->flag == FLAG_ELF
647 && (flag == FLAG_ELF_LIBC5 || flag == FLAG_ELF_LIBC6))
648 dlib_ptr->flag = flag;
649 else if ((dlib_ptr->flag == FLAG_ELF_LIBC5
650 || dlib_ptr->flag == FLAG_ELF_LIBC6)
651 && flag == FLAG_ELF)
652 dlib_ptr->flag = flag;
653 else
654 error (0, 0, _("libraries %s and %s in directory %s have same soname but different type."),
655 dlib_ptr->name, direntry->d_name, entry->path);
656 }
657 free (dlib_ptr->name);
658 dlib_ptr->name = xstrdup (direntry->d_name);
659 dlib_ptr->is_link = is_link;
660 }
661 /* Don't add this library, abort loop. */
662 /* Also free soname, since it's dynamically allocated. */
663 free (soname);
664 break;
665 }
666 }
667 /* Add the library if it's not already in. */
668 if (dlib_ptr == NULL)
669 {
670 dlib_ptr = (struct dlib_entry *)xmalloc (sizeof (struct dlib_entry));
671 dlib_ptr->name = xstrdup (direntry->d_name);
672 dlib_ptr->flag = flag;
673 dlib_ptr->soname = soname;
674 dlib_ptr->is_link = is_link;
675 /* Add at head of list. */
676 dlib_ptr->next = dlibs;
677 dlibs = dlib_ptr;
678 }
679 }
680
681 closedir (dir);
682
683 /* Now dlibs contains a list of all libs - add those to the cache
684 and created all symbolic links. */
685 for (dlib_ptr = dlibs; dlib_ptr != NULL; dlib_ptr = dlib_ptr->next)
686 {
687 /* Don't create links to links. */
688 if (dlib_ptr->is_link == 0)
689 create_links (entry->path, dlib_ptr->name, dlib_ptr->soname);
690 if (opt_build_cache)
45eca4d1 691 add_to_cache (entry->path, dlib_ptr->soname, dlib_ptr->flag, hwcap);
591e1ffb
UD
692 }
693
694 /* Free all resources. */
45eca4d1 695 while (dlibs)
591e1ffb
UD
696 {
697 dlib_ptr = dlibs;
698 free (dlib_ptr->soname);
699 free (dlib_ptr->name);
700 dlibs = dlibs->next;
701 free (dlib_ptr);
702 }
703}
704
705/* Search through all libraries. */
706static void
707search_dirs (void)
708{
709 struct dir_entry *entry;
710
711 for (entry = dir_entries; entry != NULL; entry = entry->next)
712 search_dir (entry);
713
714 /* Free all allocated memory. */
715 while (dir_entries)
716 {
717 entry = dir_entries;
718 dir_entries = dir_entries->next;
719 free (entry->path);
720 free (entry);
721 }
722}
723
724
725/* Parse configuration file. */
726static void
727parse_conf (const char *filename)
728{
729 FILE *file;
730 char *line = NULL;
731 size_t len = 0;
45eca4d1 732
591e1ffb
UD
733 file = fopen (filename, "r");
734
735 if (file == NULL)
736 {
f0189a54
UD
737 error (0, errno, _("Can't open configuration file %s%s%s"),
738 opt_chroot ?: "", opt_chroot ? "/" : "", filename);
591e1ffb
UD
739 return;
740 }
741
742 do
743 {
744 ssize_t n = getline (&line, &len, file);
745 if (n < 0)
746 break;
747
748 if (line[n - 1] == '\n')
749 line[n - 1] = '\0';
750
751 /* Because the file format does not know any form of quoting we
752 can search forward for the next '#' character and if found
753 make it terminating the line. */
754 *strchrnul (line, '#') = '\0';
755
756 /* If the line is blank it is ignored. */
757 if (line[0] == '\0')
758 continue;
759
760 add_dir (line);
761 } while (!feof (file));
762
763 /* Free buffer and close file. */
764 free (line);
765 fclose (file);
766}
767
768
769int
770main (int argc, char **argv)
771{
772 int remaining;
45eca4d1 773
591e1ffb
UD
774 /* Parse and process arguments. */
775 argp_parse (&argp, argc, argv, 0, &remaining, NULL);
776
b85697f6
UD
777 /* Remaining arguments are additional libraries if opt_manual_link
778 is not set. */
779 if (remaining != argc && !opt_manual_link)
591e1ffb
UD
780 {
781 int i;
782 for (i = remaining; i < argc; ++i)
783 add_dir (argv [i]);
784 }
785
786 if (cache_file == NULL)
787 cache_file = LD_SO_CACHE;
788
789 if (config_file == NULL)
790 config_file = LD_SO_CONF;
45eca4d1 791
591e1ffb
UD
792 /* Chroot first. */
793 if (opt_chroot)
794 {
f0189a54
UD
795 /* Normalize the path a bit, we might need it for printing later. */
796 char *endp = strchr (opt_chroot, '\0');
797 while (endp > opt_chroot + 1 && endp[-1] == '/')
798 --endp;
799 *endp = '\0';
800
591e1ffb
UD
801 if (chroot (opt_chroot))
802 /* Report failure and exit program. */
803 error (EXIT_FAILURE, errno, _("Can't chroot to %s"), opt_chroot);
804 /* chroot doesn't change the working directory, let's play safe. */
805 if (chdir ("/"))
806 error (EXIT_FAILURE, errno, _("Can't chdir to /"));
807 }
808
809 if (opt_print_cache)
810 {
811 print_cache (cache_file);
812 exit (0);
813 }
814
b85697f6
UD
815 if (opt_manual_link)
816 {
817 /* Link all given libraries manually. */
818 int i;
819
820 for (i = remaining; i < argc; ++i)
821 manual_link (argv [i]);
822
823 exit (0);
824 }
45eca4d1
UD
825
826
591e1ffb
UD
827 if (opt_build_cache)
828 init_cache ();
829
830 if (!opt_only_cline)
831 {
832 /* Always add the standard search paths. */
8ca91b36
UD
833 add_dir (SLIBDIR);
834 if (strcmp (SLIBDIR, LIBDIR))
835 add_dir (LIBDIR);
591e1ffb
UD
836
837 parse_conf (config_file);
838 }
45eca4d1 839
591e1ffb
UD
840 search_dirs ();
841
842 if (opt_build_cache)
843 save_cache (cache_file);
844
845 return 0;
846}
This page took 0.149629 seconds and 5 git commands to generate.