RPM Package Manager, CVS Repository http://rpm5.org/cvs/ ____________________________________________________________________________
Server: rpm5.org Name: Per Øyvind Karlsen Root: /v/rpm/cvs Email: pkarl...@rpm5.org Module: rpm Date: 10-Apr-2011 07:25:07 Branch: rpm-5_3 Handle: 2011041005250501 Modified files: (Branch: rpm-5_3) rpm CHANGES rpm/lib librpm.vers rpmds.c rpmds.h rpmfc.c Log: implement devel(libfoo) symlink dependencies from Mandriva, but with proper ELF SONAME checking Summary: Revision Changes Path 1.3296.2.204+2 -0 rpm/CHANGES 1.76.2.2 +1 -0 rpm/lib/librpm.vers 2.167.2.6 +171 -12 rpm/lib/rpmds.c 2.81.2.1 +13 -0 rpm/lib/rpmds.h 1.73.2.5 +17 -1 rpm/lib/rpmfc.c ____________________________________________________________________________ patch -p0 <<'@@ .' Index: rpm/CHANGES ============================================================================ $ cvs diff -u -r1.3296.2.203 -r1.3296.2.204 CHANGES --- rpm/CHANGES 9 Apr 2011 23:11:21 -0000 1.3296.2.203 +++ rpm/CHANGES 10 Apr 2011 05:25:05 -0000 1.3296.2.204 @@ -1,4 +1,6 @@ 5.3.10 -> 5.3.11 + - proyvind: rpmds: implement devel(libfoo) symlink dependencies from + Mandriva, but with proper ELF SONAME checking. - jbj: add a --nofsync popt alias (caveat: experimental & risky). - jbj: checksig: check explictly for per-item failures after iterating. - jbj: build: fix: resurrect %description -l XY yet again. @@ . patch -p0 <<'@@ .' Index: rpm/lib/librpm.vers ============================================================================ $ cvs diff -u -r1.76.2.1 -r1.76.2.2 librpm.vers --- rpm/lib/librpm.vers 27 Sep 2010 23:34:50 -0000 1.76.2.1 +++ rpm/lib/librpm.vers 10 Apr 2011 05:25:06 -0000 1.76.2.2 @@ -125,6 +125,7 @@ rpmdsSetRefs; rpmdsSetResult; rpmdsSingle; + rpmdsSymlink; rpmdsSysinfo; rpmdsTagN; rpmdsThis; @@ . patch -p0 <<'@@ .' Index: rpm/lib/rpmds.c ============================================================================ $ cvs diff -u -r2.167.2.5 -r2.167.2.6 rpmds.c --- rpm/lib/rpmds.c 25 Jan 2011 14:48:10 -0000 2.167.2.5 +++ rpm/lib/rpmds.c 10 Apr 2011 05:25:06 -0000 2.167.2.6 @@ -2891,19 +2891,37 @@ * @param isElf64 is this an ELF64 symbol? */ #if defined(HAVE_GELF_H) && defined(HAVE_LIBELF) && !defined(__FreeBSD__) -static char * sonameDep(/*@returned@*/ char * t, const char * s, int isElf64) +static char * sonameDep(/*@returned@*/ char * t, const char * s, int isElf64, int devel) /*@modifies t @*/ { + char *tmp = t; *t = '\0'; + if (devel) { + tmp = stpcpy(t, "devel("); + } #if !defined(__alpha__) && !defined(__sun) - if (isElf64) { - if (s[strlen(s)-1] != ')') - (void) stpcpy( stpcpy(t, s), "()(64bit)"); - else - (void) stpcpy( stpcpy(t, s), "(64bit)"); + if (!isElf64) { + /* XXX: eehhk, would've been nice with consistency, mandriva legacy... :| */ + if (!devel && s[strlen(s)-1] != ')') + (void) stpcpy( stpcpy(tmp, s), "()(64bit)"); + else { + char *suffix; + tmp = stpcpy(tmp, s); + if (devel && (suffix = strstr(t, ".so"))) + tmp = suffix; + tmp = stpcpy(tmp, "(64bit)"); + } }else #endif - (void) stpcpy(t, s); + tmp = stpcpy(tmp, s); + if (devel) { + char *suffix; + tmp = stpcpy(tmp, s); + if (devel && (suffix = strstr(t, ".so"))) + tmp = suffix; + (void) stpcpy(tmp, ")"); + } + return t; } #endif @@ -3075,7 +3093,7 @@ /* Add next provide dependency. */ ds = rpmdsSingle(RPMTAG_PROVIDES, - sonameDep(t, buf, isElf64), + sonameDep(t, buf, isElf64, 0), "", RPMSENSE_FIND_PROVIDES); xx = add(context, ds); (void)rpmdsFree(ds); @@ -3128,7 +3146,7 @@ /* Add next require dependency. */ ds = rpmdsSingle(RPMTAG_REQUIRENAME, - sonameDep(t, buf, isElf64), + sonameDep(t, buf, isElf64, 0), "", RPMSENSE_FIND_REQUIRES); xx = add(context, ds); (void)rpmdsFree(ds); @@ -3170,7 +3188,7 @@ assert(s != NULL); buf[0] = '\0'; ds = rpmdsSingle(RPMTAG_REQUIRENAME, - sonameDep(buf, s, isElf64), + sonameDep(buf, s, isElf64, 0), "", RPMSENSE_FIND_REQUIRES); xx = add(context, ds); (void)rpmdsFree(ds); @@ -3185,7 +3203,7 @@ /* Add next provide dependency. */ buf[0] = '\0'; ds = rpmdsSingle(RPMTAG_PROVIDENAME, - sonameDep(buf, s, isElf64), + sonameDep(buf, s, isElf64, 0), "", RPMSENSE_FIND_PROVIDES); xx = add(context, ds); (void)rpmdsFree(ds); @@ -3221,7 +3239,7 @@ /* Add next provide dependency. */ buf[0] = '\0'; ds = rpmdsSingle(RPMTAG_PROVIDENAME, - sonameDep(buf, s, isElf64), "", RPMSENSE_FIND_PROVIDES); + sonameDep(buf, s, isElf64, 0), "", RPMSENSE_FIND_PROVIDES); xx = add(context, ds); (void)rpmdsFree(ds); ds = NULL; @@ -3239,6 +3257,147 @@ } /*@=moduncon =noeffectuncon @*/ + +int rpmdsSymlink(const char * fn, int flags, + int (*add) (void * context, rpmds ds), void * context) +{ +#if defined(HAVE_GELF_H) && defined(HAVE_LIBELF) && !defined(__FreeBSD__) + Elf * elf; + Elf_Scn * scn; + Elf_Data * data; + GElf_Ehdr ehdr_mem, * ehdr; + GElf_Shdr shdr_mem, * shdr; + GElf_Dyn dyn_mem, * dyn; + int fdno; + int cnt; + int i; + char buf[BUFSIZ]; + const char * s; + int is_executable; + const char * soname = NULL; + rpmds ds; + int xx; + int isElf64; + int gotSONAME = 0; + int skipP = (flags & RPMELF_FLAG_SKIPPROVIDES); + int skipR = (flags & RPMELF_FLAG_SKIPREQUIRES); + int lnklen; + char path[MAXPATHLEN]; + ARGV_t deps = NULL; + + if ((lnklen = readlink(fn, path, MAXPATHLEN - 1)) == -1) { + warn("%s", fn); + return RPMRC_FAIL; + } + path[lnklen] = '\0'; + +/*@-castfcnptr@*/ +if (_rpmds_debug < 0) +fprintf(stderr, "*** rpmdsELF(%s, %d, %p, %p)\n", fn, flags, (void *)add, context); +/*@=castfcnptr@*/ + + /* Extract dependencies only from files with executable bit set. */ + { struct stat sb, * st = &sb; + if (lstat(fn, st) != 0) + return -1; + is_executable = (int)(st->st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)); + } + + fdno = open(fn, O_RDONLY); + if (fdno < 0) + return fdno; + + (void) elf_version(EV_CURRENT); + +/*@-evalorder@*/ + elf = NULL; + if ((elf = elf_begin (fdno, ELF_C_READ, NULL)) == NULL + || elf_kind(elf) != ELF_K_ELF + || (ehdr = gelf_getehdr(elf, &ehdr_mem)) == NULL + || !(ehdr->e_type == ET_DYN || ehdr->e_type == ET_EXEC)) + goto exit; +/*@=evalorder@*/ + + isElf64 = ehdr->e_ident[EI_CLASS] == ELFCLASS64; + + /*@-uniondef @*/ + scn = NULL; + while ((scn = elf_nextscn(elf, scn)) != NULL) { + shdr = gelf_getshdr(scn, &shdr_mem); + if (shdr == NULL) + break; + + soname = _free(soname); + switch (shdr->sh_type) { + default: + continue; + /*@notreached@*/ /*@switchbreak@*/ break; + case SHT_DYNAMIC: + data = NULL; + while ((data = elf_getdata (scn, data)) != NULL) { + for (cnt = 0; cnt < (int)(shdr->sh_size / shdr->sh_entsize); ++cnt) { + dyn = gelf_getdyn (data, cnt, &dyn_mem); + if (dyn == NULL) + /*@innerbreak@*/ break; + s = NULL; + switch (dyn->d_tag) { + default: + /*@innercontinue@*/ continue; + /*@notreached@*/ /*@switchbreak@*/ break; + case DT_NEEDED: + /* Only from files with executable bit set. */ + if (skipR || !is_executable) + /*@innercontinue@*/ continue; + /* Add next require dependency. */ + s = elf_strptr(elf, shdr->sh_link, dyn->d_un.d_val); +assert(s != NULL); + buf[0] = '\0'; + argvAdd(&deps, s); + /*@switchbreak@*/ break; + case DT_SONAME: + gotSONAME = 1; + s = elf_strptr(elf, shdr->sh_link, dyn->d_un.d_val); +assert(s != NULL); + /* Add next provide dependency. */ + buf[0] = '\0'; + if (!skipP) { + ds = rpmdsSingle(RPMTAG_PROVIDENAME, + sonameDep(buf, s, isElf64, 1), + "", RPMSENSE_FIND_PROVIDES); + xx = add(context, ds); + (void)rpmdsFree(ds); + ds = NULL; + } + /*@switchbreak@*/ break; + } + } + } + /*@switchbreak@*/ break; + } + } + /*@=uniondef @*/ + +exit: + if (gotSONAME) + for (i = 0, cnt = argvCount(deps); i < cnt; i++) { + ds = rpmdsSingle(RPMTAG_REQUIRENAME, + sonameDep(buf, deps[i], isElf64, 1), + "", RPMSENSE_FIND_REQUIRES); + xx = add(context, ds); + (void)rpmdsFree(ds); + ds = NULL; + } + + deps = argvFree(deps); + if (elf) (void) elf_end(elf); + if (fdno > 0) + xx = close(fdno); + return 0; +#else + return -1; +#endif +} + #define _SBIN_LDCONFIG_P "/sbin/ldconfig -p" /*@unchecked@*/ /*@observer@*/ /*@owned@*/ /*@relnull@*/ static const char * _ldconfig_cmd = _SBIN_LDCONFIG_P; @@ . patch -p0 <<'@@ .' Index: rpm/lib/rpmds.h ============================================================================ $ cvs diff -u -r2.81 -r2.81.2.1 rpmds.h --- rpm/lib/rpmds.h 6 Mar 2010 15:31:29 -0000 2.81 +++ rpm/lib/rpmds.h 10 Apr 2011 05:25:06 -0000 2.81.2.1 @@ -616,6 +616,19 @@ #define RPMELF_FLAG_SKIPREQUIRES 0x2 /*<! rpmdsELF: skip requires */ /** \ingroup rpmds + * Extract dependencies from a symlink. + * @param fn file name + * @param flags 1: skip provides 2: skip requires + * @param *add add(arg, ds) saves next provide/require symlink dependency. + * @param context add() callback context + * @return 0 on success + */ +int rpmdsSymlink(const char * fn, int flags, + int (*add) (void * context, rpmds ds), void * context) + /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ + /*@modifies rpmGlobalMacroContext, fileSystem, internalState @*/; + +/** \ingroup rpmds * Load /etc/ld.so.cache provides into a dependency set. * @todo Add dependency colors, and attach to file. * @retval *PRCO provides/requires/conflicts/obsoletes depedency set(s) @@ . patch -p0 <<'@@ .' Index: rpm/lib/rpmfc.c ============================================================================ $ cvs diff -u -r1.73.2.4 -r1.73.2.5 rpmfc.c --- rpm/lib/rpmfc.c 1 Apr 2011 12:27:57 -0000 1.73.2.4 +++ rpm/lib/rpmfc.c 10 Apr 2011 05:25:06 -0000 1.73.2.5 @@ -987,6 +987,21 @@ return rpmdsELF(fn, flags, rpmfcMergePR, fc); } +static int rpmfcSYMLINK(rpmfc fc) + /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ + /*@modifies rpmGlobalMacroContext, fileSystem, internalState @*/ +{ + const char * fn = fc->fn[fc->ix]; + int flags = 0; + + if (fc->skipProv) + flags |= RPMELF_FLAG_SKIPPROVIDES; + if (fc->skipReq) + flags |= RPMELF_FLAG_SKIPREQUIRES; + + return rpmdsSymlink(fn, flags, rpmfcMergePR, fc); +} + typedef struct rpmfcApplyTbl_s { int (*func) (rpmfc fc); int colormask; @@ -999,7 +1014,8 @@ /*@unchecked@*/ static struct rpmfcApplyTbl_s rpmfcApplyTable[] = { { rpmfcELF, RPMFC_ELF }, - { rpmfcSCRIPT, (RPMFC_SCRIPT|RPMFC_PERL|RPMFC_PYTHON|RPMFC_LIBTOOL|RPMFC_PKGCONFIG|RPMFC_BOURNE|RPMFC_JAVA|RPMFC_PHP|RPMFC_MONO|RPMFC_RUBY) }, + { rpmfcSCRIPT, (RPMFC_SCRIPT|RPMFC_PERL|RPMFC_PYTHON|RPMFC_LIBTOOL|RPMFC_PKGCONFIG|RPMFC_BOURNE|RPMFC_JAVA|RPMFC_PHP|RPMFC_MONO) }, + { rpmfcSYMLINK, RPMFC_SYMLINK }, { NULL, 0 } }; /*@=nullassign@*/ @@ . ______________________________________________________________________ RPM Package Manager http://rpm5.org CVS Sources Repository rpm-cvs@rpm5.org