Imported Upstream version 14.47.0 upstream/14.47.0
authorDongHun Kwak <dh0128.kwak@samsung.com>
Mon, 2 Sep 2019 07:09:38 +0000 (16:09 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Mon, 2 Sep 2019 07:09:38 +0000 (16:09 +0900)
37 files changed:
VERSION.cmake
package/libzypp.changes
tests/zypp/MediaSetAccess_test.cc
tests/zypp/PoolQueryCC_test.cc
tests/zypp/data/mediasetaccess/src1/cd1/dir/test-big.txt [new file with mode: 0644]
tests/zypp/data/mediasetaccess/src1/cd1/test-big.txt [new file with mode: 0644]
zypp/MediaSetAccess.cc
zypp/media/MediaAccess.cc
zypp/media/MediaAccess.h
zypp/media/MediaCD.cc
zypp/media/MediaCD.h
zypp/media/MediaCIFS.cc
zypp/media/MediaCIFS.h
zypp/media/MediaCurl.cc
zypp/media/MediaCurl.h
zypp/media/MediaDIR.cc
zypp/media/MediaDIR.h
zypp/media/MediaDISK.cc
zypp/media/MediaDISK.h
zypp/media/MediaException.cc
zypp/media/MediaException.h
zypp/media/MediaHandler.cc
zypp/media/MediaHandler.h
zypp/media/MediaISO.cc
zypp/media/MediaISO.h
zypp/media/MediaManager.cc
zypp/media/MediaManager.h
zypp/media/MediaMultiCurl.cc
zypp/media/MediaMultiCurl.h
zypp/media/MediaNFS.cc
zypp/media/MediaNFS.h
zypp/media/MediaPlugin.cc
zypp/media/MediaPlugin.h
zypp/parser/yum/RepomdFileReader.cc
zypp/repo/Downloader.cc
zypp/repo/MediaInfoDownloader.cc
zypp/repo/SUSEMediaVerifier.cc

index b75578d..36dd387 100644 (file)
@@ -60,9 +60,9 @@
 #
 SET(LIBZYPP_MAJOR "14")
 SET(LIBZYPP_COMPATMINOR "39")
-SET(LIBZYPP_MINOR "46")
+SET(LIBZYPP_MINOR "47")
 SET(LIBZYPP_PATCH "0")
 #
-# LAST RELEASED: 14.46.0 (39)
+# LAST RELEASED: 14.47.0 (39)
 # (The number in parenthesis is LIBZYPP_COMPATMINOR)
 #=======
index ce915aa..5c6f9c1 100644 (file)
@@ -1,4 +1,12 @@
 -------------------------------------------------------------------
+Tue Oct  2 16:00:15 CEST 2018 - ma@suse.de
+
+- Add filesize check for downloads with known size (bsc#408814)
+- MediaMultiCurl: Trigger aliveCallback when downloading metalink
+  files (bsc#1021291)
+- version 14.47.0 (39)
+
+-------------------------------------------------------------------
 Tue Oct  2 12:36:18 CEST 2018 - ma@suse.de
 
 - Fix conversion of string and glob to regex when compiling queries
index 33dea03..982cdc4 100644 (file)
@@ -260,6 +260,35 @@ BOOST_AUTO_TEST_CASE(msa_remote_tests)
 
   // providing a file which does not exist should throw
   BOOST_CHECK_THROW(setaccess.provideFile("/testBADNAME.txt"), media::MediaFileNotFoundException);
+
+  BOOST_CHECK(setaccess.doesFileExist("/test-big.txt"));
+  BOOST_CHECK(setaccess.doesFileExist("dir/test-big.txt"));
+
+  {
+    // providing a file with wrong filesize should throw
+    OnMediaLocation locPlain("dir/test-big.txt");
+    locPlain.setDownloadSize( zypp::ByteCount(500, zypp::ByteCount::B) );
+    BOOST_CHECK_THROW(setaccess.provideFile(locPlain), media::MediaFileSizeExceededException);
+
+    // using the correct file size should NOT throw
+    locPlain.setDownloadSize( zypp::ByteCount(7135, zypp::ByteCount::B) );
+    Pathname file = setaccess.provideFile( locPlain );
+    BOOST_CHECK(check_file_exists(file) == true);
+  }
+
+  {
+    // test the maximum filesize again with metalink downloads
+    // providing a file with wrong filesize should throw
+    OnMediaLocation locMeta("/test-big.txt");
+    locMeta.setDownloadSize( zypp::ByteCount(500, zypp::ByteCount::B) );
+    BOOST_CHECK_THROW(setaccess.provideFile(locMeta), media::MediaFileSizeExceededException);
+
+    // using the correct file size should NOT throw
+    locMeta.setDownloadSize( zypp::ByteCount(7135, zypp::ByteCount::B) );
+    Pathname file = setaccess.provideFile( locMeta );
+    BOOST_CHECK(check_file_exists(file) == true);
+  }
+
   web.stop();
 }
 
index 6c50db4..93c5aae 100644 (file)
@@ -21,8 +21,8 @@ template <class TCont>
 std::ostream & nlist( std::ostream & str, const TCont & set_r )
 {
   str << "[" << set_r.size() << "]: ";
-  for ( const auto & solv : set_r )
-    str << " \"" << solv.name() << "\"";
+  for_( it, set_r.begin(), set_r.end() )
+    str << " \"" << PoolItem(*it).satSolvable().name() << "\"";
   return str << endl;
 }
 
@@ -44,7 +44,7 @@ static const unsigned qtestRXFAILCOMB = unsigned(-3);
 
 unsigned qtest( const std::string & pattern_r, Match::Mode mode_r, bool verbose_r = false )
 {
-  static constexpr const bool noMatchInvalidRegexException = false;
+  static const bool noMatchInvalidRegexException = false;
 
   typedef std::set<sat::Solvable> Result;
   PoolQuery q;
diff --git a/tests/zypp/data/mediasetaccess/src1/cd1/dir/test-big.txt b/tests/zypp/data/mediasetaccess/src1/cd1/dir/test-big.txt
new file mode 100644 (file)
index 0000000..87949e6
--- /dev/null
@@ -0,0 +1,15 @@
+Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.   
+
+Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.   
+
+Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.   
+
+Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.   
+
+Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.   
+
+Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.   
+
+Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.   
+
+Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.   
diff --git a/tests/zypp/data/mediasetaccess/src1/cd1/test-big.txt b/tests/zypp/data/mediasetaccess/src1/cd1/test-big.txt
new file mode 100644 (file)
index 0000000..32a8037
--- /dev/null
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<metalink version="3.0"
+  xmlns="http://www.metalinker.org/"
+  generator="http://metalinks.sourceforge.net/"
+  >
+<files>
+       <file name="test-big.txt">
+               <size>7135</size>
+               <verification>
+                       <hash type="md4">818dcbb0bbb033aa8b8c9ddd269648d2</hash>
+                       <hash type="md5">f69a3e53751eb3249c3c36c50290b8da</hash>
+                       <hash type="sha1">edf0cf52765c9b5cfeddfd83b62f8517b119ca77</hash>
+                       <hash type="sha256">b0343a8ee06d97c9786b65bcb64c49fbb7e1d517159fac4633ba56f7a521fef0</hash>
+                       <hash type="sha384">202d21693dabe53ff5f2305d6b78844ffaa3b566b9644d61ca087cab752965b16d6a188def7a9463b5f17fdc50b3d105</hash>
+                       <hash type="sha512">caf260dd5420a6a6df6a558eac69a901cd3e43dbfd37b54e0fb176940f3e09c3f96c7faa22e505777106ebf056c471be7556c8cba80331d6efdb9e763e66190b</hash>
+                       <hash type="ripemd160">77fc06ff936163cfb6c1b0c68cb47a295a5bf8e3</hash>
+                       <hash type="tiger192">2fcd624ba2ad1adb2ff23af58049b6f7b062754eadd031b1</hash>
+                       <hash type="crc32">011209ae</hash>
+                       <hash type="ed2k">818dcbb0bbb033aa8b8c9ddd269648d2</hash>
+                       <pieces length="262144" type="sha1">
+                               <hash piece="0">edf0cf52765c9b5cfeddfd83b62f8517b119ca77</hash>
+                       </pieces>
+               </verification>
+               <resources>
+                       <url type="http">http://localhost:10002/dir/test-big.txt</url>
+               </resources>
+       </file>
+</files>
+</metalink>
index a7c5f8d..1be0824 100644 (file)
@@ -108,10 +108,11 @@ IMPL_PTR_TYPE(MediaSetAccess);
   struct ProvideFileOperation
   {
     Pathname result;
+    ByteCount expectedFileSize;
     void operator()( media::MediaAccessId media, const Pathname &file )
     {
       media::MediaManager media_mgr;
-      media_mgr.provideFile(media, file);
+      media_mgr.provideFile(media, file, expectedFileSize);
       result = media_mgr.localPath(media, file);
     }
   };
@@ -157,6 +158,7 @@ IMPL_PTR_TYPE(MediaSetAccess);
   Pathname MediaSetAccess::provideFile( const OnMediaLocation & resource, ProvideFileOptions options, const Pathname &deltafile )
   {
     ProvideFileOperation op;
+    op.expectedFileSize = resource.downloadSize();
     provide( boost::ref(op), resource, options, deltafile );
     return op.result;
   }
index f119b00..f56f260 100644 (file)
@@ -337,13 +337,13 @@ MediaAccess::release( const std::string & ejectDev )
 // filename is interpreted relative to the attached url
 // and a path prefix is preserved to destination
 void
-MediaAccess::provideFile( const Pathname & filename ) const
+MediaAccess::provideFile(const Pathname & filename , const ByteCount &expectedFileSize) const
 {
   if ( !_handler ) {
     ZYPP_THROW(MediaNotOpenException("provideFile(" + filename.asString() + ")"));
   }
 
-  _handler->provideFile( filename );
+  _handler->provideFile( filename, expectedFileSize );
 }
 
 void
@@ -470,7 +470,7 @@ void MediaAccess::getFile( const Url &from, const Pathname &to )
   try {
     media.open( u );
     media.attach();
-    media._handler->provideFileCopy( base, to );
+    media._handler->provideFileCopy( base, to, 0 );
     media.release();
   }
   catch (const MediaException & excpt_r)
index 4555b4a..4bf4af2 100644 (file)
@@ -219,7 +219,7 @@ namespace zypp {
         * \throws MediaException
         *
         **/
-       void provideFile( const Pathname & filename ) const;
+       void provideFile( const Pathname & filename, const ByteCount &expectedFileSize ) const;
 
        /**
         * Remove filename below attach point IFF handler downloads files
@@ -386,7 +386,7 @@ namespace zypp {
              ZYPP_THROW(MediaBadFilenameException(_file.asString()));
            } else if ( _media ) {
              try {
-               _media->provideFile( _file );
+               _media->provideFile( _file, 0 );
                _local_file = _media->localPath( _file );
              }
              catch (const MediaException & excpt_r)
index 03f2be9..bbc3d3c 100644 (file)
@@ -724,9 +724,9 @@ namespace zypp
   //
   //  DESCRIPTION : Asserted that media is attached.
   //
-  void MediaCD::getFile( const Pathname & filename ) const
+  void MediaCD::getFile(const Pathname & filename , const ByteCount &expectedFileSize_r) const
   {
-    MediaHandler::getFile( filename );
+    MediaHandler::getFile( filename, expectedFileSize_r );
   }
 
   ///////////////////////////////////////////////////////////////////
index 4cd3527..03cee50 100644 (file)
@@ -45,7 +45,7 @@ namespace zypp {
 
        virtual void attachTo (bool next = false);
         virtual void releaseFrom( const std::string & ejectDev );
-       virtual void getFile( const Pathname & filename ) const;
+       virtual void getFile(const Pathname & filename, const ByteCount &expectedFileSize_r ) const override;
        virtual void getDir( const Pathname & dirname, bool recurse_r ) const;
         virtual void getDirInfo( std::list<std::string> & retlist,
                                  const Pathname & dirname, bool dots = true ) const;
index 753c4db..528dd43 100644 (file)
@@ -353,9 +353,9 @@ namespace zypp {
     //
     // DESCRIPTION : Asserted that media is attached.
     //
-    void MediaCIFS::getFile (const Pathname & filename) const
+    void MediaCIFS::getFile (const Pathname & filename, const ByteCount &expectedFileSize_r) const
     {
-      MediaHandler::getFile( filename );
+      MediaHandler::getFile( filename, expectedFileSize_r );
     }
 
     ///////////////////////////////////////////////////////////////////
index 73affb4..324fec4 100644 (file)
@@ -35,7 +35,7 @@ namespace zypp {
 
       virtual void attachTo (bool next = false);
       virtual void releaseFrom( const std::string & ejectDev );
-      virtual void getFile( const Pathname & filename ) const;
+      virtual void getFile( const Pathname & filename, const ByteCount &expectedFileSize_r ) const override;
       virtual void getDir( const Pathname & dirname, bool recurse_r ) const;
       virtual void getDirInfo( std::list<std::string> & retlist,
                                const Pathname & dirname, bool dots = true ) const;
index 99a6868..90e6194 100644 (file)
@@ -156,25 +156,101 @@ namespace zypp {
   namespace {
     struct ProgressData
     {
-      ProgressData(CURL *_curl, const long _timeout, const zypp::Url &_url = zypp::Url(),
-                   callback::SendReport<DownloadProgressReport> *_report=NULL)
-        : curl(_curl)
-        , timeout(_timeout)
-        , reached(false)
-        , report(_report)
-        , drate_period(-1)
-        , dload_period(0)
-        , secs(0)
-        , drate_avg(-1)
-        , ltime( time(NULL))
-        , dload( 0)
-        , uload( 0)
-        , url(_url)
+      ProgressData( CURL *_curl, time_t _timeout = 0, const Url & _url = Url(),
+                    ByteCount expectedFileSize_r = 0,
+                   callback::SendReport<DownloadProgressReport> *_report = nullptr )
+        : curl( _curl )
+       , url( _url )
+       , timeout( _timeout )
+        , reached( false )
+        , fileSizeExceeded ( false )
+        , report( _report )
+        , _expectedFileSize( expectedFileSize_r )
       {}
-      CURL                                         *curl;
-      long                                          timeout;
-      bool                                          reached;
+
+      CURL     *curl;
+      Url      url;
+      time_t   timeout;
+      bool     reached;
+      bool      fileSizeExceeded;
       callback::SendReport<DownloadProgressReport> *report;
+      ByteCount _expectedFileSize;
+
+      time_t _timeStart        = 0;    ///< Start total stats
+      time_t _timeLast = 0;    ///< Start last period(~1sec)
+      time_t _timeRcv  = 0;    ///< Start of no-data timeout
+      time_t _timeNow  = 0;    ///< Now
+
+      double _dnlTotal = 0.0;  ///< Bytes to download or 0 if unknown
+      double _dnlLast  = 0.0;  ///< Bytes downloaded at period start
+      double _dnlNow   = 0.0;  ///< Bytes downloaded now
+
+      int    _dnlPercent= 0;   ///< Percent completed or 0 if _dnlTotal is unknown
+
+      double _drateTotal= 0.0; ///< Download rate so far
+      double _drateLast        = 0.0;  ///< Download rate in last period
+
+      void updateStats( double dltotal = 0.0, double dlnow = 0.0 )
+      {
+       time_t now = _timeNow = time(0);
+
+       // If called without args (0.0), recompute based on the last values seen
+       if ( dltotal && dltotal != _dnlTotal )
+         _dnlTotal = dltotal;
+
+       if ( dlnow && dlnow != _dnlNow )
+       {
+         _timeRcv = now;
+         _dnlNow = dlnow;
+       }
+       else if ( !_dnlNow && !_dnlTotal )
+       {
+         // Start time counting as soon as first data arrives.
+         // Skip the connection / redirection time at begin.
+         return;
+       }
+
+       // init or reset if time jumps back
+       if ( !_timeStart || _timeStart > now )
+         _timeStart = _timeLast = _timeRcv = now;
+
+       // timeout condition
+       if ( timeout )
+         reached = ( (now - _timeRcv) > timeout );
+
+        // check if the downloaded data is already bigger than what we expected
+       fileSizeExceeded = _expectedFileSize > 0 && _expectedFileSize < static_cast<ByteCount::SizeType>(_dnlNow);
+
+       // percentage:
+       if ( _dnlTotal )
+         _dnlPercent = int(_dnlNow * 100 / _dnlTotal);
+
+       // download rates:
+       _drateTotal = _dnlNow / std::max( int(now - _timeStart), 1 );
+
+       if ( _timeLast < now )
+       {
+         _drateLast = (_dnlNow - _dnlLast) / int(now - _timeLast);
+         // start new period
+         _timeLast  = now;
+         _dnlLast   = _dnlNow;
+       }
+       else if ( _timeStart == _timeLast )
+         _drateLast = _drateTotal;
+      }
+
+      int reportProgress() const
+      {
+        if ( fileSizeExceeded )
+          return 1;
+       if ( reached )
+         return 1;     // no-data timeout
+       if ( report && !(*report)->progress( _dnlPercent, url, _drateTotal, _drateLast ) )
+         return 1;     // user requested abort
+       return 0;
+      }
+
+
       // download rate of the last period (cca 1 sec)
       double                                        drate_period;
       // bytes downloaded at the start of the last period
@@ -189,7 +265,6 @@ namespace zypp {
       double                                        dload;
       // bytes uploaded at the moment the progress was last reported
       double                                        uload;
-      zypp::Url                                     url;
     };
 
     ///////////////////////////////////////////////////////////////////
@@ -868,16 +943,16 @@ Url MediaCurl::getFileUrl( const Pathname & filename_r ) const
 
 ///////////////////////////////////////////////////////////////////
 
-void MediaCurl::getFile( const Pathname & filename ) const
+void MediaCurl::getFile(const Pathname & filename , const ByteCount &expectedFileSize_r) const
 {
     // Use absolute file name to prevent access of files outside of the
     // hierarchy below the attach point.
-    getFileCopy(filename, localPath(filename).absolutename());
+    getFileCopy(filename, localPath(filename).absolutename(), expectedFileSize_r);
 }
 
 ///////////////////////////////////////////////////////////////////
 
-void MediaCurl::getFileCopy( const Pathname & filename , const Pathname & target) const
+void MediaCurl::getFileCopy( const Pathname & filename , const Pathname & target, const ByteCount &expectedFileSize_r ) const
 {
   callback::SendReport<DownloadProgressReport> report;
 
@@ -889,7 +964,7 @@ void MediaCurl::getFileCopy( const Pathname & filename , const Pathname & target
   {
     try
     {
-      doGetFileCopy(filename, target, report);
+      doGetFileCopy(filename, target, report, expectedFileSize_r);
       retry = false;
     }
     // retry with proper authentication data
@@ -949,9 +1024,9 @@ bool MediaCurl::getDoesFileExist( const Pathname & filename ) const
 
 ///////////////////////////////////////////////////////////////////
 
-void MediaCurl::evaluateCurlCode( const Pathname &filename,
+void MediaCurl::evaluateCurlCode(const Pathname &filename,
                                   CURLcode code,
-                                  bool timeout_reached ) const
+                                  bool timeout_reached) const
 {
   if ( code != 0 )
   {
@@ -960,6 +1035,7 @@ void MediaCurl::evaluateCurlCode( const Pathname &filename,
       url = _url;
     else
       url = getFileUrl(filename);
+
     std::string err;
     try
     {
@@ -1274,7 +1350,7 @@ bool MediaCurl::detectDirIndex() const
 
 ///////////////////////////////////////////////////////////////////
 
-void MediaCurl::doGetFileCopy( const Pathname & filename , const Pathname & target, callback::SendReport<DownloadProgressReport> & report, RequestOptions options ) const
+void MediaCurl::doGetFileCopy(const Pathname & filename , const Pathname & target, callback::SendReport<DownloadProgressReport> & report, const ByteCount &expectedFileSize_r, RequestOptions options ) const
 {
     Pathname dest = target.absolutename();
     if( assert_dir( dest.dirname() ) )
@@ -1326,7 +1402,7 @@ void MediaCurl::doGetFileCopy( const Pathname & filename , const Pathname & targ
     }
     try
     {
-      doGetFileCopyFile(filename, dest, file, report, options);
+      doGetFileCopyFile(filename, dest, file, report, expectedFileSize_r, options);
     }
     catch (Exception &e)
     {
@@ -1388,7 +1464,7 @@ void MediaCurl::doGetFileCopy( const Pathname & filename , const Pathname & targ
 
 ///////////////////////////////////////////////////////////////////
 
-void MediaCurl::doGetFileCopyFile( const Pathname & filename , const Pathname & dest, FILE *file, callback::SendReport<DownloadProgressReport> & report, RequestOptions options ) const
+void MediaCurl::doGetFileCopyFile(const Pathname & filename , const Pathname & dest, FILE *file, callback::SendReport<DownloadProgressReport> & report, const ByteCount &expectedFileSize_r, RequestOptions options ) const
 {
     DBG << filename.asString() << endl;
 
@@ -1428,7 +1504,7 @@ void MediaCurl::doGetFileCopyFile( const Pathname & filename , const Pathname &
     }
 
     // Set callback and perform.
-    ProgressData progressData(_curl, _settings.timeout(), url, &report);
+    ProgressData progressData(_curl, _settings.timeout(), url, expectedFileSize_r, &report);
     if (!(options & OPTION_NO_REPORT_START))
       report->start(url, dest);
     if ( curl_easy_setopt( _curl, CURLOPT_PROGRESSDATA, &progressData ) != 0 ) {
@@ -1472,7 +1548,11 @@ void MediaCurl::doGetFileCopyFile( const Pathname & filename , const Pathname &
       // which holds whether the timeout was reached or not,
       // otherwise it would be a user cancel
       try {
-        evaluateCurlCode( filename, ret, progressData.reached);
+
+        if ( progressData.fileSizeExceeded )
+          ZYPP_THROW(MediaFileSizeExceededException(url, progressData._expectedFileSize));
+
+        evaluateCurlCode( filename, ret, progressData.reached );
       }
       catch ( const MediaException &e ) {
         // some error, we are not sure about file existence, rethrw
@@ -1502,7 +1582,7 @@ void MediaCurl::getDir( const Pathname & dirname, bool recurse_r ) const
       switch ( it->type ) {
       case filesystem::FT_NOT_AVAIL: // old directory.yast contains no typeinfo at all
       case filesystem::FT_FILE:
-        getFile( filename );
+        getFile( filename, 0 );
         break;
       case filesystem::FT_DIR: // newer directory.yast contain at least directory info
         if ( recurse_r ) {
@@ -1538,97 +1618,33 @@ void MediaCurl::getDirInfo( filesystem::DirContent & retlist,
 }
 
 ///////////////////////////////////////////////////////////////////
+//
+int MediaCurl::aliveCallback( void *clientp, double /*dltotal*/, double dlnow, double /*ultotal*/, double /*ulnow*/ )
+{
+  ProgressData *pdata = reinterpret_cast<ProgressData *>( clientp );
+  if( pdata )
+  {
+    // Do not propagate dltotal in alive callbacks. MultiCurl uses this to
+    // prevent a percentage raise while downloading a metalink file. Download
+    // activity however is indicated by propagating the download rate (via dlnow).
+    pdata->updateStats( 0.0, dlnow );
+    return pdata->reportProgress();
+  }
+  return 0;
+}
 
-int MediaCurl::progressCallback( void *clientp,
-                                 double dltotal, double dlnow,
-                                 double ultotal, double ulnow)
+int MediaCurl::progressCallback( void *clientp, double dltotal, double dlnow, double ultotal, double ulnow )
 {
-  ProgressData *pdata = reinterpret_cast<ProgressData *>(clientp);
-  if( pdata)
+  ProgressData *pdata = reinterpret_cast<ProgressData *>( clientp );
+  if( pdata )
   {
     // work around curl bug that gives us old data
     long httpReturnCode = 0;
-    if (curl_easy_getinfo(pdata->curl, CURLINFO_RESPONSE_CODE, &httpReturnCode) != CURLE_OK || httpReturnCode == 0)
-      return 0;
+    if ( curl_easy_getinfo( pdata->curl, CURLINFO_RESPONSE_CODE, &httpReturnCode ) != CURLE_OK || httpReturnCode == 0 )
+      return aliveCallback( clientp, dltotal, dlnow, ultotal, ulnow );
 
-    time_t now   = time(NULL);
-    if( now > 0)
-    {
-       // reset time of last change in case initial time()
-       // failed or the time was adjusted (goes backward)
-       if( pdata->ltime <= 0 || pdata->ltime > now)
-       {
-         pdata->ltime = now;
-       }
-
-       // start time counting as soon as first data arrives
-       // (skip the connection / redirection time at begin)
-       time_t dif = 0;
-       if (dlnow > 0 || ulnow > 0)
-       {
-         dif = (now - pdata->ltime);
-         dif = dif > 0 ? dif : 0;
-
-         pdata->secs += dif;
-       }
-
-       // update the drate_avg and drate_period only after a second has passed
-       // (this callback is called much more often than a second)
-       // otherwise the values would be far from accurate when measuring
-       // the time in seconds
-       //! \todo more accurate download rate computationn, e.g. compute average value from last 5 seconds, or work with milliseconds instead of seconds
-
-        if ( pdata->secs > 1 && (dif > 0 || dlnow == dltotal ))
-          pdata->drate_avg = (dlnow / pdata->secs);
-
-       if ( dif > 0 )
-       {
-         pdata->drate_period = ((dlnow - pdata->dload_period) / dif);
-         pdata->dload_period = dlnow;
-       }
-    }
-
-    // send progress report first, abort transfer if requested
-    if( pdata->report)
-    {
-      if (!(*(pdata->report))->progress(int( dltotal ? dlnow * 100 / dltotal : 0 ),
-                                       pdata->url,
-                                       pdata->drate_avg,
-                                       pdata->drate_period))
-      {
-        return 1; // abort transfer
-      }
-    }
-
-    // check if we there is a timeout set
-    if( pdata->timeout > 0)
-    {
-      if( now > 0)
-      {
-        bool progress = false;
-
-        // update download data if changed, mark progress
-        if( dlnow != pdata->dload)
-        {
-          progress     = true;
-          pdata->dload = dlnow;
-          pdata->ltime = now;
-        }
-        // update upload data if changed, mark progress
-        if( ulnow != pdata->uload)
-        {
-          progress     = true;
-          pdata->uload = ulnow;
-          pdata->ltime = now;
-        }
-
-        if( !progress && (now >= (pdata->ltime + pdata->timeout)))
-        {
-          pdata->reached = true;
-          return 1; // aborts transfer
-        }
-      }
-    }
+    pdata->updateStats( dltotal, dlnow );
+    return pdata->reportProgress();
   }
   return 0;
 }
@@ -1656,6 +1672,18 @@ string MediaCurl::getAuthHint() const
   return "";
 }
 
+/**
+ * MediaMultiCurl needs to reset the expected filesize in case a metalink file is downloaded
+ * otherwise this function should not be called
+ */
+void MediaCurl::resetExpectedFileSize(void *clientp, const ByteCount &expectedFileSize)
+{
+  ProgressData *data = reinterpret_cast<ProgressData *>(clientp);
+  if ( data ) {
+    data->_expectedFileSize = expectedFileSize;
+  }
+}
+
 ///////////////////////////////////////////////////////////////////
 
 bool MediaCurl::authenticate(const string & availAuthTypes, bool firstTry) const
index c78c7d9..209ff06 100644 (file)
@@ -53,7 +53,7 @@ class MediaCurl : public MediaHandler
 
     virtual void attachTo (bool next = false);
     virtual void releaseFrom( const std::string & ejectDev );
-    virtual void getFile( const Pathname & filename ) const;
+    virtual void getFile( const Pathname & filename, const ByteCount &expectedFileSize_r ) const override;
     virtual void getDir( const Pathname & dirname, bool recurse_r ) const;
     virtual void getDirInfo( std::list<std::string> & retlist,
                              const Pathname & dirname, bool dots = true ) const;
@@ -82,14 +82,14 @@ class MediaCurl : public MediaHandler
      * \throws MediaException
      *
      */
-    virtual void getFileCopy( const Pathname & srcFilename, const Pathname & targetFilename) const;
+    virtual void getFileCopy( const Pathname & srcFilename, const Pathname & targetFilename, const ByteCount &expectedFileSize_r) const override;
 
     /**
      *
      * \throws MediaException
      *
      */
-    virtual void doGetFileCopy( const Pathname & srcFilename, const Pathname & targetFilename, callback::SendReport<DownloadProgressReport> & _report, RequestOptions options = OPTION_NONE ) const;
+    virtual void doGetFileCopy( const Pathname & srcFilename, const Pathname & targetFilename, callback::SendReport<DownloadProgressReport> & _report, const ByteCount &expectedFileSize_r,  RequestOptions options = OPTION_NONE ) const;
 
 
     virtual bool checkAttachPoint(const Pathname &apoint) const;
@@ -113,9 +113,10 @@ class MediaCurl : public MediaHandler
     };
 
   protected:
-
-    static int progressCallback( void *clientp, double dltotal, double dlnow,
-                                 double ultotal, double ulnow );
+//     /** Callback sending just an alive trigger to the UI, without stats (e.g. during metalink download). */
+    static int aliveCallback( void *clientp, double dltotal, double dlnow, double ultotal, double ulnow );
+    /** Callback reporting download progress. */
+    static int progressCallback( void *clientp, double dltotal, double dlnow, double ultotal, double ulnow );
     static CURL *progressCallback_getcurl( void *clientp );
     /**
      * check the url is supported by the curl library
@@ -146,9 +147,11 @@ class MediaCurl : public MediaHandler
      *
      * \throws MediaException If there is a problem
      */
-    void evaluateCurlCode( const zypp::Pathname &filename, CURLcode code, bool timeout ) const;
+    void evaluateCurlCode(const zypp::Pathname &filename, CURLcode code, bool timeout) const;
+
+    void doGetFileCopyFile( const Pathname & srcFilename, const Pathname & dest, FILE *file, callback::SendReport<DownloadProgressReport> & _report, const ByteCount &expectedFileSize_r, RequestOptions options = OPTION_NONE ) const;
 
-    void doGetFileCopyFile( const Pathname & srcFilename, const Pathname & dest, FILE *file, callback::SendReport<DownloadProgressReport> & _report, RequestOptions options = OPTION_NONE ) const;
+    static void resetExpectedFileSize ( void *clientp, const ByteCount &expectedFileSize );
 
   private:
     /**
index 4f8288e..0169d2f 100644 (file)
@@ -130,9 +130,9 @@ namespace zypp {
     //
     // DESCRIPTION : Asserted that media is attached.
     //
-    void MediaDIR::getFile( const Pathname & filename ) const
+    void MediaDIR::getFile(const Pathname & filename , const ByteCount &expectedFileSize_r) const
     {
-      MediaHandler::getFile( filename );
+      MediaHandler::getFile( filename, expectedFileSize_r );
     }
 
     ///////////////////////////////////////////////////////////////////
index 2f99de8..988c5bf 100644 (file)
@@ -31,7 +31,7 @@ namespace zypp {
 
        virtual void attachTo (bool next = false);
         virtual void releaseFrom( const std::string & ejectDev );
-       virtual void getFile( const Pathname & filename ) const;
+       virtual void getFile( const Pathname & filename, const ByteCount &expectedFileSize_r ) const override;
        virtual void getDir( const Pathname & dirname, bool recurse_r ) const;
         virtual void getDirInfo( std::list<std::string> & retlist,
                                  const Pathname & dirname, bool dots = true ) const;
index de4f244..999828b 100644 (file)
@@ -356,9 +356,9 @@ namespace zypp {
     //
     // DESCRIPTION : Asserted that media is attached.
     //
-    void MediaDISK::getFile (const Pathname & filename) const
+    void MediaDISK::getFile (const Pathname & filename, const ByteCount &expectedFileSize_r) const
     {
-      MediaHandler::getFile( filename );
+      MediaHandler::getFile( filename, expectedFileSize_r );
     }
 
     ///////////////////////////////////////////////////////////////////
index 8427611..8b2dc9e 100644 (file)
@@ -37,7 +37,7 @@ namespace zypp {
 
        virtual void attachTo (bool next = false);
         virtual void releaseFrom( const std::string & ejectDev );
-       virtual void getFile( const Pathname & filename ) const;
+       virtual void getFile(const Pathname & filename, const ByteCount &expectedFileSize_r ) const override;
        virtual void getDir( const Pathname & dirname, bool recurse_r ) const;
         virtual void getDirInfo( std::list<std::string> & retlist,
                                  const Pathname & dirname, bool dots = true ) const;
index 346802d..a1cbb7c 100644 (file)
@@ -210,6 +210,14 @@ namespace zypp
       return str;
     }
 
+    std::ostream &MediaFileSizeExceededException::dumpOn(std::ostream &str) const
+    {
+      str << form(_("Downloaded data exceeded the expected filesize '%s' of '%s'."), _expectedFileSize.asString().c_str(), _url.c_str() );
+      if ( !_msg.empty() )
+        str << endl << _msg;
+      return str;
+    }
+
     std::ostream & MediaTemporaryProblemException::dumpOn( std::ostream & str ) const
     {
       str << form(_("Location '%s' is temporarily unaccessible."), _url.c_str()) << endl;
index 1e885d8..981a283 100644 (file)
@@ -20,6 +20,7 @@
 #include "zypp/base/Exception.h"
 #include "zypp/Pathname.h"
 #include "zypp/Url.h"
+#include "zypp/ByteCount.h"
 
 ///////////////////////////////////////////////////////////////////
 namespace zypp
@@ -486,6 +487,23 @@ namespace zypp
       std::string _msg;
     };
 
+    class MediaFileSizeExceededException : public MediaException
+    {
+    public:
+      MediaFileSizeExceededException(const Url & url_r, const ByteCount &cnt_r, const std::string & msg = "")
+      : MediaException(msg)
+      , _url(url_r.asString())
+      , _msg(msg)
+      , _expectedFileSize(cnt_r)
+      {}
+      virtual ~MediaFileSizeExceededException() throw() {};
+    protected:
+      virtual std::ostream & dumpOn( std::ostream & str ) const;
+      std::string _url;
+      std::string _msg;
+      ByteCount _expectedFileSize;
+    };
+
     /** For HTTP 503 and similar. */
     class MediaTemporaryProblemException : public MediaException
     {
index 90967bd..28c581b 100644 (file)
@@ -989,8 +989,8 @@ MediaHandler::dependsOnParent(MediaAccessId parentId, bool exactIdMatch)
 //
 //     DESCRIPTION :
 //
-void MediaHandler::provideFileCopy( Pathname srcFilename,
-                                       Pathname targetFilename ) const
+void MediaHandler::provideFileCopy(Pathname srcFilename,
+                                       Pathname targetFilename , const ByteCount &expectedFileSize_r) const
 {
   if ( !isAttached() ) {
     INT << "Media not_attached on provideFileCopy(" << srcFilename
@@ -998,18 +998,18 @@ void MediaHandler::provideFileCopy( Pathname srcFilename,
     ZYPP_THROW(MediaNotAttachedException(url()));
   }
 
-  getFileCopy( srcFilename, targetFilename ); // pass to concrete handler
+  getFileCopy( srcFilename, targetFilename, expectedFileSize_r ); // pass to concrete handler
   DBG << "provideFileCopy(" << srcFilename << "," << targetFilename  << ")" << endl;
 }
 
-void MediaHandler::provideFile( Pathname filename ) const
+void MediaHandler::provideFile(Pathname filename , const ByteCount &expectedFileSize_r) const
 {
   if ( !isAttached() ) {
     INT << "Error: Not attached on provideFile(" << filename << ")" << endl;
     ZYPP_THROW(MediaNotAttachedException(url()));
   }
 
-  getFile( filename ); // pass to concrete handler
+  getFile( filename, expectedFileSize_r ); // pass to concrete handler
   DBG << "provideFile(" << filename << ")" << endl;
 }
 
@@ -1174,7 +1174,7 @@ void MediaHandler::getDirectoryYast( filesystem::DirContent & retlist,
 
   // look for directory.yast
   Pathname dirFile = dirname + "directory.yast";
-  getFile( dirFile );
+  getFile( dirFile, 0 );
   DBG << "provideFile(" << dirFile << "): " << "OK" << endl;
 
   // using directory.yast
@@ -1230,7 +1230,7 @@ ostream & operator<<( ostream & str, const MediaHandler & obj )
 //     DESCRIPTION : Asserted that media is attached.
 //                    Default implementation of pure virtual.
 //
-void MediaHandler::getFile( const Pathname & filename ) const
+void MediaHandler::getFile(const Pathname & filename , const ByteCount &) const
 {
     PathInfo info( localPath( filename ) );
     if( info.isFile() ) {
@@ -1244,9 +1244,9 @@ void MediaHandler::getFile( const Pathname & filename ) const
 }
 
 
-void MediaHandler::getFileCopy ( const Pathname & srcFilename, const Pathname & targetFilename ) const
+void MediaHandler::getFileCopy (const Pathname & srcFilename, const Pathname & targetFilename , const ByteCount &expectedFileSize_r) const
 {
-  getFile(srcFilename);
+  getFile(srcFilename, expectedFileSize_r);
 
   if ( copy( localPath( srcFilename ), targetFilename ) != 0 ) {
     ZYPP_THROW(MediaWriteException(targetFilename));
index f5b5cde..acc7d8c 100644 (file)
@@ -357,7 +357,7 @@ class MediaHandler {
         * \throws MediaException
         *
         **/
-       virtual void getFile( const Pathname & filename ) const = 0;
+       virtual void getFile( const Pathname & filename, const ByteCount &expectedFileSize_r ) const;
 
         /**
          * Call concrete handler to provide a file under a different place
@@ -370,7 +370,7 @@ class MediaHandler {
         * \throws MediaException
         *
          **/
-        virtual void getFileCopy( const Pathname & srcFilename, const Pathname & targetFilename ) const;
+        virtual void getFileCopy( const Pathname & srcFilename, const Pathname & targetFilename, const ByteCount &expectedFileSize_r ) const;
 
 
        /**
@@ -570,7 +570,7 @@ class MediaHandler {
         * \throws MediaException
         *
         **/
-       void provideFile( Pathname filename ) const;
+       void provideFile( Pathname filename, const ByteCount &expectedFileSize_r ) const;
 
        /**
         * Call concrete handler to provide a copy of a file under a different place
@@ -583,7 +583,7 @@ class MediaHandler {
         * \throws MediaException
         *
         **/
-        void provideFileCopy( Pathname srcFilename, Pathname targetFilename) const;
+        void provideFileCopy( Pathname srcFilename, Pathname targetFilename, const ByteCount &expectedFileSize_r ) const;
 
        /**
         * Use concrete handler to provide directory denoted
index 85aa783..e7f71fc 100644 (file)
@@ -276,9 +276,9 @@ namespace zypp
     }
 
     // ---------------------------------------------------------------
-    void MediaISO::getFile(const Pathname &filename) const
+    void MediaISO::getFile(const Pathname &filename, const ByteCount &expectedFileSize_r) const
     {
-      MediaHandler::getFile(filename);
+      MediaHandler::getFile(filename, expectedFileSize_r);
     }
 
     // ---------------------------------------------------------------
index 7828e8b..032a3b4 100644 (file)
@@ -43,7 +43,7 @@ namespace zypp
 
        virtual void attachTo (bool next = false);
         virtual void releaseFrom( const std::string & ejectDev = "" );
-       virtual void getFile( const Pathname & filename ) const;
+       virtual void getFile( const Pathname & filename, const ByteCount &expectedFileSize_r ) const;
        virtual void getDir( const Pathname & dirname, bool recurse_r ) const;
         virtual void getDirInfo( std::list<std::string> & retlist,
                                  const Pathname & dirname, bool dots = true ) const;
index 7295132..bbca585 100644 (file)
@@ -679,10 +679,10 @@ namespace zypp
       return path;
     }
 
-    // ---------------------------------------------------------------
     void
     MediaManager::provideFile(MediaAccessId   accessId,
-                              const Pathname &filename ) const
+                              const Pathname &filename,
+                              const ByteCount &expectedFileSize ) const
     {
       MutexLock glock(g_Mutex);
 
@@ -690,7 +690,15 @@ namespace zypp
 
       ref.checkDesired(accessId);
 
-      ref.handler->provideFile(filename);
+      ref.handler->provideFile(filename, expectedFileSize);
+    }
+
+    // ---------------------------------------------------------------
+    void
+    MediaManager::provideFile(MediaAccessId   accessId,
+                              const Pathname &filename ) const
+    {
+      provideFile( accessId, filename, 0);
     }
 
     // ---------------------------------------------------------------
index 049da47..390c653 100644 (file)
@@ -748,6 +748,7 @@ namespace zypp
        *
        * \param accessId  The media access id to use.
        * \param filename  The filename to provide, relative to localRoot().
+       * \param expectedFileSize The expected filesize, download will stop if it is exceeded
        *
        * \throws MediaNotOpenException in case of invalid access id.
        * \throws MediaNotAttachedException in case, that the media is not attached.
@@ -760,6 +761,11 @@ namespace zypp
        */
 
       void
+      provideFile(MediaAccessId accessId,
+                  const Pathname &filename,
+                  const ByteCount &expectedFileSize) const;
+
+      void
       provideFile(MediaAccessId   accessId,
                   const Pathname &filename ) const;
 
index 9f2f072..0d921ef 100644 (file)
@@ -1119,12 +1119,17 @@ multifetchrequest::run(std::vector<Url> &urllist)
                  worker->evaluateCurlCode(Pathname(), cc, false);
                }
            }
+
+         if ( _filesize > 0 && _fetchedgoodsize > _filesize ) {
+           ZYPP_THROW(MediaFileSizeExceededException(_baseurl, _filesize));
+         }
        }
 
       // send report
       if (_report)
        {
          int percent = _totalsize ? (100 * (_fetchedgoodsize + _fetchedsize)) / (_totalsize + _fetchedsize) : 0;
+
          double avg = 0;
          if (now > _starttime)
            avg = _fetchedsize / (now - _starttime);
@@ -1236,16 +1241,27 @@ static bool looks_like_metalink(const Pathname & file)
 }
 
 // here we try to suppress all progress coming from a metalink download
+// bsc#1021291: Nevertheless send alive trigger (without stats), so UIs
+// are able to abort a hanging metalink download via callback response.
 int MediaMultiCurl::progressCallback( void *clientp, double dltotal, double dlnow, double ultotal, double ulnow)
 {
   CURL *_curl = MediaCurl::progressCallback_getcurl(clientp);
   if (!_curl)
-    return 0;
+    return MediaCurl::aliveCallback(clientp, dltotal, dlnow, ultotal, ulnow);
 
+  // bsc#408814: Don't report any sizes before we don't have data on disk. Data reported
+  // due to redirection etc. are not interesting, but may disturb filesize checks.
+  FILE *fp = 0;
+  if ( curl_easy_getinfo( _curl, CURLINFO_PRIVATE, &fp ) != CURLE_OK || !fp )
+    return MediaCurl::aliveCallback( clientp, dltotal, dlnow, ultotal, ulnow );
+  if ( ftell( fp ) == 0 )
+    return MediaCurl::aliveCallback( clientp, dltotal, 0.0, ultotal, ulnow );
+
+  // (no longer needed due to the filesize check above?)
   // work around curl bug that gives us old data
   long httpReturnCode = 0;
   if (curl_easy_getinfo(_curl, CURLINFO_RESPONSE_CODE, &httpReturnCode ) != CURLE_OK || httpReturnCode == 0)
-    return 0;
+    return MediaCurl::aliveCallback(clientp, dltotal, dlnow, ultotal, ulnow);
 
   char *ptr = NULL;
   bool ismetalink = false;
@@ -1257,31 +1273,28 @@ int MediaMultiCurl::progressCallback( void *clientp, double dltotal, double dlno
     }    
   if (!ismetalink && dlnow < 256)
     {
-      // can't tell yet, suppress callback
-      return 0;
+      // can't tell yet, ...
+      return MediaCurl::aliveCallback(clientp, dltotal, dlnow, ultotal, ulnow);
     }
   if (!ismetalink)
     {
-      FILE *fp = 0;
-      if (curl_easy_getinfo(_curl, CURLINFO_PRIVATE, &fp) != CURLE_OK)
-       return 0;
-      if (!fp)
-       return 0;       /* hmm */
       fflush(fp);
       ismetalink = looks_like_metalink_fd(fileno(fp));
       DBG << "looks_like_metalink_fd: " << ismetalink << endl;
     }
   if (ismetalink)
     {
-      // we're downloading the metalink file. no progress please.
-      curl_easy_setopt(_curl, CURLOPT_NOPROGRESS, 1L);
-      return 0;
+      // this is a metalink file change the expected filesize
+      MediaCurl::resetExpectedFileSize( clientp, ByteCount( 2, ByteCount::MB) );
+      // we're downloading the metalink file. Just trigger aliveCallbacks
+      curl_easy_setopt(_curl, CURLOPT_PROGRESSFUNCTION, &MediaCurl::aliveCallback);
+      return MediaCurl::aliveCallback(clientp, dltotal, dlnow, ultotal, ulnow);
     }
   curl_easy_setopt(_curl, CURLOPT_PROGRESSFUNCTION, &MediaCurl::progressCallback);
   return MediaCurl::progressCallback(clientp, dltotal, dlnow, ultotal, ulnow);
 }
 
-void MediaMultiCurl::doGetFileCopy( const Pathname & filename , const Pathname & target, callback::SendReport<DownloadProgressReport> & report, RequestOptions options ) const
+void MediaMultiCurl::doGetFileCopy( const Pathname & filename , const Pathname & target, callback::SendReport<DownloadProgressReport> & report, const ByteCount &expectedFileSize_r, RequestOptions options ) const
 {
   Pathname dest = target.absolutename();
   if( assert_dir( dest.dirname() ) )
@@ -1337,7 +1350,7 @@ void MediaMultiCurl::doGetFileCopy( const Pathname & filename , const Pathname &
   curl_easy_setopt(_curl, CURLOPT_PRIVATE, file);
   try
     {
-      MediaCurl::doGetFileCopyFile(filename, dest, file, report, options);
+      MediaCurl::doGetFileCopyFile(filename, dest, file, report, expectedFileSize_r, options);
     }
   catch (Exception &ex)
     {
@@ -1427,7 +1440,7 @@ void MediaMultiCurl::doGetFileCopy( const Pathname & filename , const Pathname &
            }
          try
            {
-             multifetch(filename, file, &urls, &report, &bl);
+             multifetch(filename, file, &urls, &report, &bl, expectedFileSize_r);
            }
          catch (MediaCurlException &ex)
            {
@@ -1435,6 +1448,9 @@ void MediaMultiCurl::doGetFileCopy( const Pathname & filename , const Pathname &
              ZYPP_RETHROW(ex);
            }
        }
+      catch (MediaFileSizeExceededException &ex) {
+        ZYPP_RETHROW(ex);
+      }
       catch (Exception &ex)
        {
          // something went wrong. fall back to normal download
@@ -1454,7 +1470,7 @@ void MediaMultiCurl::doGetFileCopy( const Pathname & filename , const Pathname &
          file = fopen(destNew.c_str(), "w+e");
          if (!file)
            ZYPP_THROW(MediaWriteException(destNew));
-         MediaCurl::doGetFileCopyFile(filename, dest, file, report, options | OPTION_NO_REPORT_START);
+         MediaCurl::doGetFileCopyFile(filename, dest, file, report, expectedFileSize_r, options | OPTION_NO_REPORT_START);
        }
     }
 
@@ -1496,6 +1512,7 @@ void MediaMultiCurl::multifetch(const Pathname & filename, FILE *fp, std::vector
       if (!_multi)
        ZYPP_THROW(MediaCurlInitException(baseurl));
     }
+
   multifetchrequest req(this, filename, baseurl, _multi, fp, report, blklist, filesize);
   req._timeout = _settings.timeout();
   req._connect_timeout = _settings.connectTimeout();
index e5d8212..0c2e1ee 100644 (file)
@@ -45,7 +45,7 @@ public:
   MediaMultiCurl(const Url &url_r, const Pathname & attach_point_hint_r);
   ~MediaMultiCurl();
 
-  virtual void doGetFileCopy( const Pathname & srcFilename, const Pathname & targetFilename, callback::SendReport<DownloadProgressReport> & _report, RequestOptions options = OPTION_NONE ) const;
+  virtual void doGetFileCopy( const Pathname & srcFilename, const Pathname & targetFilename, callback::SendReport<DownloadProgressReport> & _report, const ByteCount &expectedFileSize_r, RequestOptions options = OPTION_NONE ) const override;
 
   void multifetch(const Pathname &filename, FILE *fp, std::vector<Url> *urllist, callback::SendReport<DownloadProgressReport> *report = 0, MediaBlockList *blklist = 0, off_t filesize = off_t(-1)) const;
 
index 63c1fc5..787d73d 100644 (file)
@@ -210,9 +210,9 @@ namespace zypp {
     //
     // DESCRIPTION : Asserted that media is attached.
     //
-    void MediaNFS::getFile (const Pathname & filename) const
+    void MediaNFS::getFile (const Pathname & filename, const ByteCount &expectedFileSize_r) const
     {
-      MediaHandler::getFile( filename );;
+      MediaHandler::getFile( filename, expectedFileSize_r );
     }
 
     ///////////////////////////////////////////////////////////////////
index eea5daf..bcc084c 100644 (file)
@@ -40,7 +40,7 @@ namespace zypp {
        virtual void attachTo (bool next = false);
 
         virtual void releaseFrom( const std::string & ejectDev );
-       virtual void getFile( const Pathname & filename ) const;
+       virtual void getFile( const Pathname & filename, const ByteCount &expectedFileSize_r ) const;
        virtual void getDir( const Pathname & dirname, bool recurse_r ) const;
         virtual void getDirInfo( std::list<std::string> & retlist,
                                  const Pathname & dirname, bool dots = true ) const;
index 76b75b3..fcb9f09 100644 (file)
@@ -39,7 +39,7 @@ namespace zypp
     void MediaPlugin::releaseFrom( const std::string & ejectDev_r )
     {}
 
-    void MediaPlugin::getFile( const Pathname & filename_r ) const
+    void MediaPlugin::getFile(const Pathname & filename_r , const ByteCount expectedFileSize_r) const
     {}
 
     void MediaPlugin::getDir( const Pathname & dirname_r, bool recurse_r ) const
index 2b68ace..fd47dc9 100644 (file)
@@ -36,7 +36,7 @@ namespace zypp
       protected:
        virtual void attachTo( bool next_r = false );
        virtual void releaseFrom( const std::string & ejectDev_r );
-       virtual void getFile( const Pathname & filename_r ) const;
+       virtual void getFile( const Pathname & filename_r, const ByteCount expectedFileSize_r ) const;
        virtual void getDir( const Pathname & dirname_r, bool recurse_r ) const;
        virtual void getDirInfo( std::list<std::string> & retlist_r, const Pathname & dirname_r, bool dots_r = true ) const;
        virtual void getDirInfo( filesystem::DirContent & retlist_r, const Pathname & dirname_r, bool dots_r = true ) const;
index 6163a78..a2a2cca 100644 (file)
@@ -165,6 +165,15 @@ namespace zypp
         return true;
       }
 
+      // xpath: /repomd/size
+      if ( reader_r->name() == "size" )
+      {
+        string size_value = reader_r.nodeText().asString();
+        zypp::ByteCount size = zypp::ByteCount( str::strtonum<ByteCount::SizeType>( size_value ) );
+        _location.setDownloadSize( size );
+        return true;
+      }
+
       //! \todo xpath: /repomd/open-checksum (?)
     }
 
index 2f36b03..332b72b 100644 (file)
@@ -52,8 +52,8 @@ void Downloader::defaultDownloadMasterIndex( MediaSetAccess & media_r, const Pat
   Pathname keypath = masterIndex_r.extend( ".key" );
 
   // always download them, even if repoGpgCheck is disabled
-  enqueue( OnMediaLocation( sigpath, 1 ).setOptional( true ) );
-  enqueue( OnMediaLocation( keypath, 1 ).setOptional( true ) );
+  enqueue( OnMediaLocation( sigpath, 1 ).setOptional( true ).setDownloadSize( ByteCount( 20, ByteCount::MB ) ) );
+  enqueue( OnMediaLocation( keypath, 1 ).setOptional( true ).setDownloadSize( ByteCount( 20, ByteCount::MB ) ) );
   start( destdir_r, media_r );
   reset();
 
@@ -91,7 +91,7 @@ void Downloader::defaultDownloadMasterIndex( MediaSetAccess & media_r, const Pat
     WAR << "Signature checking disabled in config of repository " << repoInfo().alias() << endl;
   }
 
-  enqueue( OnMediaLocation( masterIndex_r, 1 ), checker ? checker : FileChecker(NullFileChecker()) );
+  enqueue( OnMediaLocation( masterIndex_r, 1 ).setDownloadSize( ByteCount( 20, ByteCount::MB ) ), checker ? checker : FileChecker(NullFileChecker()) );
   start( destdir_r, media_r );
   reset();
 
index 9c35864..4df4593 100644 (file)
@@ -27,7 +27,10 @@ void downloadMediaInfo( const Pathname &dest_dir,
                         const ProgressData::ReceiverFnc & progressrcv )
 {
   Fetcher fetcher;
-  fetcher.enqueue( OnMediaLocation("/media.1/media") );
+
+  //hardcode the max filesize to 20MB, to prevent unlimited data downloads but this limit will
+  //never be reached in a sane setup
+  fetcher.enqueue( OnMediaLocation("/media.1/media").setDownloadSize( ByteCount(20, ByteCount::MB ) ) );
   fetcher.start( dest_dir, media, progressrcv );
   // ready, go!
   fetcher.reset();
index 1a91de6..3d920e3 100644 (file)
@@ -8,6 +8,7 @@
 \---------------------------------------------------------------------*/
 
 #include <fstream>
+#include "zypp/base/Logger.h"
 #include "zypp/repo/SUSEMediaVerifier.h"
 
 using namespace std;
@@ -31,7 +32,7 @@ SUSEMediaVerifier::SUSEMediaVerifier( int media_nr, const Pathname &path_r )
   std::ifstream str(path_r.asString().c_str());
   std::string vendor;
   std::string id;
-  
+
   if ( str )
   {
     getline(str, _media_vendor);
@@ -49,17 +50,23 @@ bool SUSEMediaVerifier::isDesiredMedia(const media::MediaAccessRef &ref)
   if (_media_vendor.empty() || _media_id.empty())
     return true;
 
-    Pathname media_file = "/media." + str::numstring(_media_nr) + "/media";
-    ref->provideFile (media_file);
-    media_file = ref->localPath(media_file);
-    std::ifstream str(media_file.asString().c_str());
-    std::string vendor;
-    std::string id;
-#warning check the stream status
-    getline(str, vendor);
-    getline(str, id);
+  Pathname media_file = "/media." + str::numstring(_media_nr) + "/media";
+  ref->provideFile (media_file, 0);
+  media_file = ref->localPath(media_file);
+  std::ifstream str(media_file.asString().c_str());
+  std::string vendor;
+  std::string id;
+  getline(str, vendor);
+  getline(str, id);
 
-    return (vendor == _media_vendor && id == _media_id );
+  bool ret = ( vendor == _media_vendor && id == _media_id  );
+  if ( !ret ) {
+    DBG << "cached vendor: " << _media_vendor << endl;
+    DBG << "repo vendor: " << vendor << endl;
+    DBG << "cached id: " << _media_id << endl;
+    DBG << "repo id: " << id << endl;
+  }
+  return ret;
 }
 
 }