| diff --git a/build/rpmfc.c b/build/rpmfc.c |
| index 3cc2d6d..84d1e8a 100644 |
| |
| |
| @@ -522,7 +522,7 @@ static const struct rpmfcTokens_s const 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 }, |
| |
| @@ -683,6 +683,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 |
| @@ -1115,6 +1214,7 @@ static const struct rpmfcApplyTbl_s const rpmfcApplyTable[] = { |
| { rpmfcSCRIPT, (RPMFC_SCRIPT|RPMFC_PKGCONFIG) }, |
| { rpmfcSCRIPT, (RPMFC_SCRIPT|RPMFC_LIBTOOL) }, |
| { rpmfcSCRIPT, RPMFC_MONO }, |
| + { rpmfcSYMLINK, RPMFC_SYMLINK }, |
| { NULL, 0 } |
| }; |
| |
| @@ -1135,6 +1235,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++) { |
| @@ -1185,11 +1286,13 @@ assert(se != NULL); |
| 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); |
| @@ -1211,7 +1314,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]++; |
| } |
| |