+ cp = cp + strlen(cp);
+
+ /* construct the full path name */
+ sprintf(buff, "%s%s%s", dir, (*dir && strcmp(dir, "/")) ? "/" : "", name);
+
+ /* get real path in case of chroot */
+ if (!chroot_realpath(chroot_dir, buff, real))
+ warn("can't resolve %s in chroot %s", buff, chroot_dir);
+
+ /* first, make sure it's a regular file */
+ if (lstat(real, &statbuf))
+ warn("skipping %s", buff);
+ else if (!S_ISREG(statbuf.st_mode) && !S_ISLNK(statbuf.st_mode))
+ warnx("%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(real, "rb")))
+ warn("skipping %s", buff);
+ else {
+ /* now make sure it's a shared library */
+ if (fread(&exec, sizeof exec, 1, file) < 1)
+ warnx("can't read header from %s, skipping", buff);
+ else if (N_MAGIC(exec) != ZMAGIC
+ && N_MAGIC(exec) != QMAGIC
+ && N_MAGIC_SWAP(exec) != ZMAGIC
+ && N_MAGIC_SWAP(exec) != QMAGIC) {
+ elf_hdr = (ElfW(Ehdr) *) & exec;
+ if (elf_hdr->e_ident[0] != 0x7f ||
+ strncmp((char *)elf_hdr->e_ident + 1, "ELF", 3) != 0)
+ {
+ /* silently ignore linker scripts */
+ if (strncmp((char *)&exec, "/* GNU ld", 9) != 0)
+ warnx("%s is not a shared library, skipping", buff);
+ } else {
+ /* always call readsoname to update type */
+ if (expected_type == LIB_DLL) {
+ warnx("%s is not an a.out library, it's ELF!", buff);
+ expected_type = LIB_ANY;
+ }
+ *type = LIB_ELF;
+ good = readsoname(buff, file, expected_type, type,
+ elf_hdr->e_ident[EI_CLASS]);
+ if (byteswapflag == -1)
+ /* byte-order detected */
+ byteswapflag = byteswap;
+ 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] != '.')))
+ warnx("%s has inconsistent soname (%s)", buff, good);
+ }
+ }
+ } else {
+ /* Determine byte-order */
+ byteswap = (N_MAGIC(exec) == ZMAGIC || N_MAGIC(exec) == QMAGIC) ? 0 : 1;
+ if (byteswapflag == -1)
+ /* byte-order detected */
+ byteswapflag = byteswap;
+
+ 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) {
+ warnx("%s is not an ELF library, its an a.out DLL!", buff);
+ expected_type = LIB_ANY;
+ }
+
+ *type = LIB_DLL;
+ }
+ fclose(file);
+
+ if (byteswapflag >= 0 && byteswap != byteswapflag) {
+ byteswapflag = -2;
+ warnx("mixed byte-order detected, using host byte-order...");
+ }
+ if (byteswapflag == -2)
+ byteswap = 0;
+ }