📄 ldconfig.c
字号:
/* * ldconfig - update shared library symlinks * * usage: ldconfig [-DvqnNX] [-f conf] [-C cache] [-r root] dir ... * ldconfig -l [-Dv] lib ... * ldconfig -p * -D: debug mode, don't update links * -v: verbose mode, print things as we go * -q: quiet mode, don't print warnings * -n: don't process standard directories * -N: don't update the library cache * -X: don't update the library links * -l: library mode, manually link libraries * -p: print the current library cache * -f conf: use conf instead of /etc/ld.so.conf * -C cache: use cache instead of /etc/ld.so.cache * -r root: first, do a chroot to the indicated directory * dir ...: directories to process * lib ...: libraries to link * * Copyright 1994-2000 David Engel and Mitch D'Souza * * This program may be used for any purpose as long as this * copyright notice is kept. */#include <stdio.h>#include <stdlib.h>#include <stdarg.h>#include <string.h>#include <ctype.h>#include <getopt.h>#include <dirent.h>#include <unistd.h>#include <link.h>#include <elf.h>#include <sys/stat.h>#include <fcntl.h>#include <sys/mman.h>#include <errno.h>#include "../config.h"#include "readsoname.h"struct exec{ unsigned long a_info; /* Use macros N_MAGIC, etc for access */ unsigned a_text; /* length of text, in bytes */ unsigned a_data; /* length of data, in bytes */ unsigned a_bss; /* length of uninitialized data area for file, in bytes */ unsigned a_syms; /* length of symbol table data in file, in bytes */ unsigned a_entry; /* start address */ unsigned a_trsize; /* length of relocation info for text, in bytes */ unsigned a_drsize; /* length of relocation info for data, in bytes */};#if !defined (N_MAGIC)#define N_MAGIC(exec) ((exec).a_info & 0xffff)#endif/* Code indicating object file or impure executable. */#define OMAGIC 0407/* Code indicating pure executable. */#define NMAGIC 0410/* Code indicating demand-paged executable. */#define ZMAGIC 0413/* This indicates a demand-paged executable with the header in the text. The first page is unmapped to help trap NULL pointer references */#define QMAGIC 0314/* Code indicating core file. */#define CMAGIC 0421#ifdef __GNUC__void warn(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));void error(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));#endifchar *___strtok = NULL;/* For SunOS */#ifndef PATH_MAX#include <limits.h>#define PATH_MAX _POSIX_PATH_MAX#endif/* For SunOS */#ifndef N_MAGIC#define N_MAGIC(exec) ((exec).a_magic & 0xffff)#endif#define EXIT_OK 0#define EXIT_FATAL 128char *prog = NULL;int debug = 0; /* debug mode */int verbose = 0; /* verbose mode */int libmode = 0; /* library mode */int nocache = 0; /* don't build cache */int nolinks = 0; /* don't update links */char *conffile = LDSO_CONF; /* default conf file */char *cachefile = LDSO_CACHE; /* default cache file */void cache_print(void);void cache_dolib(const char *dir, const char *so, int libtype);void cache_write(void);void warn(const char *fmt, ...){ va_list ap; if (verbose < 0) return; fflush(stdout); /* don't mix output and error messages */ fprintf(stderr, "%s: warning: ", prog); va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); fprintf(stderr, "\n"); return;}void error(const char *fmt, ...){ va_list ap; fflush(stdout); /* don't mix output and error messages */ fprintf(stderr, "%s: ", prog); va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); fprintf(stderr, "\n"); exit(EXIT_FATAL);}void *xmalloc(size_t size){ void *ptr; if ((ptr = malloc(size)) == NULL) error("out of memory"); return ptr;}char *xstrdup(const char *str){ char *ptr; if ((ptr = strdup(str)) == NULL) error("out of memory"); return ptr;}/* If shared library, return a malloced copy of the soname and set the type, else return NULL. expected_type should be either LIB_ANY or one of the following:- LIB_DLL LIB_ELF LIB_ELF_LIBC5 LIB_ELF_LIBC6 If the lib is ELF and we can not deduce the type the type will be set based on expected_type. If the expected, actual/deduced types missmatch we display a warning and use the actual/deduced type.*/char *is_shlib(const char *dir, const char *name, int *type, int *islink, int expected_type){ char *good = NULL; char *cp, *cp2; FILE *file; struct exec exec; ElfW(Ehdr) *elf_hdr; struct stat statbuf; char buff[4096]; /* see if name is of the form libZ.so* */ if ((strncmp(name, "lib", 3) == 0 || strncmp(name, "ld-", 3) == 0) && \ name[strlen(name)-1] != '~' && (cp = strstr(name, ".so"))) { /* find the start of the Vminor part, if any */ if (cp[3] == '.' && (cp2 = strchr(cp + 4, '.'))) cp = cp2; else cp = cp + strlen(cp); /* construct the full path name */ sprintf(buff, "%s%s%s", dir, (*dir && strcmp(dir, "/")) ? "/" : "", name); /* first, make sure it's a regular file */ if (lstat(buff, &statbuf)) warn("can't lstat %s (%s), skipping", buff, strerror(errno)); else if (!S_ISREG(statbuf.st_mode) && !S_ISLNK(statbuf.st_mode)) warn("%s is not a regular file or symlink, skipping", buff); else { /* is it a regular file or a symlink */ *islink = S_ISLNK(statbuf.st_mode); /* then try opening it */ if (!(file = fopen(buff, "rb"))) warn("can't open %s (%s), skipping", buff, strerror(errno)); else { /* now make sure it's a shared library */ if (fread(&exec, sizeof exec, 1, file) < 1) warn("can't read header from %s, skipping", buff); else if (N_MAGIC(exec) != ZMAGIC && N_MAGIC(exec) != QMAGIC) { elf_hdr = (ElfW(Ehdr) *) &exec; if (elf_hdr->e_ident[0] != 0x7f || strncmp(&elf_hdr->e_ident[1], "ELF",3) != 0) { /* silently ignore linker scripts */ if (strncmp((char *)&exec, "/* GNU ld", 9) != 0) warn("%s is not a shared library, skipping", buff); } else { /* always call readsoname to update type */ if(expected_type == LIB_DLL){ warn("%s is not an a.out library, its ELF!\n", buff); expected_type=LIB_ANY; } *type = LIB_ELF; good = readsoname(buff, file, expected_type, type, elf_hdr->e_ident[EI_CLASS]); if (good == NULL || *islink) { if (good != NULL) free(good); good = xstrdup(name); } else { /* if the soname does not match the filename, issue a warning, but only in debug mode. */ int len = strlen(good); if (debug && (strncmp(good, name, len) != 0 || (name[len] != '\0' && name[len] != '.'))) warn("%s has inconsistent soname (%s)", buff, good); } } } else { if (*islink) good = xstrdup(name); else { good = xmalloc(cp - name + 1); strncpy(good, name, cp - name); good[cp - name] = '\0'; } if(expected_type != LIB_ANY && expected_type != LIB_DLL) { warn("%s is not an ELF library, its an a.out DLL!", buff); expected_type=LIB_ANY; } *type = LIB_DLL; } fclose(file); } } } return good;}/* update the symlink to new library */void link_shlib(const char *dir, const char *file, const char *so){ int change = 1; char libname[4096]; char linkname[4096]; struct stat libstat; struct stat linkstat; /* construct the full path names */ sprintf(libname, "%s/%s", dir, file); sprintf(linkname, "%s/%s", dir, so); /* see if a link already exists */ if (!stat(linkname, &linkstat)) { /* now see if it's the one we want */ if (stat(libname, &libstat)) warn("can't stat %s (%s)", libname, strerror(errno)); else if (libstat.st_dev == linkstat.st_dev && libstat.st_ino == linkstat.st_ino) change = 0; } /* then update the link, if required */ if (change > 0 && !nolinks) { if (!lstat(linkname, &linkstat)) { if (!S_ISLNK(linkstat.st_mode)) { warn("%s is not a symlink", linkname); change = -1; } else if (remove(linkname)) { warn("can't unlink %s (%s)", linkname, strerror(errno)); change = -1; } } if (change > 0) { if (symlink(file, linkname)) { warn("can't link %s to %s (%s)", linkname, file, strerror(errno)); change = -1; } } } /* some people like to know what we're doing */ if (verbose > 0) printf("\t%s => %s%s\n", so, file, change < 0 ? " (SKIPPED)" : (change > 0 ? " (changed)" : "")); return;}/* figure out which library is greater */int libcmp(char *p1, char *p2){ while (*p1) { if (isdigit(*p1) && isdigit(*p2)) { /* must compare this numerically */ int v1, v2; v1 = strtoul(p1, &p1, 10); v2 = strtoul(p2, &p2, 10); if (v1 != v2) return v1 - v2; } else if (isdigit(*p1) && !isdigit(*p2)) return 1; else if (!isdigit(*p1) && isdigit(*p2)) return -1; else if (*p1 != *p2) return *p1 - *p2; else p1++, p2++; } return *p1 - *p2;}struct lib{ char *so; /* soname of a library */ char *name; /* name of a library */ int libtype; /* type of a library */ int islink; /* is it a symlink */ struct lib *next; /* next library in list */};/* update all shared library links in a directory */void scan_dir(const char *name){ DIR *dir; struct dirent *ent; char *so; struct lib *lp, *libs = NULL; int libtype, islink; int expected_type = LIB_ANY; char *t; /* Check for an embedded expected type */ t=strrchr(name, '='); if( t ) { *t++ = '\0'; /* Skip = char */ if(strcasecmp(t, "libc4") == 0) { expected_type = LIB_DLL; } else { if(strcasecmp(t, "libc5") == 0) { expected_type = LIB_ELF_LIBC5; } else { if(strcasecmp(t, "libc6") == 0) { expected_type = LIB_ELF_LIBC6; } else { warn("Unknown type field '%s' for dir '%s' - ignored\n", t, name); expected_type = LIB_ANY; } } } } /* let 'em know what's going on */ if (verbose > 0) printf("%s:\n", name); /* if we can't open it, we can't do anything */ if ((dir = opendir(name)) == NULL) { warn("can't open %s (%s), skipping", name, strerror(errno)); return; } /* yes, we have to look at every single file */ while ((ent = readdir(dir)) != NULL) { /* if it's not a shared library, don't bother */ if ((so = is_shlib(name, ent->d_name, &libtype, &islink, expected_type)) == NULL) continue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -