diff -up rpm-4.6.1/build/rpmfc.c.devel-autodep rpm-4.6.1/build/rpmfc.c --- rpm-4.6.1/build/rpmfc.c.devel-autodep 2009-05-08 15:15:16.000000000 +0300 +++ rpm-4.6.1/build/rpmfc.c 2009-05-18 14:15:47.000000000 +0300 @@ -506,7 +506,7 @@ static const struct rpmfcTokens_s const { "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 }, @@ -667,6 +667,105 @@ rpmds rpmfcRequires(rpmfc fc) /** + * 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 (fc->skipReq) + return 0; + + 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 = 0; + int i, cnt; + char * soname = NULL; + 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; + +/* alpha uses /lib, not /lib64 so don't add (64bit) deps */ +#if !defined(__alpha__) + isElf64 = ehdr->e_ident[EI_CLASS] == ELFCLASS64; +#endif + + 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; + GElf_Shdr *shdr; + + if (phdr == NULL || phdr->p_type != PT_DYNAMIC) + continue; + + scn = gelf_offscn(elf, phdr->p_offset); + shdr = gelf_getshdr(scn, &shdr_mem); + + if (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); + char *depname = NULL; + + 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; + + rasprintf(&depname, "%s%s", soname, isElf64 ? "()(64bit)" : ""); + /* Add to package dependencies. */ + ds = rpmdsSingle(RPMTAG_REQUIRENAME, depname, "", + RPMSENSE_FIND_REQUIRES); + free(depname); + + rpmdsMerge(&fc->requires, ds); + rpmfcAddFileDep(&fc->ddict, 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 @@ -1097,6 +1196,7 @@ static const struct rpmfcApplyTbl_s cons { rpmfcSCRIPT, (RPMFC_SCRIPT|RPMFC_BOURNE| RPMFC_PERL|RPMFC_PYTHON|RPMFC_MONO| RPMFC_PKGCONFIG|RPMFC_LIBTOOL) }, + { rpmfcSYMLINK, RPMFC_SYMLINK }, { NULL, 0 } }; @@ -1117,6 +1217,7 @@ rpmRC rpmfcApply(rpmfc fc) int ix; int i; int xx; + int skipping = 0; /* Generate package and per-file dependencies. */ for (fc->ix = 0; fc->fn[fc->ix] != NULL; fc->ix++) { @@ -1171,11 +1272,13 @@ rpmRC rpmfcApply(rpmfc fc) default: break; case 'P': + skipping = fc->skipProv; ds = rpmdsSingle(RPMTAG_PROVIDENAME, N, EVR, Flags); dix = rpmdsFind(fc->provides, ds); ds = rpmdsFree(ds); break; case 'R': + skipping = fc->skipReq; ds = rpmdsSingle(RPMTAG_REQUIRENAME, N, EVR, Flags); dix = rpmdsFind(fc->requires, ds); ds = rpmdsFree(ds); @@ -1197,7 +1300,7 @@ assert(dix >= 0); previx = ix; xx = argiAdd(&fc->fddictx, ix, argiCount(fc->ddictx)-1); } - if (fc->fddictn && fc->fddictn->vals) + if (fc->fddictn && fc->fddictn->vals && !skipping) fc->fddictn->vals[ix]++; }