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

Reply via email to