899539de21f8cfc224606337f1ec0c58d5e21b29
* Copyright (c) 1993 Paul Kranenburg
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Paul Kranenburg.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software withough specific prior written permission
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* $Id: ldconfig.c,v 1.2 1993/11/09 04:19:22 paul Exp $
#include <sys/resource.h>
/* Internal list of shared libraries found */
static struct shlib_list
*shlib_head
= NULL
, **shlib_tail
= &shlib_head
;
static void enter
__P((char *, char *, char *, int *, int));
static int dodir
__P((char *));
static int build_hints
__P((void));
if ((progname
= strrchr(argv
[0], '/')) == NULL
)
while ((c
= getopt(argc
, argv
, "rsv")) != EOF
) {
fprintf(stderr
, "Usage: %s [-v] [dir ...]\n", progname
);
for (i
= 0; i
< n_search_dirs
; i
++)
rval
|= dodir(search_dirs
[i
]);
for (i
= optind
; i
< argc
; i
++)
char name
[MAXPATHLEN
], rest
[MAXPATHLEN
];
int dewey
[MAXDEWEY
], ndewey
;
if ((dd
= opendir(dir
)) == NULL
) {
while ((dp
= readdir(dd
)) != NULL
) {
name
[0] = rest
[0] = '\0';
n
= sscanf(dp
->d_name
, "lib%[^.].so.%s",
if (n
< 2 || rest
[0] == '\0')
ndewey
= getdewey(dewey
, rest
);
enter(dir
, dp
->d_name
, name
, dewey
, ndewey
);
enter(dir
, file
, name
, dewey
, ndewey
)
for (shp
= shlib_head
; shp
; shp
= shp
->next
) {
if (strcmp(name
, shp
->name
) != 0 || major
!= shp
->major
)
/* Name matches existing entry */
if (cmpndewey(dewey
, ndewey
, shp
->dewey
, shp
->ndewey
) > 0) {
/* Update this entry with higher versioned lib */
printf("Updating lib%s.%d.%d to %s/%s\n",
shp
->name
, shp
->major
, shp
->minor
,
shp
->name
= strdup(name
);
shp
->path
= concat(dir
, "/", file
);
bcopy(dewey
, shp
->dewey
, sizeof(shp
->dewey
));
/* Name exists: older version or just updated */
/* Allocate new list element */
printf("Adding %s/%s\n", dir
, file
);
shp
= (struct shlib_list
*)xmalloc(sizeof *shp
);
shp
->name
= strdup(name
);
shp
->path
= concat(dir
, "/", file
);
bcopy(dewey
, shp
->dewey
, MAXDEWEY
);
#define _PATH_LD_HINTS "./ld.so.hints"
hinthash(cp
, vmajor
, vminor
)
k
= (((k
<< 1) + (k
>> 14)) ^ (*cp
++)) & 0x3fff;
k
= (((k
<< 1) + (k
>> 14)) ^ (vmajor
*257)) & 0x3fff;
k
= (((k
<< 1) + (k
>> 14)) ^ (vminor
*167)) & 0x3fff;
struct hints_bucket
*blist
;
int strtab_sz
= 0; /* Total length of strings */
int nhints
= 0; /* Total number of hints */
for (shp
= shlib_head
; shp
; shp
= shp
->next
) {
strtab_sz
+= 1 + strlen(shp
->name
);
strtab_sz
+= 1 + strlen(shp
->path
);
/* Fill hints file header */
hdr
.hh_version
= LD_HINTS_VERSION_1
;
hdr
.hh_nbucket
= 1 * nhints
;
n
= hdr
.hh_nbucket
* sizeof(struct hints_bucket
);
hdr
.hh_hashtab
= sizeof(struct hints_header
);
hdr
.hh_strtab
= hdr
.hh_hashtab
+ n
;
hdr
.hh_strtab_sz
= strtab_sz
;
hdr
.hh_ehints
= hdr
.hh_strtab
+ hdr
.hh_strtab_sz
;
printf("Totals: entries %d, buckets %d, string size %d\n",
nhints
, hdr
.hh_nbucket
, strtab_sz
);
/* Allocate buckets and string table */
blist
= (struct hints_bucket
*)xmalloc(n
);
for (i
= 0; i
< hdr
.hh_nbucket
; i
++)
strtab
= (char *)xmalloc(strtab_sz
);
for (shp
= shlib_head
; shp
; shp
= shp
->next
) {
(hinthash(shp
->name
, shp
->major
, shp
->minor
) % hdr
.hh_nbucket
);
for (i
= 0; i
< hdr
.hh_nbucket
; i
++) {
if (blist
[i
].hi_pathx
== 0)
if (i
== hdr
.hh_nbucket
) {
fprintf(stderr
, "Bummer!\n");
while (bp
->hi_next
!= -1)
bp
= &blist
[bp
->hi_next
];
/* Insert strings in string table */
bp
->hi_namex
= str_index
;
strcpy(strtab
+ str_index
, shp
->name
);
str_index
+= 1 + strlen(shp
->name
);
bp
->hi_pathx
= str_index
;
strcpy(strtab
+ str_index
, shp
->path
);
str_index
+= 1 + strlen(shp
->path
);
bcopy(shp
->dewey
, bp
->hi_dewey
, sizeof(bp
->hi_dewey
));
bp
->hi_ndewey
= shp
->ndewey
;
tmpfile
= concat(_PATH_LD_HINTS
, "+", "");
if ((fd
= open(tmpfile
, O_RDWR
|O_CREAT
|O_TRUNC
, 0444)) == -1) {
mywrite(&hdr
, 1, sizeof(struct hints_header
), fd
);
mywrite(blist
, hdr
.hh_nbucket
, sizeof(struct hints_bucket
), fd
);
mywrite(strtab
, strtab_sz
, 1, fd
);
/* Now, install real file */
if (unlink(_PATH_LD_HINTS
) != 0 && errno
!= ENOENT
) {
if (rename(tmpfile
, _PATH_LD_HINTS
) != 0) {
struct hints_header
*hdr
;
struct hints_bucket
*blist
;
if ((fd
= open(_PATH_LD_HINTS
, O_RDONLY
, 0)) == -1) {
addr
= mmap(0, msize
, PROT_READ
, MAP_FILE
|MAP_COPY
, fd
, 0);
if (addr
== (caddr_t
)-1) {
hdr
= (struct hints_header
*)addr
;
fprintf(stderr
, "%s: Bad magic: %d\n");
if (hdr
->hh_version
!= LD_HINTS_VERSION_1
) {
fprintf(stderr
, "Unsupported version: %d\n", hdr
->hh_version
);
if (hdr
->hh_ehints
> msize
) {
if (mmap(addr
+msize
, hdr
->hh_ehints
- msize
,
PROT_READ
, MAP_FILE
|MAP_COPY
|MAP_FIXED
,
fd
, msize
) != (caddr_t
)(addr
+msize
)) {
blist
= (struct hints_bucket
*)(addr
+ hdr
->hh_hashtab
);
strtab
= (char *)(addr
+ hdr
->hh_strtab
);
printf("%s:\n", _PATH_LD_HINTS
);
for (i
= 0; i
< hdr
->hh_nbucket
; i
++) {
struct hints_bucket
*bp
= &blist
[i
];
if (bp
->hi_namex
>= hdr
->hh_strtab_sz
) {
fprintf(stderr
, "Bad name index: %#x\n", bp
->hi_namex
);
if (bp
->hi_pathx
>= hdr
->hh_strtab_sz
) {
fprintf(stderr
, "Bad path index: %#x\n", bp
->hi_pathx
);
printf("\t%d:-l%s.%d.%d => %s (%d -> %d)\n",
strtab
+ bp
->hi_namex
, bp
->hi_major
, bp
->hi_minor
,
hinthash(strtab
+bp
->hi_namex
, bp
->hi_major
, bp
->hi_minor
)