diff -up rpm-4.4.2.2/build/rpmfc.c.develdeps rpm-4.4.2.2/build/rpmfc.c --- rpm-4.4.2.2/build/rpmfc.c.develdeps 2007-09-11 09:28:12.000000000 +0300 +++ rpm-4.4.2.2/build/rpmfc.c 2007-12-21 14:22:55.000000000 +0200 @@ -497,7 +497,7 @@ static struct rpmfcTokens_s rpmfcTokens[ { "ASCII text", RPMFC_WHITE|RPMFC_INCLUDE }, { "ISO-8859 text", RPMFC_WHITE|RPMFC_INCLUDE }, - { "symbolic link to", RPMFC_SYMLINK }, + { "symbolic link to", RPMFC_SYMLINK|RPMFC_INCLUDE }, { "socket", RPMFC_DEVICE }, { "special", RPMFC_DEVICE }, @@ -647,6 +647,109 @@ rpmfc rpmfcNew(void) } /** + * Ensure that symlinks for shared libs generate a dep on the shared lib + * @param fc file classifier + * @return 0 on success + */ +static int rpmfcSYMLINK(rpmfc fc) +{ + const char * fn = fc->fn[fc->ix]; + struct stat sb; + int fdno; + + if (stat(fn, &sb) < 0) + return -1; + if (S_ISLNK(sb.st_mode)) + return -1; + + fdno = open(fn, O_RDONLY); + if (fdno < 0) { + return fdno; + } + +#if HAVE_GELF_H && HAVE_LIBELF + Elf * elf = NULL; + GElf_Ehdr ehdr_mem, * ehdr; + int isElf64; + int i, cnt; + char * soname = NULL; + char buf[BUFSIZ]; + char * t; + rpmds ds; + + (void) elf_version(EV_CURRENT); + elf = NULL; + if ((elf = elf_begin (fdno, ELF_C_READ_MMAP, NULL)) == NULL + || elf_kind(elf) != ELF_K_ELF + || (ehdr = gelf_getehdr(elf, &ehdr_mem)) == NULL + || ehdr->e_type != ET_DYN) + goto exit; + + isElf64 = ehdr->e_ident[EI_CLASS] == ELFCLASS64; + + for (i = 0; i < ehdr->e_phnum; ++i) { + GElf_Phdr phdr_mem; + GElf_Phdr *phdr = gelf_getphdr (elf, i, &phdr_mem); + GElf_Shdr shdr_mem; + Elf_Data * data = NULL; + Elf_Scn * scn = NULL; + GElf_Shdr *shdr = NULL; + + if (phdr == NULL || phdr->p_type != PT_DYNAMIC) + continue; + + while ((scn = elf_nextscn(elf, scn)) != NULL) { + shdr = gelf_getshdr(scn, &shdr_mem); + if (shdr->sh_offset == phdr->p_offset) + break; + } + + scn = gelf_offscn(elf, phdr->p_offset); + shdr = gelf_getshdr(scn, &shdr_mem); + + if (scn != NULL && shdr != NULL && shdr->sh_type == SHT_DYNAMIC) + data = elf_getdata (scn, NULL); + if (data == NULL) + continue; + + for (cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt) { + GElf_Dyn dynmem; + GElf_Dyn *dyn = gelf_getdyn (data, cnt, &dynmem); + if (dyn == NULL) + break; + if (dyn->d_tag != DT_SONAME) + continue; + + /* add the soname to package deps */ + soname = elf_strptr(elf, shdr->sh_link, dyn->d_un.d_val); + if (soname == NULL) + break; + buf[0] = '\0'; + t = buf; + t = stpcpy(t, soname); +#if !defined(__alpha__) + if (isElf64) + t = stpcpy(t, "()(64bit)"); +#endif + t++; + /* Add to package dependencies. */ + ds = rpmdsSingle(RPMTAG_REQUIRENAME, + buf, "", RPMSENSE_FIND_REQUIRES); + rpmdsMerge(&fc->requires, ds); + rpmfcSaveArg(&fc->ddict, rpmfcFileDep(t, fc->ix, ds)); + ds = rpmdsFree(ds); + break; + } + } +exit: + if (elf) (void) elf_end(elf); + close(fdno); + return 0; +#endif + return -1; +} + +/** * Extract script dependencies. * @param fc file classifier * @return 0 on success @@ -1094,6 +1197,7 @@ static struct rpmfcApplyTbl_s rpmfcApply { rpmfcSCRIPT, (RPMFC_SCRIPT|RPMFC_PERL) }, { rpmfcSCRIPT, (RPMFC_SCRIPT|RPMFC_PYTHON) }, { rpmfcSCRIPT, RPMFC_MONO }, + { rpmfcSYMLINK, RPMFC_SYMLINK }, { NULL, 0 } };