I knew I'd seen this symlink patch before: https://lists.dulug.duke.edu/pipermail/rpm-devel/2006-April/001037.html
I did not like the patch the first time, and I don't like it 5 years later. I will rework the issue under #if RPM_VENDOR_MANDRIVA across the board. Note that the rule (already implemented except you've turned it off) All symlinks depend on their end-point. not only covers the special case of ELF libraries (when the symlink is explicitly "owned" by a package), but all other cases of symlinks to end-points in other packages. Yes you will need to teach URPMI and other depsolvers about symlink end-points constructed from RPMTAG_FILELINKTOS data, very not hard. The only remaining "feature" is the explicit Requires: devel(whatever) added to metadata. I fully realize the difficulties of transitive closure in "dependency hell", but hey, lets not go around in circles all over again. Note that the rule I've stated requires zero additional metadata, the linkto dependency is constructed on the install box from the symlink end-points that are already in metadata (but you're likely choosing to disable that functionality some 4? 5? years after being implemented). hth 73 de Jeff On Apr 10, 2011, at 1:23 AM, Per Øyvind Karlsen wrote: > 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:23:26 > Branch: HEAD Handle: 2011041005232500 > > Modified files: > 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.3607 +2 -0 rpm/CHANGES > 1.78 +1 -0 rpm/lib/librpm.vers > 2.173 +171 -12 rpm/lib/rpmds.c > 2.82 +13 -0 rpm/lib/rpmds.h > 1.80 +17 -1 rpm/lib/rpmfc.c > ____________________________________________________________________________ > > patch -p0 <<'@@ .' > Index: rpm/CHANGES > ============================================================================ > $ cvs diff -u -r1.3606 -r1.3607 CHANGES > --- rpm/CHANGES 8 Apr 2011 16:14:15 -0000 1.3606 > +++ rpm/CHANGES 10 Apr 2011 05:23:25 -0000 1.3607 > @@ -1,4 +1,6 @@ > 5.4.0 -> 5.4.1: > + - proyvind: rpmds: implement devel(libfoo) symlink dependencies from > + Mandriva, but with proper ELF SONAME checking. > - jbj: mongo: stub-in a /usr/lib/rpm/bin mongo shell wrapper. > - jbj: spewage: fix: rework sql/json markup to use the EVRD parser. > - jbj: build: fix: resurrect %description -l XY yet again. > @@ . > patch -p0 <<'@@ .' > Index: rpm/lib/librpm.vers > ============================================================================ > $ cvs diff -u -r1.77 -r1.78 librpm.vers > --- rpm/lib/librpm.vers 27 Sep 2010 23:12:48 -0000 1.77 > +++ rpm/lib/librpm.vers 10 Apr 2011 05:23:25 -0000 1.78 > @@ -125,6 +125,7 @@ > rpmdsSetRefs; > rpmdsSetResult; > rpmdsSingle; > + rpmdsSymlink; > rpmdsSysinfo; > rpmdsTagN; > rpmdsThis; > @@ . > patch -p0 <<'@@ .' > Index: rpm/lib/rpmds.c > ============================================================================ > $ cvs diff -u -r2.172 -r2.173 rpmds.c > --- rpm/lib/rpmds.c 25 Jan 2011 14:47:14 -0000 2.172 > +++ rpm/lib/rpmds.c 10 Apr 2011 05:23:25 -0000 2.173 > @@ -2890,19 +2890,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 > @@ -3074,7 +3092,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); > @@ -3127,7 +3145,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); > @@ -3169,7 +3187,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); > @@ -3184,7 +3202,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); > @@ -3220,7 +3238,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; > @@ -3238,6 +3256,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.82 rpmds.h > --- rpm/lib/rpmds.h 6 Mar 2010 15:31:29 -0000 2.81 > +++ rpm/lib/rpmds.h 10 Apr 2011 05:23:25 -0000 2.82 > @@ -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.79 -r1.80 rpmfc.c > --- rpm/lib/rpmfc.c 1 Apr 2011 12:27:28 -0000 1.79 > +++ rpm/lib/rpmfc.c 10 Apr 2011 05:23:25 -0000 1.80 > @@ -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-...@rpm5.org
smime.p7s
Description: S/MIME cryptographic signature