ldconfig.c 25 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009
  1. /*
  2. * ldconfig - update shared library symlinks
  3. *
  4. * usage: ldconfig [-DvqnNX] [-f conf] [-C cache] [-r root] dir ...
  5. * ldconfig -l [-Dv] lib ...
  6. * ldconfig -p
  7. * -D: debug mode, don't update links
  8. * -v: verbose mode, print things as we go
  9. * -q: quiet mode, don't print warnings
  10. * -n: don't process standard directories
  11. * -N: don't update the library cache
  12. * -X: don't update the library links
  13. * -l: library mode, manually link libraries
  14. * -p: print the current library cache
  15. * -f conf: use conf instead of /etc/ld.so.conf
  16. * -C cache: use cache instead of /etc/ld.so.cache
  17. * -r root: first, do a chroot to the indicated directory
  18. * dir ...: directories to process
  19. * lib ...: libraries to link
  20. *
  21. * Copyright 1994-2000 David Engel and Mitch D'Souza
  22. *
  23. * This program may be used for any purpose as long as this
  24. * copyright notice is kept.
  25. *
  26. * 2005/09/16: Dan Howell (modified for cross-development)
  27. */
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. #include <stdarg.h>
  31. #include <string.h>
  32. #include <ctype.h>
  33. #include <dirent.h>
  34. #include <unistd.h>
  35. #include <link.h>
  36. #include <fcntl.h>
  37. #include <errno.h>
  38. #include <sys/stat.h>
  39. #include <sys/mman.h>
  40. #include "bswap.h"
  41. #include "dl-defs.h"
  42. #define BUFFER_SIZE 4096
  43. struct exec {
  44. unsigned long a_info; /* Use macros N_MAGIC, etc for access */
  45. unsigned a_text; /* length of text, in bytes */
  46. unsigned a_data; /* length of data, in bytes */
  47. unsigned a_bss; /* length of uninitialized data area for file, in bytes */
  48. unsigned a_syms; /* length of symbol table data in file, in bytes */
  49. unsigned a_entry; /* start address */
  50. unsigned a_trsize; /* length of relocation info for text, in bytes */
  51. unsigned a_drsize; /* length of relocation info for data, in bytes */
  52. };
  53. #if !defined (N_MAGIC)
  54. #define N_MAGIC(exec) ((exec).a_info & 0xffff)
  55. #endif
  56. #define N_MAGIC_SWAP(exec) (bswap_32((exec).a_info) & 0xffff)
  57. /* Code indicating object file or impure executable. */
  58. #define OMAGIC 0407
  59. /* Code indicating pure executable. */
  60. #define NMAGIC 0410
  61. /* Code indicating demand-paged executable. */
  62. #define ZMAGIC 0413
  63. /* This indicates a demand-paged executable with the header in the text.
  64. The first page is unmapped to help trap NULL pointer references */
  65. #define QMAGIC 0314
  66. /* Code indicating core file. */
  67. #define CMAGIC 0421
  68. char *___strtok = NULL;
  69. /* For SunOS */
  70. #ifndef PATH_MAX
  71. #include <limits.h>
  72. #define PATH_MAX _POSIX_PATH_MAX
  73. #endif
  74. /* For SunOS */
  75. #ifndef N_MAGIC
  76. #define N_MAGIC(exec) ((exec).a_magic & 0xffff)
  77. #endif
  78. #define EXIT_OK 0
  79. #define EXIT_FATAL 128
  80. char *prog = NULL;
  81. int debug = 0; /* debug mode */
  82. int verbose = 0; /* verbose mode */
  83. int libmode = 0; /* library mode */
  84. int nolinks = 0; /* don't update links */
  85. int nocache = 0; /* don't build cache */
  86. void cache_print(void);
  87. void cache_write(void);
  88. void cache_dolib(const char *dir, const char *so, int libtype);
  89. #ifdef __LDSO_CACHE_SUPPORT__
  90. char *conffile = LDSO_CONF; /* default conf file */
  91. char *cachefile = LDSO_CACHE; /* default cache file */
  92. #endif
  93. char *chroot_dir = NULL;
  94. int byteswap = 0;
  95. struct needed_tab {
  96. char *soname;
  97. int type;
  98. };
  99. struct needed_tab needed_tab[] = {
  100. {"libc.so.0", LIB_ELF_LIBC0},
  101. {"libm.so.0", LIB_ELF_LIBC0},
  102. {"libdl.so.0", LIB_ELF_LIBC0},
  103. {"libc.so.5", LIB_ELF_LIBC5},
  104. {"libm.so.5", LIB_ELF_LIBC5},
  105. {"libdl.so.1", LIB_ELF_LIBC5},
  106. {"libc.so.6", LIB_ELF_LIBC6},
  107. {"libm.so.6", LIB_ELF_LIBC6},
  108. {"libdl.so.2", LIB_ELF_LIBC6},
  109. {NULL, LIB_ELF}
  110. };
  111. extern char *chroot_realpath(const char *chroot, const char *path,
  112. char resolved_path[]);
  113. /* These two are used internally -- you shouldn't need to use them */
  114. static void verror_msg(const char *s, va_list p)
  115. {
  116. fflush(stdout);
  117. fprintf(stderr, "%s: ", prog);
  118. vfprintf(stderr, s, p);
  119. }
  120. static void warnx(const char *s, ...)
  121. {
  122. va_list p;
  123. va_start(p, s);
  124. verror_msg(s, p);
  125. va_end(p);
  126. fprintf(stderr, "\n");
  127. }
  128. static void err(int errnum, const char *s, ...)
  129. {
  130. va_list p;
  131. va_start(p, s);
  132. verror_msg(s, p);
  133. va_end(p);
  134. fprintf(stderr, "\n");
  135. exit(errnum);
  136. }
  137. static void vperror_msg(const char *s, va_list p)
  138. {
  139. int err = errno;
  140. if (s == 0)
  141. s = "";
  142. verror_msg(s, p);
  143. if (*s)
  144. s = ": ";
  145. fprintf(stderr, "%s%s\n", s, strerror(err));
  146. }
  147. static void warn(const char *s, ...)
  148. {
  149. va_list p;
  150. va_start(p, s);
  151. vperror_msg(s, p);
  152. va_end(p);
  153. }
  154. static void *xmalloc(size_t size)
  155. {
  156. void *ptr;
  157. if ((ptr = malloc(size)) == NULL)
  158. err(EXIT_FATAL, "out of memory");
  159. return ptr;
  160. }
  161. static char *xstrdup(const char *str)
  162. {
  163. char *ptr;
  164. if ((ptr = strdup(str)) == NULL)
  165. err(EXIT_FATAL, "out of memory");
  166. return ptr;
  167. }
  168. #undef __ELF_NATIVE_CLASS
  169. #undef readsonameXX
  170. #define readsonameXX readsoname32
  171. #define __ELF_NATIVE_CLASS 32
  172. #include "readsoname2.c"
  173. #undef __ELF_NATIVE_CLASS
  174. #undef readsonameXX
  175. #define readsonameXX readsoname64
  176. #define __ELF_NATIVE_CLASS 64
  177. #include "readsoname2.c"
  178. char *readsoname(char *name, FILE *infile, int expected_type,
  179. int *type, int elfclass)
  180. {
  181. char *res;
  182. if (elfclass == ELFCLASS32)
  183. res = readsoname32(name, infile, expected_type, type);
  184. else {
  185. res = readsoname64(name, infile, expected_type, type);
  186. #if 0
  187. /* relies on multilib support which we dont have ... */
  188. *type |= LIB_ELF64;
  189. #endif
  190. }
  191. return res;
  192. }
  193. /* If shared library, return a malloced copy of the soname and set the
  194. * type, else return NULL.
  195. *
  196. * expected_type should be either LIB_ANY or one of the following:-
  197. * LIB_DLL
  198. * LIB_ELF
  199. * LIB_ELF_LIBC5
  200. * LIB_ELF_LIBC6
  201. *
  202. * If the lib is ELF and we can not deduce the type the type will
  203. * be set based on expected_type.
  204. *
  205. * If the expected, actual/deduced types missmatch we display a warning
  206. * and use the actual/deduced type.
  207. */
  208. char *is_shlib(const char *dir, const char *name, int *type,
  209. int *islink, int expected_type)
  210. {
  211. char *good = NULL;
  212. char *cp, *cp2;
  213. FILE *file;
  214. struct exec exec;
  215. ElfW(Ehdr) *elf_hdr;
  216. struct stat statbuf;
  217. char buff[BUFFER_SIZE];
  218. char real[BUFFER_SIZE];
  219. static int byteswapflag = -1; /* start with byte-order unknown */
  220. /* see if name is of the form *.so* */
  221. if (name[strlen(name) - 1] != '~' && (cp = strstr(name, ".so"))) {
  222. /* find the start of the Vminor part, if any */
  223. if (cp[3] == '.' && (cp2 = strchr(cp + 4, '.')))
  224. cp = cp2;
  225. else
  226. cp = cp + strlen(cp);
  227. /* construct the full path name */
  228. sprintf(buff, "%s%s%s", dir, (*dir && strcmp(dir, "/")) ? "/" : "", name);
  229. /* get real path in case of chroot */
  230. if (!chroot_realpath(chroot_dir, buff, real))
  231. warn("can't resolve %s in chroot %s", buff, chroot_dir);
  232. /* first, make sure it's a regular file */
  233. if (lstat(real, &statbuf))
  234. warn("skipping %s", buff);
  235. else if (!S_ISREG(statbuf.st_mode) && !S_ISLNK(statbuf.st_mode))
  236. warnx("%s is not a regular file or symlink, skipping", buff);
  237. else {
  238. /* is it a regular file or a symlink */
  239. *islink = S_ISLNK(statbuf.st_mode);
  240. /* then try opening it */
  241. if (!(file = fopen(real, "rb")))
  242. warn("skipping %s", buff);
  243. else {
  244. /* now make sure it's a shared library */
  245. if (fread(&exec, sizeof exec, 1, file) < 1)
  246. warnx("can't read header from %s, skipping", buff);
  247. else if (N_MAGIC(exec) != ZMAGIC
  248. && N_MAGIC(exec) != QMAGIC
  249. && N_MAGIC_SWAP(exec) != ZMAGIC
  250. && N_MAGIC_SWAP(exec) != QMAGIC) {
  251. elf_hdr = (ElfW(Ehdr) *) & exec;
  252. if (elf_hdr->e_ident[0] != 0x7f ||
  253. strncmp((char *)elf_hdr->e_ident + 1, "ELF", 3) != 0)
  254. {
  255. /* silently ignore linker scripts */
  256. if (strncmp((char *)&exec, "/* GNU ld", 9) != 0)
  257. warnx("%s is not a shared library, skipping", buff);
  258. } else {
  259. /* always call readsoname to update type */
  260. if (expected_type == LIB_DLL) {
  261. warnx("%s is not an a.out library, it's ELF!", buff);
  262. expected_type = LIB_ANY;
  263. }
  264. *type = LIB_ELF;
  265. good = readsoname(buff, file, expected_type, type,
  266. elf_hdr->e_ident[EI_CLASS]);
  267. if (byteswapflag == -1)
  268. /* byte-order detected */
  269. byteswapflag = byteswap;
  270. if (good == NULL || *islink) {
  271. if (good != NULL)
  272. free(good);
  273. good = xstrdup(name);
  274. } else {
  275. /* if the soname does not match the filename,
  276. issue a warning, but only in debug mode. */
  277. int len = strlen(good);
  278. if (debug && (strncmp(good, name, len) != 0
  279. || (name[len] != '\0' && name[len] != '.')))
  280. warnx("%s has inconsistent soname (%s)", buff, good);
  281. }
  282. }
  283. } else {
  284. /* Determine byte-order */
  285. byteswap = (N_MAGIC(exec) == ZMAGIC || N_MAGIC(exec) == QMAGIC) ? 0 : 1;
  286. if (byteswapflag == -1)
  287. /* byte-order detected */
  288. byteswapflag = byteswap;
  289. if (*islink)
  290. good = xstrdup(name);
  291. else {
  292. good = xmalloc(cp - name + 1);
  293. strncpy(good, name, cp - name);
  294. good[cp - name] = '\0';
  295. }
  296. if (expected_type != LIB_ANY && expected_type != LIB_DLL) {
  297. warnx("%s is not an ELF library, its an a.out DLL!", buff);
  298. expected_type = LIB_ANY;
  299. }
  300. *type = LIB_DLL;
  301. }
  302. fclose(file);
  303. if (byteswapflag >= 0 && byteswap != byteswapflag) {
  304. byteswapflag = -2;
  305. warnx("mixed byte-order detected, using host byte-order...");
  306. }
  307. if (byteswapflag == -2)
  308. byteswap = 0;
  309. }
  310. }
  311. }
  312. return good;
  313. }
  314. /* update the symlink to new library */
  315. void link_shlib(const char *dir, const char *file, const char *so)
  316. {
  317. int change = 1;
  318. char libname[BUFFER_SIZE];
  319. char linkname[BUFFER_SIZE];
  320. char reallibname[BUFFER_SIZE];
  321. char reallinkname[BUFFER_SIZE];
  322. struct stat libstat;
  323. struct stat linkstat;
  324. /* construct the full path names */
  325. sprintf(libname, "%s/%s", dir, file);
  326. sprintf(linkname, "%s/%s", dir, so);
  327. if (!chroot_realpath(chroot_dir, libname, reallibname))
  328. warn("can't resolve %s in chroot %s", libname, chroot_dir);
  329. if (!chroot_realpath(chroot_dir, linkname, reallinkname))
  330. warn("can't resolve %s in chroot %s", linkname, chroot_dir);
  331. /* see if a link already exists */
  332. if (!stat(reallinkname, &linkstat)) {
  333. /* now see if it's the one we want */
  334. if (stat(reallibname, &libstat))
  335. warn("can't stat %s", libname);
  336. else if (libstat.st_dev == linkstat.st_dev &&
  337. libstat.st_ino == linkstat.st_ino)
  338. change = 0;
  339. }
  340. /* then update the link, if required */
  341. if (change > 0 && !nolinks) {
  342. if (!lstat(reallinkname, &linkstat)) {
  343. if (!S_ISLNK(linkstat.st_mode)) {
  344. warnx("%s is not a symlink", linkname);
  345. change = -1;
  346. } else if (remove(reallinkname)) {
  347. warn("can't unlink %s", linkname);
  348. change = -1;
  349. }
  350. }
  351. if (change > 0) {
  352. if (symlink(file, reallinkname)) {
  353. warn("can't link %s to %s", linkname, file);
  354. change = -1;
  355. }
  356. }
  357. }
  358. /* some people like to know what we're doing */
  359. if (verbose > 0)
  360. printf("\t%s => %s%s\n", so, file,
  361. change < 0 ? " (SKIPPED)" :
  362. (change > 0 ? " (changed)" : ""));
  363. return;
  364. }
  365. /* figure out which library is greater */
  366. int libcmp(char *p1, char *p2)
  367. {
  368. while (*p1) {
  369. if (isdigit(*p1) && isdigit(*p2)) {
  370. /* must compare this numerically */
  371. int v1, v2;
  372. v1 = strtoul(p1, &p1, 10);
  373. v2 = strtoul(p2, &p2, 10);
  374. if (v1 != v2)
  375. return v1 - v2;
  376. } else if (isdigit(*p1) && !isdigit(*p2))
  377. return 1;
  378. else if (!isdigit(*p1) && isdigit(*p2))
  379. return -1;
  380. else if (*p1 != *p2)
  381. return *p1 - *p2;
  382. else
  383. p1++, p2++;
  384. }
  385. return *p1 - *p2;
  386. }
  387. struct lib {
  388. char *so; /* soname of a library */
  389. char *name; /* name of a library */
  390. int libtype; /* type of a library */
  391. int islink; /* is it a symlink */
  392. struct lib *next; /* next library in list */
  393. };
  394. /* update all shared library links in a directory */
  395. void scan_dir(const char *rawname)
  396. {
  397. DIR *dir;
  398. const char *name;
  399. struct dirent *ent;
  400. char *so, *path, *path_n;
  401. struct lib *lp, *libs = NULL;
  402. int i, libtype, islink, expected_type = LIB_ANY;
  403. char realname[BUFFER_SIZE];
  404. /* We need a writable copy of this string */
  405. path = strdup(rawname);
  406. if (!path) {
  407. err(EXIT_FATAL, "Out of memory!\n");
  408. }
  409. /* Eliminate all double //s */
  410. path_n = path;
  411. while ((path_n = strstr(path_n, "//"))) {
  412. i = strlen(path_n);
  413. memmove(path_n, path_n + 1, i - 1);
  414. *(path_n + i - 1) = '\0';
  415. }
  416. name = path;
  417. #if 0
  418. char *t;
  419. /* Check for an embedded expected type */
  420. t = strrchr(name, '=');
  421. if (t) {
  422. *t++ = '\0'; /* Skip = char */
  423. if (strcasecmp(t, "libc4") == 0) {
  424. expected_type = LIB_DLL;
  425. } else {
  426. if (strcasecmp(t, "libc5") == 0) {
  427. expected_type = LIB_ELF_LIBC5;
  428. } else {
  429. if (strcasecmp(t, "libc6") == 0) {
  430. expected_type = LIB_ELF_LIBC6;
  431. } else {
  432. if (strcasecmp(t, "libc0") == 0) {
  433. expected_type = LIB_ELF_LIBC0;
  434. } else {
  435. warnx("Unknown type field '%s' for dir '%s' - ignored", t, name);
  436. expected_type = LIB_ANY;
  437. }
  438. }
  439. }
  440. }
  441. }
  442. #endif
  443. /* let 'em know what's going on */
  444. if (verbose > 0)
  445. printf("%s:\n", name);
  446. /* get real path in case of chroot */
  447. if (!chroot_realpath(chroot_dir, name, realname))
  448. warn("can't resolve %s in chroot %s", name, chroot_dir);
  449. /* if we can't open it, we can't do anything */
  450. if ((dir = opendir(realname)) == NULL) {
  451. warn("skipping %s", name);
  452. free(path);
  453. return;
  454. }
  455. /* yes, we have to look at every single file */
  456. while ((ent = readdir(dir)) != NULL) {
  457. /* if it's not a shared library, don't bother */
  458. if ((so = is_shlib(name, ent->d_name, &libtype, &islink, expected_type)) == NULL)
  459. continue;
  460. /* have we already seen one with the same so name? */
  461. for (lp = libs; lp; lp = lp->next) {
  462. if (strcmp(so, lp->so) == 0) {
  463. /* we have, which one do we want to use? */
  464. if ((!islink && lp->islink) ||
  465. (islink == lp->islink &&
  466. libcmp(ent->d_name, lp->name) > 0)) {
  467. /* let's use the new one */
  468. free(lp->name);
  469. lp->name = xstrdup(ent->d_name);
  470. lp->libtype = libtype;
  471. lp->islink = islink;
  472. }
  473. break;
  474. }
  475. }
  476. /* congratulations, you're the first one we've seen */
  477. if (!lp) {
  478. lp = xmalloc(sizeof *lp);
  479. lp->so = xstrdup(so);
  480. lp->name = xstrdup(ent->d_name);
  481. lp->libtype = libtype;
  482. lp->islink = islink;
  483. lp->next = libs;
  484. libs = lp;
  485. }
  486. free(so);
  487. }
  488. /* don't need this any more */
  489. closedir(dir);
  490. /* now we have all the latest libs, update the links */
  491. for (lp = libs; lp; lp = lp->next) {
  492. if (!lp->islink)
  493. link_shlib(name, lp->name, lp->so);
  494. if (!nocache)
  495. cache_dolib(name, lp->so, lp->libtype);
  496. }
  497. /* always try to clean up after ourselves */
  498. while (libs) {
  499. lp = libs->next;
  500. free(libs->so);
  501. free(libs->name);
  502. free(libs);
  503. libs = lp;
  504. }
  505. free(path);
  506. return;
  507. }
  508. #ifndef __LDSO_CACHE_SUPPORT__
  509. void cache_print(void)
  510. {
  511. printf("Library cache disabled\n");
  512. }
  513. void cache_dolib(const char *dir, const char *so, int libtype)
  514. {
  515. return;
  516. }
  517. void cache_write(void)
  518. {
  519. return;
  520. }
  521. #else
  522. /* return the list of system-specific directories */
  523. char *get_extpath(void)
  524. {
  525. char *res = NULL, *cp;
  526. FILE *file;
  527. struct stat stat;
  528. char realconffile[BUFFER_SIZE];
  529. if (!chroot_realpath(chroot_dir, conffile, realconffile))
  530. return NULL;
  531. if ((file = fopen(realconffile, "r")) != NULL) {
  532. fstat(fileno(file), &stat);
  533. res = xmalloc(stat.st_size + 1);
  534. fread(res, 1, stat.st_size, file);
  535. fclose(file);
  536. res[stat.st_size] = '\0';
  537. /* convert comments fo spaces */
  538. for (cp = res; *cp; /*nada */ ) {
  539. if (*cp == '#') {
  540. do
  541. *cp++ = ' ';
  542. while (*cp && *cp != '\n');
  543. } else {
  544. cp++;
  545. }
  546. }
  547. }
  548. return res;
  549. }
  550. typedef struct liblist {
  551. int flags;
  552. int sooffset;
  553. int liboffset;
  554. char *soname;
  555. char *libname;
  556. struct liblist *next;
  557. } liblist_t;
  558. static header_t magic = { LDSO_CACHE_MAGIC, LDSO_CACHE_VER, 0 };
  559. static liblist_t *lib_head = NULL;
  560. static int liblistcomp(liblist_t *x, liblist_t *y)
  561. {
  562. int res;
  563. if ((res = libcmp(x->soname, y->soname)) == 0) {
  564. res = libcmp(strrchr(x->libname, '/') + 1,
  565. strrchr(y->libname, '/') + 1);
  566. }
  567. return res;
  568. }
  569. void cache_dolib(const char *dir, const char *so, int libtype)
  570. {
  571. char fullpath[PATH_MAX];
  572. liblist_t *new_lib, *cur_lib;
  573. magic.nlibs++;
  574. sprintf(fullpath, "%s/%s", dir, so);
  575. new_lib = xmalloc(sizeof(liblist_t));
  576. new_lib->flags = libtype;
  577. new_lib->soname = xstrdup(so);
  578. new_lib->libname = xstrdup(fullpath);
  579. if (lib_head == NULL || liblistcomp(new_lib, lib_head) > 0) {
  580. new_lib->next = lib_head;
  581. lib_head = new_lib;
  582. } else {
  583. for (cur_lib = lib_head; cur_lib->next != NULL &&
  584. liblistcomp(new_lib, cur_lib->next) <= 0;
  585. cur_lib = cur_lib->next)
  586. /* nothing */ ;
  587. new_lib->next = cur_lib->next;
  588. cur_lib->next = new_lib;
  589. }
  590. }
  591. void cache_write(void)
  592. {
  593. int cachefd;
  594. int stroffset = 0;
  595. char realcachefile[BUFFER_SIZE];
  596. char tempfile[BUFFER_SIZE];
  597. header_t swap_magic;
  598. header_t *magic_ptr;
  599. libentry_t swap_lib;
  600. libentry_t *lib_ptr;
  601. liblist_t *cur_lib;
  602. if (!magic.nlibs)
  603. return;
  604. if (!chroot_realpath(chroot_dir, cachefile, realcachefile))
  605. err(EXIT_FATAL, "can't resolve %s in chroot %s (%s)",
  606. cachefile, chroot_dir, strerror(errno));
  607. sprintf(tempfile, "%s~", realcachefile);
  608. if (unlink(tempfile) && errno != ENOENT)
  609. err(EXIT_FATAL, "can't unlink %s~ (%s)", cachefile,
  610. strerror(errno));
  611. if ((cachefd = creat(tempfile, 0644)) < 0)
  612. err(EXIT_FATAL, "can't create %s~ (%s)", cachefile,
  613. strerror(errno));
  614. if (byteswap) {
  615. swap_magic = magic;
  616. swap_magic.nlibs = bswap_32(swap_magic.nlibs);
  617. magic_ptr = &swap_magic;
  618. } else {
  619. magic_ptr = &magic;
  620. }
  621. if (write(cachefd, magic_ptr, sizeof(header_t)) != sizeof(header_t))
  622. err(EXIT_FATAL, "can't write %s~ (%s)", cachefile,
  623. strerror(errno));
  624. for (cur_lib = lib_head; cur_lib != NULL; cur_lib = cur_lib->next) {
  625. cur_lib->sooffset = stroffset;
  626. stroffset += strlen(cur_lib->soname) + 1;
  627. cur_lib->liboffset = stroffset;
  628. stroffset += strlen(cur_lib->libname) + 1;
  629. if (byteswap) {
  630. swap_lib.flags = bswap_32(cur_lib->flags);
  631. swap_lib.sooffset = bswap_32(cur_lib->sooffset);
  632. swap_lib.liboffset = bswap_32(cur_lib->liboffset);
  633. lib_ptr = &swap_lib;
  634. } else {
  635. lib_ptr = (libentry_t *) cur_lib;
  636. }
  637. if (write(cachefd, lib_ptr, sizeof(libentry_t)) !=
  638. sizeof(libentry_t))
  639. err(EXIT_FATAL, "can't write %s~ (%s)", cachefile,
  640. strerror(errno));
  641. }
  642. for (cur_lib = lib_head; cur_lib != NULL; cur_lib = cur_lib->next) {
  643. if ((size_t)write(cachefd, cur_lib->soname, strlen(cur_lib->soname) + 1)
  644. != strlen(cur_lib->soname) + 1)
  645. err(EXIT_FATAL, "can't write %s~ (%s)", cachefile,
  646. strerror(errno));
  647. if ((size_t)write(cachefd, cur_lib->libname, strlen(cur_lib->libname) + 1)
  648. != strlen(cur_lib->libname) + 1)
  649. err(EXIT_FATAL, "can't write %s~ (%s)", cachefile,
  650. strerror(errno));
  651. }
  652. if (close(cachefd))
  653. err(EXIT_FATAL, "can't close %s~ (%s)", cachefile,
  654. strerror(errno));
  655. if (chmod(tempfile, 0644))
  656. err(EXIT_FATAL, "can't chmod %s~ (%s)", cachefile,
  657. strerror(errno));
  658. if (rename(tempfile, realcachefile))
  659. err(EXIT_FATAL, "can't rename %s~ (%s)", cachefile,
  660. strerror(errno));
  661. }
  662. void cache_print(void)
  663. {
  664. caddr_t c;
  665. struct stat st;
  666. int fd = 0;
  667. char *strs;
  668. header_t *header;
  669. libentry_t *libent;
  670. char realcachefile[BUFFER_SIZE];
  671. if (!chroot_realpath(chroot_dir, cachefile, realcachefile))
  672. err(EXIT_FATAL, "can't resolve %s in chroot %s (%s)",
  673. cachefile, chroot_dir, strerror(errno));
  674. if (stat(realcachefile, &st) || (fd = open(realcachefile, O_RDONLY)) < 0)
  675. err(EXIT_FATAL, "can't read %s (%s)", cachefile, strerror(errno));
  676. c = mmap(0, st.st_size, PROT_READ, LDSO_CACHE_MMAP_FLAGS, fd, 0);
  677. if (c == MAP_FAILED)
  678. err(EXIT_FATAL, "can't map %s (%s)", cachefile, strerror(errno));
  679. close(fd);
  680. if (memcmp(((header_t *) c)->magic, LDSO_CACHE_MAGIC, LDSO_CACHE_MAGIC_LEN))
  681. err(EXIT_FATAL, "%s cache corrupt", cachefile);
  682. if (memcmp(((header_t *) c)->version, LDSO_CACHE_VER, LDSO_CACHE_VER_LEN))
  683. err(EXIT_FATAL, "wrong cache version - expected %s",
  684. LDSO_CACHE_VER);
  685. header = (header_t *) c;
  686. libent = (libentry_t *) (c + sizeof(header_t));
  687. strs = (char *)&libent[header->nlibs];
  688. printf("%d libs found in cache `%s' (version %s)\n",
  689. header->nlibs, cachefile, LDSO_CACHE_VER);
  690. for (fd = 0; fd < header->nlibs; fd++) {
  691. printf("\t%s ", strs + libent[fd].sooffset);
  692. switch (libent[fd].flags & ~LIB_ELF64) {
  693. case LIB_DLL:
  694. printf("(libc4)");
  695. break;
  696. case LIB_ELF:
  697. printf("(ELF%s)", libent[fd].flags & LIB_ELF64 ? "/64" : "");
  698. break;
  699. case LIB_ELF_LIBC0:
  700. printf("(libc0%s)", libent[fd].flags & LIB_ELF64 ? "/64" : "");
  701. break;
  702. case LIB_ELF_LIBC5:
  703. case LIB_ELF_LIBC6:
  704. printf("(libc%d%s)",
  705. (libent[fd].flags & ~LIB_ELF64) + 3,
  706. libent[fd].flags & LIB_ELF64 ? "/64" : "");
  707. break;
  708. default:
  709. printf("(unknown)");
  710. break;
  711. }
  712. printf(" => %s\n", strs + libent[fd].liboffset);
  713. }
  714. munmap(c, st.st_size);
  715. }
  716. #endif
  717. void usage(void)
  718. {
  719. fprintf(stderr,
  720. #ifdef __LDSO_CACHE_SUPPORT__
  721. "ldconfig - updates symlinks and cache for shared libraries\n\n"
  722. "Usage: ldconfig [-DvqnNX] [-f conf] [-C cache] [-r root] dir ...\n"
  723. " ldconfig -l [-Dv] lib ...\n"
  724. " ldconfig -p\n\nOptions:\n"
  725. #else
  726. "ldconfig - updates symlinks for shared libraries\n\n"
  727. "Usage: ldconfig [-DvqnX] [-r root] dir ...\n"
  728. " ldconfig -l [-Dv] lib ...\n\nOptions:\n"
  729. #endif
  730. "\t-D:\t\tdebug mode, don't update links\n"
  731. "\t-v:\t\tverbose mode, print things as we go\n"
  732. "\t-q:\t\tquiet mode, don't print warnings\n"
  733. "\t-n:\t\tdon't process standard directories\n"
  734. "\t-N:\t\tdon't update the library cache\n"
  735. "\t-X:\t\tdon't update the library links\n"
  736. "\t-l:\t\tlibrary mode, manually link libraries\n"
  737. "\t-p:\t\tprint the current library cache\n"
  738. #ifdef __LDSO_CACHE_SUPPORT__
  739. "\t-f conf :\tuse conf instead of %s\n"
  740. "\t-C cache:\tuse cache instead of %s\n"
  741. #endif
  742. "\t-r root :\tfirst, do a chroot to the indicated directory\n"
  743. "\tdir ... :\tdirectories to process\n"
  744. #ifdef __LDSO_CACHE_SUPPORT__
  745. "\tlib ... :\tlibraries to link\n\n", LDSO_CONF, LDSO_CACHE
  746. #else
  747. "\tlib ... :\tlibraries to link\n\n"
  748. #endif
  749. );
  750. exit(EXIT_FATAL);
  751. }
  752. #define DIR_SEP ":, \t\n"
  753. int main(int argc, char **argv)
  754. {
  755. int i, c;
  756. int nodefault = 0;
  757. char *cp, *dir, *so;
  758. int libtype, islink;
  759. int printcache = 0;
  760. #ifdef __LDSO_CACHE_SUPPORT__
  761. char *extpath;
  762. #endif
  763. prog = argv[0];
  764. opterr = 0;
  765. while ((c = getopt(argc, argv, "DvqnNXlpf:C:r:")) != EOF)
  766. switch (c) {
  767. case 'D':
  768. debug = 1; /* debug mode */
  769. nocache = 1;
  770. nolinks = 1;
  771. verbose = 1;
  772. break;
  773. case 'v':
  774. verbose = 1; /* verbose mode */
  775. break;
  776. case 'q':
  777. if (verbose <= 0)
  778. verbose = -1; /* quiet mode */
  779. break;
  780. case 'n':
  781. nodefault = 1; /* no default dirs */
  782. nocache = 1;
  783. break;
  784. case 'N':
  785. nocache = 1; /* don't build cache */
  786. break;
  787. case 'X':
  788. nolinks = 1; /* don't update links */
  789. break;
  790. case 'l':
  791. libmode = 1; /* library mode */
  792. break;
  793. case 'p':
  794. printcache = 1; /* print cache */
  795. break;
  796. case 'f':
  797. #ifdef __LDSO_CACHE_SUPPORT__
  798. conffile = optarg; /* alternate conf file */
  799. #endif
  800. break;
  801. case 'C':
  802. #ifdef __LDSO_CACHE_SUPPORT__
  803. cachefile = optarg; /* alternate cache file */
  804. #endif
  805. break;
  806. case 'r':
  807. chroot_dir = optarg;
  808. break;
  809. default:
  810. usage();
  811. break;
  812. /* THE REST OF THESE ARE UNDOCUMENTED AND MAY BE REMOVED
  813. IN FUTURE VERSIONS. */
  814. }
  815. if (chroot_dir && *chroot_dir) {
  816. if (chroot(chroot_dir) < 0) {
  817. if (chdir(chroot_dir) < 0)
  818. err(EXIT_FATAL, "couldn't chroot to %s (%s)", chroot_dir, strerror(errno));
  819. chroot_dir = ".";
  820. } else {
  821. if (chdir("/") < 0)
  822. err(EXIT_FATAL, "couldn't chdir to / (%s)", strerror(errno));
  823. chroot_dir = NULL;
  824. }
  825. }
  826. /* allow me to introduce myself, hi, my name is ... */
  827. if (verbose > 0)
  828. printf("%s: uClibc version\n", argv[0]);
  829. if (printcache) {
  830. /* print the cache -- don't you trust me? */
  831. cache_print();
  832. exit(EXIT_OK);
  833. } else if (libmode) {
  834. /* so you want to do things manually, eh? */
  835. /* ok, if you're so smart, which libraries do we link? */
  836. for (i = optind; i < argc; i++) {
  837. /* split into directory and file parts */
  838. if (!(cp = strrchr(argv[i], '/'))) {
  839. dir = "."; /* no dir, only a filename */
  840. cp = argv[i];
  841. } else {
  842. if (cp == argv[i])
  843. dir = "/"; /* file in root directory */
  844. else
  845. dir = argv[i];
  846. *cp++ = '\0'; /* neither of the above */
  847. }
  848. /* we'd better do a little bit of checking */
  849. if ((so = is_shlib(dir, cp, &libtype, &islink, LIB_ANY)) == NULL)
  850. err(EXIT_FATAL, "%s%s%s is not a shared library",
  851. dir, (*dir && strcmp(dir, "/")) ? "/" : "", cp);
  852. /* so far, so good, maybe he knows what he's doing */
  853. link_shlib(dir, cp, so);
  854. }
  855. } else {
  856. /* the lazy bum want's us to do all the work for him */
  857. /* don't cache dirs on the command line */
  858. int nocache_save = nocache;
  859. nocache = 1;
  860. /* OK, which directories should we do? */
  861. for (i = optind; i < argc; i++)
  862. scan_dir(argv[i]);
  863. /* restore the desired caching state */
  864. nocache = nocache_save;
  865. /* look ma, no defaults */
  866. if (!nodefault) {
  867. scan_dir(UCLIBC_RUNTIME_PREFIX "lib");
  868. scan_dir(UCLIBC_RUNTIME_PREFIX "usr/lib");
  869. #ifndef __LDSO_CACHE_SUPPORT__
  870. scan_dir(UCLIBC_RUNTIME_PREFIX "usr/X11R6/lib");
  871. #else
  872. /* I guess the defaults aren't good enough */
  873. if ((extpath = get_extpath())) {
  874. for (cp = strtok(extpath, DIR_SEP); cp; cp = strtok(NULL, DIR_SEP)) {
  875. /* strip trailing slashes */
  876. int len = strlen(cp);
  877. if (len)
  878. while (cp[--len] == '/' && len)
  879. cp[len] = 0;
  880. /* we do the redundancy check only if cache usage is enabled */
  881. if (strcmp(UCLIBC_RUNTIME_PREFIX "lib", cp) == 0
  882. || strcmp(UCLIBC_RUNTIME_PREFIX "usr/lib", cp) == 0) {
  883. if (verbose >= 0)
  884. warnx("You should remove `%s' from `%s'", cp, LDSO_CONF);
  885. continue;
  886. }
  887. scan_dir(cp);
  888. }
  889. free(extpath);
  890. }
  891. #endif
  892. }
  893. if (!nocache)
  894. cache_write();
  895. }
  896. exit(EXIT_OK);
  897. }