Disable use if rpm-4.4 legacy interface (dropped in 4.9) (bnc#691089)
authorMichael Andres <ma@suse.de>
Fri, 20 May 2011 11:39:27 +0000 (13:39 +0200)
committerMichael Andres <ma@suse.de>
Fri, 20 May 2011 11:41:43 +0000 (13:41 +0200)
CMakeLists.txt
zypp/target/rpm/BinHeader.cc
zypp/target/rpm/BinHeader.h
zypp/target/rpm/RpmHeader.cc
zypp/target/rpm/librpmDb.cc
zypp/target/rpm/librpmDb.cv3.cc

index b281b70..f4d9a68 100644 (file)
@@ -76,8 +76,11 @@ ELSE ( NOT RPM_FOUND)
        MESSAGE( STATUS "rpm found: enable rpm-4 compat interface." )
        ADD_DEFINITIONS(-D_RPM_5)
   elseif ( RPM_SUSPECT_VERSION STREQUAL "4.x" )
+       MESSAGE( STATUS "rpm found: use rpm-4.x interface." )
+       ADD_DEFINITIONS(-D_RPM_4_X)
+  elseif ( RPM_SUSPECT_VERSION STREQUAL "4.4" )
        MESSAGE( STATUS "rpm found: enable rpm-4.4 legacy interface." )
-       ADD_DEFINITIONS(-D_RPM_4_4_COMPAT)
+       ADD_DEFINITIONS(-D_RPM_4_4)
   endif ( RPM_SUSPECT_VERSION STREQUAL "5.x" )
 ENDIF( NOT RPM_FOUND)
 
index e9ad382..fb54315 100644 (file)
@@ -15,20 +15,16 @@ extern "C"
 #ifdef _RPM_5
 #undef RPM_NULL_TYPE
 #define RPM_NULL_TYPE rpmTagType(0)
-#endif
-
-#ifndef _RPM_4_4_COMPAT
-#ifdef _RPM_5
 typedef rpmuint32_t rpm_count_t;
-#else
+#elifdef _RPM_4_4
 typedef int32_t rpm_count_t;
 #endif
-#endif
 }
 
 #include <iostream>
 
 #include "zypp/base/Logger.h"
+#include "zypp/base/NonCopyable.h"
 
 #include "zypp/target/rpm/BinHeader.h"
 
@@ -44,43 +40,88 @@ namespace target
 namespace rpm
 {
 
+  /** Helper for header data retieval.
+   * With \c _RPM_4_X use \c ::headerGet; with older \c _RPM_4_4
+   * use the meanwhile deprecated \c ::headerGetEntry.
+   * \ingroup g_RAII
+   */
+  struct HeaderEntryGetter : private base::NonCopyable
+  {
+    public:
+      HeaderEntryGetter( const Header & h_r, rpmTag & tag_r );
+      ~HeaderEntryGetter();
+      rpmTagType  type();
+      rpm_count_t cnt();
+      void *      val();
+    private:
+#ifdef _RPM_4_X
+     ::rpmtd           _rpmtd;
+#else
+      rpmTagType       _type;
+      rpm_count_t      _cnt;
+      void *           _val;
+#endif //_RPM_4_X
+ };
+
+#ifdef _RPM_4_X
+  inline HeaderEntryGetter::HeaderEntryGetter( const Header & h_r, rpmTag & tag_r )
+    : _rpmtd( ::rpmtdNew() )
+  { ::headerGet( h_r, tag_r, _rpmtd, HEADERGET_DEFAULT ); }
+  inline HeaderEntryGetter::~HeaderEntryGetter()
+  { ::rpmtdFreeData( _rpmtd ); ::rpmtdFree( _rpmtd ); }
+  inline rpmTagType    HeaderEntryGetter::type()       { return _rpmtd->type; }
+  inline rpm_count_t   HeaderEntryGetter::cnt()        { return _rpmtd->count; }
+  inline void *                HeaderEntryGetter::val()        { return _rpmtd->data; }
+#else
+  inline HeaderEntryGetter::HeaderEntryGetter( const Header & h_r, rpmTag & tag_r )
+    : _type( RPM_NULL_TYPE )
+    , _cnt( 0 )
+    , _val( 0 )
+  { ::headerGetEntry( h_r, tag_r, hTYP_t(&_type), &_val, &_cnt ); }
+  inline HeaderEntryGetter::~HeaderEntryGetter()
+  { if ( _val && _type == RPM_STRING_ARRAY_TYPE ) free( _val ); }
+  inline rpmTagType    HeaderEntryGetter::type()       { return _type; }
+  inline rpm_count_t   HeaderEntryGetter::cnt()        { return _cnt; }
+  inline void *                HeaderEntryGetter::val( int i ) { return _val; }
+#endif //_RPM_4_X
+
 ///////////////////////////////////////////////////////////////////
 //
 //        CLASS NAME : BinHeader::intList
 //
 ///////////////////////////////////////////////////////////////////
 
-BinHeader::intList::intList()
-    : cnt( 0 ), val( 0 ), type( RPM_NULL_TYPE )
-{}
-
 unsigned BinHeader::intList::set( void * val_r, unsigned cnt_r, rpmTagType type_r )
 {
-  val = val_r;
-  cnt = val ? cnt_r : 0;
-  type = type_r;
-  return cnt;
-}
-
-int BinHeader::intList::operator[]( const unsigned idx_r ) const
-{
-  if ( idx_r < cnt )
-  {
-    switch ( type )
+  if ( val_r )
+    switch ( _type )
     {
 #if RPM_CHAR_TYPE != RPM_INT8_TYPE
-    case RPM_CHAR_TYPE:
-      return ((char*)val)[idx_r];
+      case RPM_CHAR_TYPE:
+       std::vector<long>( (char*)val_r, ((char*)val_r)+cnt_r ).swap( _data );
+       break;
 #endif
-    case RPM_INT8_TYPE:
-      return ((int8_t*)val)[idx_r];
-    case RPM_INT16_TYPE:
-      return ((int16_t*)val)[idx_r];
-    case RPM_INT32_TYPE:
-      return ((int32_t*)val)[idx_r];
+      case RPM_INT8_TYPE:
+       std::vector<long>( (int8_t*)val_r, ((int8_t*)val_r)+cnt_r ).swap( _data );
+       break;
+      case RPM_INT16_TYPE:
+       std::vector<long>( (int16_t*)val_r, ((int16_t*)val_r)+cnt_r ).swap( _data );
+       break;
+      case RPM_INT32_TYPE:
+       std::vector<long>( (int32_t*)val_r, ((int32_t*)val_r)+cnt_r ).swap( _data );
+       break;
+       #ifdef _RPM_4_X
+      case RPM_INT64_TYPE:
+       std::vector<long>( (int64_t*)val_r, ((int64_t*)val_r)+cnt_r ).swap( _data );
+       break;
+       #endif
+      default:
+       std::vector<long>( cnt_r, 0L ).swap( _data );
+       break;
     }
-  }
-  return 0;
+  else
+    _data.clear();
+  return _data.size();
 }
 
 ///////////////////////////////////////////////////////////////////
@@ -89,29 +130,13 @@ int BinHeader::intList::operator[]( const unsigned idx_r ) const
 //
 ///////////////////////////////////////////////////////////////////
 
-void BinHeader::stringList::clear()
-{
-  if ( val )
-    free( val );
-  val = 0;
-  cnt = 0;
-}
-
-BinHeader::stringList::stringList()
-    : cnt( 0 ), val( 0 )
-{}
-
 unsigned BinHeader::stringList::set( char ** val_r, unsigned cnt_r )
 {
-  clear();
-  val = val_r;
-  cnt = val ? cnt_r : 0;
-  return cnt;
-}
-
-std::string BinHeader::stringList::operator[]( const unsigned idx_r ) const
-{
-  return( idx_r < cnt ? val[idx_r] : "" );
+  if ( val_r )
+    std::vector<std::string>( val_r, val_r+cnt_r ).swap( _data );
+  else
+    _data.clear();
+  return _data.size();
 }
 
 ///////////////////////////////////////////////////////////////////
@@ -215,30 +240,24 @@ unsigned BinHeader::int_list( tag tag_r, intList & lst_r ) const
 {
   if ( !empty() )
   {
-    rpmTagType type = RPM_NULL_TYPE;
-    rpm_count_t cnt = 0;
-    void * val  = 0;
-    ::headerGetEntry( _h, tag_r, hTYP_t(&type), &val, &cnt );
+    HeaderEntryGetter headerget( _h, tag_r );
 
-    if ( val )
+    if ( headerget.val() )
     {
-      switch ( type )
+      switch ( headerget.type() )
       {
       case RPM_NULL_TYPE:
-        return lst_r.set( 0, 0, type );
+        return lst_r.set( 0, 0, headerget.type() );
 #if RPM_CHAR_TYPE != RPM_INT8_TYPE
       case RPM_CHAR_TYPE:
 #endif
       case RPM_INT8_TYPE:
       case RPM_INT16_TYPE:
       case RPM_INT32_TYPE:
-        return lst_r.set( val, cnt, type );
+        return lst_r.set( headerget.val(), headerget.cnt(), headerget.type() );
 
-      case RPM_STRING_ARRAY_TYPE:
-        free( val );
-        // fall through
       default:
-        INT << "RPM_TAG MISSMATCH: RPM_INT32_TYPE " << tag_r << " got type " << type << endl;
+        INT << "RPM_TAG MISSMATCH: RPM_INT32_TYPE " << tag_r << " got type " << headerget.type() << endl;
       }
     }
   }
@@ -257,22 +276,19 @@ unsigned BinHeader::string_list( tag tag_r, stringList & lst_r ) const
 {
   if ( !empty() )
   {
-    rpmTagType type = RPM_NULL_TYPE;
-    rpm_count_t cnt = 0;
-    void * val  = 0;
-    ::headerGetEntry( _h, tag_r, hTYP_t(&type), &val, &cnt );
+    HeaderEntryGetter headerget( _h, tag_r );
 
-    if ( val )
+    if ( headerget.val() )
     {
-      switch ( type )
+      switch ( headerget.type() )
       {
       case RPM_NULL_TYPE:
         return lst_r.set( 0, 0 );
       case RPM_STRING_ARRAY_TYPE:
-        return lst_r.set( (char**)val, cnt );
+        return lst_r.set( (char**)headerget.val(), headerget.cnt() );
 
       default:
-        INT << "RPM_TAG MISSMATCH: RPM_STRING_ARRAY_TYPE " << tag_r << " got type " << type << endl;
+        INT << "RPM_TAG MISSMATCH: RPM_STRING_ARRAY_TYPE " << tag_r << " got type " << headerget.type() << endl;
       }
     }
   }
@@ -291,33 +307,27 @@ int BinHeader::int_val( tag tag_r ) const
 {
   if ( !empty() )
   {
-    rpmTagType type = RPM_NULL_TYPE;
-    rpm_count_t cnt = 0;
-    void * val  = 0;
-    ::headerGetEntry( _h, tag_r, hTYP_t(&type), &val, &cnt );
+    HeaderEntryGetter headerget( _h, tag_r );
 
-    if ( val )
+    if ( headerget.val() )
     {
-      switch ( type )
+      switch ( headerget.type() )
       {
       case RPM_NULL_TYPE:
         return 0;
 #if RPM_CHAR_TYPE != RPM_INT8_TYPE
       case RPM_CHAR_TYPE:
-        return *((char*)val);
+        return *((char*)headerget.val());
 #endif
       case RPM_INT8_TYPE:
-        return *((int8_t*)val);
+        return *((int8_t*)headerget.val());
       case RPM_INT16_TYPE:
-        return *((int16_t*)val);
+        return *((int16_t*)headerget.val());
       case RPM_INT32_TYPE:
-        return *((int32_t*)val);
+        return *((int32_t*)headerget.val());
 
-      case RPM_STRING_ARRAY_TYPE:
-        free( val );
-        // fall through
       default:
-        INT << "RPM_TAG MISSMATCH: RPM_INT32_TYPE " << tag_r << " got type " << type << endl;
+        INT << "RPM_TAG MISSMATCH: RPM_INT32_TYPE " << tag_r << " got type " << headerget.type() << endl;
       }
     }
   }
@@ -336,25 +346,19 @@ std::string BinHeader::string_val( tag tag_r ) const
 {
   if ( !empty() )
   {
-    rpmTagType type = RPM_NULL_TYPE;
-    rpm_count_t cnt = 0;
-    void * val  = 0;
-    ::headerGetEntry( _h, tag_r, hTYP_t(&type), &val, &cnt );
+    HeaderEntryGetter headerget( _h, tag_r );
 
-    if ( val )
+    if ( headerget.val() )
     {
-      switch ( type )
+      switch ( headerget.type() )
       {
       case RPM_NULL_TYPE:
         return "";
       case RPM_STRING_TYPE:
-        return (char*)val;
+        return (char*)headerget.val();
 
-      case RPM_STRING_ARRAY_TYPE:
-        free( val );
-        // fall through
-      default:
-        INT << "RPM_TAG MISSMATCH: RPM_STRING_TYPE " << tag_r << " got type " << type << endl;
+     default:
+        INT << "RPM_TAG MISSMATCH: RPM_STRING_TYPE " << tag_r << " got type " << headerget.type() << endl;
       }
     }
   }
index a3cba75..1dc636c 100644 (file)
@@ -19,6 +19,7 @@ extern "C"
 
 #include <iosfwd>
 #include <string>
+#include <vector>
 #include <list>
 
 #include "zypp/base/ReferenceCounted.h"
@@ -105,28 +106,29 @@ public:
 /**
  *
  **/
-class BinHeader::intList
+class BinHeader::intList : private base::NonCopyable
 {
-  intList            ( const intList & );
-  intList & operator=( const intList & );
-private:
-  unsigned cnt;
-  void *   val;
-  rpmTagType type;
-private:
-  friend class BinHeader;
-  unsigned set( void * val_r, unsigned cnt_r, rpmTagType type_r );
-public:
-  intList();
-  bool empty() const
-  {
-    return cnt==0;
-  }
-  unsigned size() const
-  {
-    return cnt;
-  }
-  int operator[]( const unsigned idx_r ) const;
+  public:
+    intList()
+      : _type( RPM_NULL_TYPE )
+    {}
+
+    bool empty() const
+    { return _data.empty(); }
+
+    unsigned size() const
+    { return _data.size(); }
+
+    long operator[]( const unsigned idx_r ) const
+    { return idx_r < _data.size() ? _data[idx_r] : 0; }
+
+  private:
+    friend class BinHeader;
+    unsigned set( void * val_r, unsigned cnt_r, rpmTagType type_r );
+
+  private:
+    std::vector<long> _data;
+    rpmTagType _type;
 };
 
 ///////////////////////////////////////////////////////////////////
@@ -137,32 +139,24 @@ public:
 /**
  *
  **/
-class BinHeader::stringList
+class BinHeader::stringList : private base::NonCopyable
 {
-  stringList            ( const stringList & );
-  stringList & operator=( const stringList & );
-private:
-  unsigned cnt;
-  char **  val;
-  void clear();
-private:
-  friend class BinHeader;
-  unsigned set( char ** val_r, unsigned cnt_r );
-public:
-  stringList();
-  ~stringList()
-  {
-    clear();
-  }
-  bool empty() const
-  {
-    return cnt==0;
-  }
-  unsigned size() const
-  {
-    return cnt;
-  }
-  std::string operator[]( const unsigned idx_r ) const;
+  public:
+    bool empty() const
+    { return _data.empty(); }
+
+    unsigned size() const
+    { return _data.size(); }
+
+    std::string operator[]( const unsigned idx_r ) const
+    { return idx_r < _data.size() ? _data[idx_r] : std::string(); }
+
+  private:
+    friend class BinHeader;
+    unsigned set( char ** val_r, unsigned cnt_r );
+
+  private:
+    std::vector<std::string> _data;
 };
 
 ///////////////////////////////////////////////////////////////////
index 1224ecd..b83bcba 100644 (file)
@@ -10,7 +10,7 @@
  *
 */
 #include "librpm.h"
-#if !defined(_RPM_4_4_COMPAT) && !defined(_RPM_5)
+#ifdef _RPM_4_4
 #include <rpm/ugid.h>
 #else
 ////////////////////////////////////////////////////////////////////
index 1689fbb..d1a3002 100644 (file)
@@ -452,7 +452,7 @@ unsigned librpmDb::size() const
   unsigned count = 0;
   if ( valid() )
   {
-#if defined(_RPM_4_4_COMPAT) || defined(_RPM_5)
+#ifndef _RPM_4_4
     // looks like rpm-4.7 has no public dbi interface anymore
     int dbi = ::rpmdbOpen("/", &_d._db, O_RDONLY, 0);
     if (dbi == 0) {
index bf18e45..bbec8aa 100644 (file)
 #include "librpm.h"
 extern "C"
 {
-#ifndef _RPM_4_4_COMPAT
 #ifdef _RPM_5
 typedef rpmuint32_t rpm_count_t;
-#else
+#elifdef _RPM_4_4
 typedef int32_t rpm_count_t;
 #endif
-#endif
 
-#if defined( _RPM_5 )
+#ifdef _RPM_5
 #define HGEPtr_t void *
 #define headerGetEntryMinMemory headerGetEntry
 #define headerNVR(h,n,v,r) headerNEVRA(h,n,NULL,v,r,NULL)
-#elif defined( _RPM_4_4_COMPAT )
-#define HGEPtr_t void *
-#else
+#elifdef _RPM_4_4
 #define HGEPtr_t const void *
 #endif
 }
@@ -39,6 +35,9 @@ typedef int32_t rpm_count_t;
 #include "zypp/target/rpm/RpmCallbacks.h"
 #include "zypp/ZYppCallbacks.h"
 
+#define xmalloc malloc
+#define xstrdup strdup
+
 extern "C"
 {
 #include <string.h>
@@ -68,7 +67,6 @@ namespace target
 {
 namespace rpm
 {
-
 static int fadFileSize;
 
 static ssize_t Pread(FD_t fd, void * buf, size_t count, off_t offset)
@@ -172,6 +170,7 @@ static int dncmp(const void * a, const void * b)
 /*@=boundsread@*/
 
 /*@-bounds@*/
+#ifndef _RPM_4_X
 static void compressFilelist(Header h)
 /*@*/
 {
@@ -362,6 +361,158 @@ exit:
                                 &pEVR, 1);
   }
 }
+#else
+static void compressFilelist(Header h)
+{
+    struct rpmtd_s fileNames;
+    char ** dirNames;
+    const char ** baseNames;
+    uint32_t * dirIndexes;
+    rpm_count_t count;
+    int xx, i;
+    int dirIndex = -1;
+
+    /*
+     * This assumes the file list is already sorted, and begins with a
+     * single '/'. That assumption isn't critical, but it makes things go
+     * a bit faster.
+     */
+
+    if (headerIsEntry(h, RPMTAG_DIRNAMES)) {
+        xx = headerDel(h, RPMTAG_OLDFILENAMES);
+        return;         /* Already converted. */
+    }
+
+    if (!headerGet(h, RPMTAG_OLDFILENAMES, &fileNames, HEADERGET_MINMEM))
+        return;
+    count = rpmtdCount(&fileNames);
+    if (count < 1)
+        return;
+
+    dirNames = (char**)malloc(sizeof(*dirNames) * count);      /* worst case */
+    baseNames = (const char**)malloc(sizeof(*dirNames) * count);
+    dirIndexes = (uint32_t*)malloc(sizeof(*dirIndexes) * count);
+
+    /* HACK. Source RPM, so just do things differently */
+    {   const char *fn = rpmtdGetString(&fileNames);
+        if (fn && *fn != '/') {
+            dirIndex = 0;
+            dirNames[dirIndex] = xstrdup("");
+            while ((i = rpmtdNext(&fileNames)) >= 0) {
+                dirIndexes[i] = dirIndex;
+                baseNames[i] = rpmtdGetString(&fileNames);
+            }
+            goto exit;
+        }
+    }
+
+    while ((i = rpmtdNext(&fileNames)) >= 0) {
+        char ** needle;
+        char savechar;
+        char * baseName;
+        size_t len;
+        const char *filename = rpmtdGetString(&fileNames);
+
+        if (filename == NULL)   /* XXX can't happen */
+            continue;
+        baseName = strrchr((char*)filename, '/') + 1;
+        len = baseName - filename;
+        needle = dirNames;
+        savechar = *baseName;
+        *baseName = '\0';
+        if (dirIndex < 0 ||
+            (needle = (char**)bsearch(&filename, dirNames, dirIndex + 1, sizeof(dirNames[0]), dncmp)) == NULL) {
+            char *s = (char*)malloc(len + 1);
+            rstrlcpy(s, filename, len + 1);
+            dirIndexes[i] = ++dirIndex;
+            dirNames[dirIndex] = s;
+        } else
+            dirIndexes[i] = needle - dirNames;
+
+        *baseName = savechar;
+        baseNames[i] = baseName;
+    }
+
+exit:
+    if (count > 0) {
+        headerPutUint32(h, RPMTAG_DIRINDEXES, dirIndexes, count);
+        headerPutStringArray(h, RPMTAG_BASENAMES, baseNames, count);
+        headerPutStringArray(h, RPMTAG_DIRNAMES,
+                             (const char **) dirNames, dirIndex + 1);
+    }
+
+    rpmtdFreeData(&fileNames);
+    for (i = 0; i <= dirIndex; i++) {
+        free(dirNames[i]);
+    }
+    free(dirNames);
+    free(baseNames);
+    free(dirIndexes);
+
+    xx = headerDel(h, RPMTAG_OLDFILENAMES);
+}
+
+/*
+ * Up to rpm 3.0.4, packages implicitly provided their own name-version-release.
+ * Retrofit an explicit "Provides: name = epoch:version-release.
+ */
+static void providePackageNVR(Header h)
+{
+    const char *name;
+    char *pEVR;
+    rpmsenseFlags pFlags = RPMSENSE_EQUAL;
+    int bingo = 1;
+    struct rpmtd_s pnames;
+    rpmds hds, nvrds;
+
+    /* Generate provides for this package name-version-release. */
+    pEVR = headerGetEVR(h, &name);
+    if (!(name && pEVR))
+        return;
+
+    /*
+     * Rpm prior to 3.0.3 does not have versioned provides.
+     * If no provides at all are available, we can just add.
+     */
+    if (!headerGet(h, RPMTAG_PROVIDENAME, &pnames, HEADERGET_MINMEM)) {
+        goto exit;
+    }
+
+    /*
+     * Otherwise, fill in entries on legacy packages.
+     */
+    if (!headerIsEntry(h, RPMTAG_PROVIDEVERSION)) {
+        while (rpmtdNext(&pnames) >= 0) {
+            uint32_t fdummy = RPMSENSE_ANY;
+
+            headerPutString(h, RPMTAG_PROVIDEVERSION, "");
+            headerPutUint32(h, RPMTAG_PROVIDEFLAGS, &fdummy, 1);
+        }
+        goto exit;
+    }
+
+    /* see if we already have this provide */
+    hds = rpmdsNew(h, RPMTAG_PROVIDENAME, 0);
+    nvrds = rpmdsSingle(RPMTAG_PROVIDENAME, name, pEVR, pFlags);
+    if (rpmdsFind(hds, nvrds) >= 0) {
+        bingo = 0;
+    }
+    rpmdsFree(hds);
+    rpmdsFree(nvrds);
+
+exit:
+    if (bingo) {
+        const char *evr = pEVR;
+       uint32_t fdummy = pFlags;
+        headerPutString(h, RPMTAG_PROVIDENAME, name);
+        headerPutString(h, RPMTAG_PROVIDEVERSION, evr);
+        headerPutUint32(h, RPMTAG_PROVIDEFLAGS, &fdummy, 1);
+    }
+    rpmtdFreeData(&pnames);
+    free(pEVR);
+}
+
+#endif
 
 ///////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////
@@ -562,7 +713,7 @@ void convertV3toV4( const Pathname & v3db_r, const librpmDb::constPtr & v4db_r )
   report->start(v3db_r);
   try
   {
-    internal_convertV3toV4( v3db_r, v4db_r, report );
+    //internal_convertV3toV4( v3db_r, v4db_r, report );
   }
   catch (RpmException & excpt_r)
   {