Imported Upstream version 15.0.0
[platform/upstream/libzypp.git] / zypp / Fetcher.cc
index ef150ea..03924d6 100644 (file)
@@ -21,6 +21,7 @@
 #include "zypp/base/DefaultIntegral.h"
 #include "zypp/base/String.h"
 #include "zypp/Fetcher.h"
+#include "zypp/ZYppFactory.h"
 #include "zypp/CheckSum.h"
 #include "zypp/base/UserRequestException.h"
 #include "zypp/parser/susetags/ContentFileReader.h"
@@ -91,8 +92,9 @@ namespace zypp
     ZYPP_DECLARE_FLAGS(Flags, Flag);
 
 
-    FetcherJob( const OnMediaLocation &loc )
+    FetcherJob( const OnMediaLocation &loc, const Pathname dfile = Pathname())
       : location(loc)
+      , deltafile(dfile)
       , flags(None)
     {
       //MIL << location << endl;
@@ -104,6 +106,7 @@ namespace zypp
     }
 
     OnMediaLocation location;
+    Pathname deltafile;
     //CompositeFileChecker checkers;
     list<FileChecker> checkers;
     Flags flags;
@@ -129,9 +132,7 @@ namespace zypp
   public:
     Impl();
 
-    ~Impl() {
-      MIL << endl;
-    }
+    ~Impl() {}
 
     void setOptions( Fetcher::Options options );
     Fetcher::Options options() const;
@@ -142,7 +143,7 @@ namespace zypp
     void enqueueDigestedDir( const OnMediaLocation &resource, bool recursive, const FileChecker &checker = FileChecker() );
 
     void enqueue( const OnMediaLocation &resource, const FileChecker &checker = FileChecker()  );
-    void enqueueDigested( const OnMediaLocation &resource, const FileChecker &checker = FileChecker() );
+    void enqueueDigested( const OnMediaLocation &resource, const FileChecker &checker = FileChecker(), const Pathname &deltafile = Pathname() );
     void addCachePath( const Pathname &cache_dir );
     void reset();
     void start( const Pathname &dest_dir,
@@ -175,10 +176,10 @@ namespace zypp
        */
       void readIndex( const Pathname &index, const Pathname &basedir );
 
-      /** specific version of \ref readIndex for SHA1SUMS file */
-      void readSha1sumsIndex( const Pathname &index, const Pathname &basedir );
+      /** specific version of \ref readIndex for CHECKSUMS file */
+      void readChecksumsIndex( const Pathname &index, const Pathname &basedir );
 
-      /** specific version of \ref readIndex for SHA1SUMS file */
+      /** specific version of \ref readIndex for content file */
       void readContentFileIndex( const Pathname &index, const Pathname &basedir );
 
       /** reads the content of a directory but keeps a cache **/
@@ -213,7 +214,7 @@ namespace zypp
       /**
        * Provide the resource to \ref dest_dir
        */
-      void provideToDest( MediaSetAccess &media, const OnMediaLocation &resource, const Pathname &dest_dir );
+      void provideToDest( MediaSetAccess &media, const OnMediaLocation &resource, const Pathname &dest_dir , const Pathname &deltafile);
 
   private:
     friend Impl * rwcowClone<Impl>( const Impl * rhs );
@@ -233,10 +234,10 @@ namespace zypp
   };
   ///////////////////////////////////////////////////////////////////
 
-  void Fetcher::Impl::enqueueDigested( const OnMediaLocation &resource, const FileChecker &checker )
+  void Fetcher::Impl::enqueueDigested( const OnMediaLocation &resource, const FileChecker &checker, const Pathname &deltafile )
   {
     FetcherJob_Ptr job;
-    job.reset(new FetcherJob(resource));
+    job.reset(new FetcherJob(resource, deltafile));
     job->flags |= FetcherJob:: AlwaysVerifyChecksum;
     _resources.push_back(job);
   }
@@ -367,15 +368,10 @@ namespace zypp
             if ( assert_dir( dest_full_path.dirname() ) != 0 )
               ZYPP_THROW( Exception("Can't create " + dest_full_path.dirname().asString()));
 
-            if ( filesystem::hardlink(cached_file, dest_full_path ) != 0 )
+            if ( filesystem::hardlinkCopy(cached_file, dest_full_path ) != 0 )
             {
-              WAR << "Can't hardlink '" << cached_file << "' to '" << dest_dir << "'. Trying copying." << endl;
-              if ( filesystem::copy(cached_file, dest_full_path ) != 0 )
-              {
-                ERR << "Can't copy " << cached_file + " to " + dest_dir << endl;
-                // try next cache
-                continue;
-              }
+              ERR << "Can't hardlink/copy " << cached_file + " to " + dest_dir << endl;
+              continue;
             }
           }
           // found in cache
@@ -429,35 +425,26 @@ namespace zypp
                                       const OnMediaLocation &resource,
                                       const Pathname &dest_dir )
   {
-      if ( _options & AutoAddSha1sumsIndexes )
+      auto fnc_addIfInContent( [&]( const std::string & index_r ) -> bool
       {
-          // only try to add an index if it exists
-          filesystem::DirEntry shafile;
-          shafile.name = "SHA1SUMS"; shafile.type = filesystem::FT_FILE;
-          if ( find( content.begin(), content.end(), shafile ) != content.end() )
-          {
-              // add the index of this directory
-              OnMediaLocation indexloc(resource);
-              indexloc.changeFilename(resource.filename() + "SHA1SUMS");
-              addIndex(indexloc);
-              // we need to read it now
-              downloadAndReadIndexList(media, dest_dir);
-          }
+       if ( find( content.begin(), content.end(), filesystem::DirEntry(index_r,filesystem::FT_FILE) ) == content.end() )
+         return false;
+       // add the index of this directory
+       OnMediaLocation indexloc( resource );
+       indexloc.changeFilename( resource.filename() + index_r );
+       addIndex( indexloc );
+       // we need to read it now
+       downloadAndReadIndexList( media, dest_dir );
+       return true;
+      } );
+
+      if ( _options & AutoAddChecksumsIndexes )
+      {
+       fnc_addIfInContent( "CHECKSUMS" ) || fnc_addIfInContent( "SHA1SUMS" );
       }
       if ( _options & AutoAddContentFileIndexes )
       {
-          // only try to add an index if it exists
-          filesystem::DirEntry contentfile;
-          contentfile.name = "content"; contentfile.type = filesystem::FT_FILE;
-          if ( find( content.begin(), content.end(), contentfile ) != content.end() )
-          {
-              // add the index of this directory
-              OnMediaLocation indexloc(resource);
-              indexloc.changeFilename(resource.filename() + "content");
-              addIndex(indexloc);
-              // we need to read it now
-              downloadAndReadIndexList(media, dest_dir);
-          }
+       fnc_addIfInContent( "content" );
       }
   }
 
@@ -492,7 +479,15 @@ namespace zypp
       // individual transfer jobs
       MIL << "Adding directory " << resource.filename() << endl;
       filesystem::DirContent content;
-      getDirectoryContent(media, resource, content);
+      try {
+       getDirectoryContent(media, resource, content);
+      }
+      catch ( media::MediaFileNotFoundException & exception )
+      {
+       ZYPP_CAUGHT( exception );
+       WAR << "Skiping subtree hidden at " << resource.filename() << endl;
+       return;
+      }
 
       // this method test for the option flags so indexes are added
       // only if the options are enabled
@@ -502,8 +497,8 @@ namespace zypp
             it != content.end();
             ++it )
       {
-          // skip SHA1SUMS* as they were already retrieved
-          if ( str::hasPrefix(it->name, "SHA1SUMS") )
+          // skip CHECKSUMS* as they were already retrieved
+          if ( str::hasPrefix(it->name, "CHECKSUMS") || str::hasPrefix(it->name, "SHA1SUMS") )
               continue;
 
           Pathname filename = resource.filename() + it->name;
@@ -540,7 +535,7 @@ namespace zypp
       }
   }
 
-  void Fetcher::Impl::provideToDest( MediaSetAccess &media, const OnMediaLocation &resource, const Pathname &dest_dir )
+  void Fetcher::Impl::provideToDest( MediaSetAccess &media, const OnMediaLocation &resource, const Pathname &dest_dir, const Pathname &deltafile )
   {
     bool got_from_cache = false;
 
@@ -554,11 +549,13 @@ namespace zypp
       // try to get the file from the net
       try
       {
-        Pathname tmp_file = media.provideFile(resource);
+        Pathname tmp_file = media.provideFile(resource, resource.optional() ? MediaSetAccess::PROVIDE_NON_INTERACTIVE : MediaSetAccess::PROVIDE_DEFAULT, deltafile );
+
         Pathname dest_full_path = dest_dir + resource.filename();
+
         if ( assert_dir( dest_full_path.dirname() ) != 0 )
               ZYPP_THROW( Exception("Can't create " + dest_full_path.dirname().asString()));
-        if ( filesystem::copy(tmp_file, dest_full_path ) != 0 )
+        if ( filesystem::hardlinkCopy( tmp_file, dest_full_path ) != 0 )
         {
           if ( ! PathInfo(tmp_file).isExist() )
               ERR << tmp_file << " does not exist" << endl;
@@ -566,23 +563,22 @@ namespace zypp
               ERR << dest_full_path.dirname() << " does not exist" << endl;
 
           media.releaseFile(resource); //not needed anymore, only eat space
-          ZYPP_THROW( Exception("Can't copy " + tmp_file.asString() + " to " + dest_dir.asString()));
+          ZYPP_THROW( Exception("Can't hardlink/copy " + tmp_file.asString() + " to " + dest_dir.asString()));
         }
 
         media.releaseFile(resource); //not needed anymore, only eat space
       }
       catch (Exception & excpt_r)
       {
-        ZYPP_CAUGHT(excpt_r);
-        excpt_r.remember("Can't provide " + resource.filename().asString() + " : " + excpt_r.msg());
-
         if ( resource.optional() )
         {
-            WAR << "optional resource " << resource << " could not be transfered" << endl;
+           ZYPP_CAUGHT(excpt_r);
+            WAR << "optional resource " << resource << " could not be transferred" << endl;
             return;
         }
         else
         {
+           excpt_r.remember("Can't provide " + resource.filename().asString() );
             ZYPP_RETHROW(excpt_r);
         }
       }
@@ -612,8 +608,8 @@ namespace zypp
   // generic function for reading indexes
   void Fetcher::Impl::readIndex( const Pathname &index, const Pathname &basedir )
   {
-    if ( index.basename() == "SHA1SUMS" )
-      readSha1sumsIndex(index, basedir);
+    if ( index.basename() == "CHECKSUMS" || index.basename() == "SHA1SUMS" )
+      readChecksumsIndex(index, basedir);
     else if ( index.basename() == "content" )
       readContentFileIndex(index, basedir);
     else
@@ -633,26 +629,34 @@ namespace zypp
       }
   }
 
-  // reads a SHA1SUMS file index
-  void Fetcher::Impl::readSha1sumsIndex( const Pathname &index, const Pathname &basedir )
+  // reads a CHECKSUMS (old SHA1SUMS) file index
+  void Fetcher::Impl::readChecksumsIndex( const Pathname &index, const Pathname &basedir )
   {
       std::ifstream in( index.c_str() );
-      string buffer;
       if ( ! in.fail() )
       {
-          while ( getline(in, buffer) )
+         std::string buffer;
+          while ( getline( in, buffer ) )
           {
-              vector<string> words;
-              str::split( buffer, back_inserter(words) );
-              if ( words.size() != 2 )
-                  ZYPP_THROW(Exception("Wrong format for SHA1SUMS file"));
-              //MIL << "check: '" << words[0] << "' | '" << words[1] << "'" << endl;
-              if ( ! words[1].empty() )
-                  _checksums[(basedir + words[1]).asString()] = CheckSum::sha1(words[0]);
+
+             if ( buffer[0] == '#' )
+               continue;       // simple comment
+
+             CheckSum checksum( str::stripFirstWord( buffer, /*ltrim before strip*/true ) );
+             if ( checksum.empty() )
+               continue;       // empty line | unknown cheksum format
+
+             if ( buffer.empty() )
+             {
+               WAR << "Missing filename in CHECKSUMS file: " << index.asString() << " (" << checksum << ")" << endl;
+               continue;
+             }
+
+             _checksums[(basedir/buffer).asString()] = checksum;
           }
       }
       else
-          ZYPP_THROW(Exception("Can't open SHA1SUMS file: " + index.asString()));
+          ZYPP_THROW(Exception("Can't open CHECKSUMS file: " + index.asString()));
   }
 
   void Fetcher::Impl::downloadIndex( MediaSetAccess &media, const OnMediaLocation &resource, const Pathname &dest_dir)
@@ -695,6 +699,12 @@ namespace zypp
     fetcher.start( dest_dir, media );
     fetcher.reset();
 
+    // try to import the key
+    if ( PathInfo(dest_dir + keyloc.filename()).isExist() )
+        getZYpp()->keyRing()->importKey(PublicKey(dest_dir + keyloc.filename()), false);
+    else
+        WAR << "No public key specified by user for index '" << keyloc.filename() << "'"<< endl;
+
     // now the index itself
     fetcher.enqueue( idxloc, FileChecker(sigchecker) );
     fetcher.start( dest_dir, media );
@@ -758,7 +768,7 @@ namespace zypp
       // may be this code can be factored out
       // together with the autodiscovery of indexes
       // of addDirJobs
-      if ( ( _options & AutoAddSha1sumsIndexes ) ||
+      if ( ( _options & AutoAddChecksumsIndexes ) ||
            ( _options & AutoAddContentFileIndexes ) )
       {
           // if auto indexing is enabled, then we need to read the
@@ -786,9 +796,9 @@ namespace zypp
           autoaddIndexes(content, media, Pathname("/"), dest_dir);
       }
 
-      provideToDest(media, (*it_res)->location, dest_dir);
+      provideToDest(media, (*it_res)->location, dest_dir, (*it_res)->deltafile);
 
-      // if the file was not transfered, and no exception, just
+      // if the file was not transferred, and no exception, just
       // return, as it was an optional file
       if ( ! PathInfo(dest_dir + (*it_res)->location.filename()).isExist() )
           return;
@@ -858,9 +868,9 @@ namespace zypp
     return _pimpl->options();
   }
 
-  void Fetcher::enqueueDigested( const OnMediaLocation &resource, const FileChecker &checker )
+  void Fetcher::enqueueDigested( const OnMediaLocation &resource, const FileChecker &checker, const Pathname &deltafile )
   {
-    _pimpl->enqueueDigested(resource, checker);
+    _pimpl->enqueueDigested(resource, checker, deltafile);
   }
 
   void Fetcher::enqueueDir( const OnMediaLocation &resource,