Remade for alpha-1.93
[platform/upstream/glibc.git] / elf / dl-cache.c
1 /* Support for reading /etc/ld.so.cache files written by Linux ldconfig.
2 Copyright (C) 1996 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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
17 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
18 Cambridge, MA 02139, USA.  */
19
20 #include <link.h>
21 #include <stddef.h>
22 #include <sys/mman.h>
23
24 /* System-dependent function to read a file's whole contents
25    in the most convenient manner available.  */
26 extern void *_dl_sysdep_read_whole_file (const char *filename,
27                                          size_t *filesize_ptr,
28                                          int mmap_prot);
29
30 #define CACHEMAGIC "ld.so-1.7.0"
31
32 struct cache_file
33   {
34     char magic[sizeof CACHEMAGIC - 1];
35     unsigned int nlibs;
36     struct
37       {
38         int flags;              /* This is 1 for an ELF library.  */
39         unsigned int key, value; /* String table indices.  */
40       } libs[0];
41   };
42
43 /* Look up NAME in ld.so.cache and return the file name stored there,
44    or null if none is found.  */
45
46 const char *
47 _dl_load_cache_lookup (const char *name)
48 {
49   static struct cache_file *cache;
50   static size_t cachesize;
51   unsigned int i;
52
53   if (cache == (void *) -1)
54     /* Previously looked for the cache file and didn't find it.  */
55     return NULL;
56
57   if (cache == NULL)
58     {
59       /* Read the contents of the file.  */
60       void *file = _dl_sysdep_read_whole_file ("/etc/ld.so.cache", &cachesize,
61                                                PROT_READ);
62       if (file && cachesize > sizeof *cache &&
63           !memcmp (file, CACHEMAGIC, sizeof CACHEMAGIC - 1))
64         /* Looks ok.  */
65         cache = file;
66       else
67         {
68           if (file)
69             __munmap (file, cachesize);
70           cache = (void *) -1;
71           return NULL;
72         }
73     }
74
75   for (i = 0; i < cache->nlibs; ++i)
76     if (cache->libs[i].flags == 1 && /* ELF library entry.  */
77         /* Make sure string table indices are not bogus before using them.  */
78         cache->libs[i].key < cachesize - sizeof *cache &&
79         cache->libs[i].value < cachesize - sizeof *cache &&
80         /* Does the name match?  */
81         ! strcmp (name, ((const char *) &cache->libs[cache->nlibs] +
82                          cache->libs[i].key)))
83       return (const char *) &cache->libs[cache->nlibs] + cache->libs[i].value;
84
85   return NULL;
86 }