]> cygwin.com Git - cygwin-apps/setup.git/blobdiff - download.cc
2002-07-15 Robert Collins <rbtcollins@hotmail.com>
[cygwin-apps/setup.git] / download.cc
index 0052de23627199df5c5f15513230687d0df55789..6a375a9c84172106369d039e1c58ee41388bfefb 100644 (file)
@@ -21,6 +21,8 @@ static const char *cvsid =
   "\n%%% $Id$\n";
 #endif
 
+#include "download.h"
+  
 #include "win32.h"
 
 #include <stdio.h>
@@ -29,15 +31,12 @@ static const char *cvsid =
 
 #include "resource.h"
 #include "msg.h"
-#include "ini.h"
 #include "dialog.h"
 #include "String++.h"
 #include "geturl.h"
 #include "state.h"
-#include "mkdir.h"
-#include "log.h"
+#include "LogSingleton.h"
 #include "filemanip.h"
-#include "port.h"
 
 #include "io_stream.h"
 
@@ -49,11 +48,61 @@ static const char *cvsid =
 #include "rfc1738.h"
 
 #include "threebar.h"
+
+#include "md5.h"
+
+#include "Exception.h"
+
 extern ThreeBarProgressPage Progress;
 
+
+bool
+validateCachedPackage (String const &fullname, packagesource & pkgsource)
+{
+  if (pkgsource.md5.isSet())
+    {
+      // check the MD5 sum of the cached file here
+      io_stream *thefile = io_stream::open (fullname, "rb");
+      if (!thefile)
+       return 0;
+      md5_state_t pns;
+      md5_init (&pns);
+
+      log (LOG_BABBLE) << "Checking MD5 for " << fullname << endLog;
+
+      Progress.SetText1 ((String ("Checking MD5 for ") + pkgsource.Base()).cstr_oneuse());
+      Progress.SetText4 ("Progress:");
+      Progress.SetBar1 (0);
+      
+      unsigned char buffer[16384];
+      ssize_t count;
+      while ((count = thefile->read (buffer, 16384)) > 0)
+       {
+         md5_append (&pns, buffer, count);
+         Progress.SetBar1 (thefile->tell(), thefile->get_size());
+       }
+      delete thefile;
+      if (count < 0)
+       throw new Exception ("__LINE__ __FILE__", (String ("IO Error reading ") + pkgsource.Cached()).cstr_oneuse(), APPERR_IO_ERROR);
+      
+      md5_byte_t tempdigest[16];
+      md5_finish(&pns, tempdigest);
+      md5 tempMD5;
+      tempMD5.set (tempdigest);
+      
+      log (LOG_BABBLE) << "For file '" << fullname << 
+          " ini digest is " << pkgsource.md5.print() <<
+          " file digest is " << tempMD5.print() << endLog;
+      
+      if (pkgsource.md5 != tempMD5)
+       return false;
+    }
+  return true;
+}
+
 /* 0 on failure
  */
-static int
+int
 check_for_cached (packagesource & pkgsource)
 {
   /* search algo:
@@ -62,35 +111,40 @@ check_for_cached (packagesource & pkgsource)
      file://local_dir
    */
 
+  // Already found one.
+  if (pkgsource.Cached())
+    return 1;
+  
+  String prefix = String ("file://") + local_dir +  "/";
   DWORD size;
-  if ((size =
-       get_file_size (local_dir +  "/" + pkgsource.Canonical ())) >
-      0)
+  if ((size = get_file_size (prefix + pkgsource.Canonical ())) > 0)
     if (size == pkgsource.size)
       {
-       pkgsource.
-         set_cached (String ("file://") + local_dir +  "/" + pkgsource.Canonical ());
+       if (validateCachedPackage (prefix + pkgsource.Canonical (), pkgsource))
+         pkgsource.set_cached (prefix + pkgsource.Canonical ());
+       else
+         throw new Exception ("__LINE__ __FILE__", (String ("Package validation failure for ") + prefix + pkgsource.Canonical ()).cstr_oneuse(), APPERR_CORRUPT_PACKAGE);
        return 1;
       }
 
   /*
      2) is there a version from one of the selected mirror sites available ?
    */
-  for (size_t n = 1; n <= pkgsource.sites.number (); n++)
-    if ((size =
-        get_file_size (local_dir + "/" +
-                        rfc1738_escape_part (pkgsource.sites[n]->key) + "/" +
-                        pkgsource.Canonical ())) > 0)
+  for (packagesource::sitestype::const_iterator n = pkgsource.sites.begin();
+       n != pkgsource.sites.end(); ++n)
+    {
+      String fullname = prefix + rfc1738_escape_part (n->key) + "/" +
+       pkgsource.Canonical ();
+    if ((size = get_file_size (fullname)) > 0)
       if (size == pkgsource.size)
        {
-         pkgsource.
-           set_cached (String ("file://") + local_dir + "/" +
-                        rfc1738_escape_part (pkgsource.sites[n]->
-                                             key) + "/" +
-                        pkgsource.Canonical ());
+         if (validateCachedPackage (fullname, pkgsource))
+           pkgsource.set_cached (fullname );
+         else
+           throw new Exception ("__LINE__ __FILE__", (String ("Package validation failure for ") + fullname).cstr_oneuse(), APPERR_CORRUPT_PACKAGE);
          return 1;
        }
-
+    }
   return 0;
 }
 
@@ -98,22 +152,34 @@ check_for_cached (packagesource & pkgsource)
 static int
 download_one (packagesource & pkgsource, HWND owner)
 {
-  if (check_for_cached (pkgsource) && source != IDC_SOURCE_DOWNLOAD)
-    return 0;
-
+  try
+    {
+      if (check_for_cached (pkgsource))
+        return 0;
+    }
+  catch (Exception * e)
+    {
+      // We know what to do with these..
+      if (e->errNo() == APPERR_CORRUPT_PACKAGE)
+       {
+         fatal (owner, IDS_CORRUPT_PACKAGE, pkgsource.Canonical());
+         return 1;
+       }
+      // Unexpected exception.
+      throw e;
+    }
   /* try the download sites one after another */
 
   int success = 0;
-  for (size_t n = 1; n <= pkgsource.sites.number () && !success; n++)
+  for (packagesource::sitestype::const_iterator n = pkgsource.sites.begin();
+       n != pkgsource.sites.end() && !success; ++n)
     {
       String const local = local_dir + "/" +
-                                 rfc1738_escape_part (pkgsource.sites[n]->
-                                                      key) + "/" +
+                                 rfc1738_escape_part (n->key) + "/" +
                                  pkgsource.Canonical ();
       io_stream::mkpath_p (PATH_TO_FILE, String ("file://") + local);
 
-      if (get_url_to_file(pkgsource.sites[n]->key +  "/" +
-                         pkgsource.Canonical (),
+      if (get_url_to_file(n->key +  "/" + pkgsource.Canonical (),
                          local + ".tmp", pkgsource.size, owner))
        {
          /* FIXME: note new source ? */
@@ -121,10 +187,10 @@ download_one (packagesource & pkgsource, HWND owner)
        }
       else
        {
-         size_t size = get_file_size (local + ".tmp");
+         size_t size = get_file_size (String("file://") + local + ".tmp");
          if (size == pkgsource.size)
            {
-             log (LOG_PLAIN, String ("Downloaded ") + local);
+             log (LOG_PLAIN) << "Downloaded " << local << endLog;
              if (_access (local.cstr_oneuse(), 0) == 0)
                remove (local.cstr_oneuse());
              rename ((local + ".tmp").cstr_oneuse(), local.cstr_oneuse());
@@ -136,9 +202,9 @@ download_one (packagesource & pkgsource, HWND owner)
            }
          else
            {
-             log (LOG_PLAIN,
-                  "Download %s wrong size (%u actual vs %d expected)",
-                  local.cstr_oneuse(), size, pkgsource.size);
+             log (LOG_PLAIN) << "Download " << local << " wrong size (" <<
+               size << " actual vs " << pkgsource.size << " expected)" << 
+               endLog;
              remove ((local + ".tmp").cstr_oneuse());
              continue;
            }
@@ -159,37 +225,70 @@ do_download_thread (HINSTANCE h, HWND owner)
 
   packagedb db;
   /* calculate the amount needed */
-  for (size_t n = 1; n <= db.packages.number (); n++)
+  for (vector <packagemeta *>::iterator i = db.packages.begin ();
+       i != db.packages.end (); ++i)
     {
-      packagemeta & pkg = *db.packages[n];
-      if (pkg.desired && (pkg.desired->srcpicked || pkg.desired->binpicked))
+      packagemeta & pkg = **i;
+      if (pkg.desired.changeRequested())
        {
-         packageversion *version = pkg.desired;
-         if (!
-             (check_for_cached (version->bin)
-              && source != IDC_SOURCE_DOWNLOAD) && pkg.desired->binpicked)
-           total_download_bytes += version->bin.size;
-         if (!
-             (check_for_cached (version->src)
-              && source != IDC_SOURCE_DOWNLOAD) && pkg.desired->srcpicked)
-           total_download_bytes += version->src.size;
+         packageversion version = pkg.desired;
+         packageversion sourceversion = version.sourcePackage();
+         try 
+           {
+             if (version.picked())
+               {
+                 for (vector<packagesource>::iterator i = 
+                      version.sources ()->begin(); 
+                      i != version.sources ()->end(); ++i)
+                   if (!check_for_cached (*i))
+                     total_download_bytes += i->size;
+               }
+             if (sourceversion.picked ())
+               {
+                 for (vector<packagesource>::iterator i =
+                      sourceversion.sources ()->begin();
+                      i != sourceversion.sources ()->end(); ++i)
+                   if (!check_for_cached (*i))
+                     total_download_bytes += i->size;
+               }
+           }
+         catch (Exception * e)
+           {
+             // We know what to do with these..
+             if (e->errNo() == APPERR_CORRUPT_PACKAGE)
+               fatal (owner, IDS_CORRUPT_PACKAGE, pkg.name.cstr_oneuse());
+             // Unexpected exception.
+             throw e;
+           }
        }
     }
 
   /* and do the download. FIXME: This here we assign a new name for the cached version
    * and check that above.
    */
-  for (size_t n = 1; n <= db.packages.number (); n++)
+  for (vector <packagemeta *>::iterator i = db.packages.begin ();
+       i != db.packages.end (); ++i)
     {
-      packagemeta & pkg = *db.packages[n];
-      if (pkg.desired && (pkg.desired->srcpicked || pkg.desired->binpicked))
+      packagemeta & pkg = **i;
+      if (pkg.desired.changeRequested())
        {
          int e = 0;
-         packageversion *version = pkg.desired;
-         if (version->binpicked)
-           e += download_one (version->bin, owner);
-         if (version->srcpicked)
-           e += download_one (version->src, owner);
+         packageversion version = pkg.desired;
+         packageversion sourceversion = version.sourcePackage();
+         if (version.picked())
+           {
+             for (vector<packagesource>::iterator i =
+                  version.sources ()->begin();
+                  i != version.sources ()->end(); ++i)
+               e += download_one (*i, owner);
+           }
+         if (sourceversion && sourceversion.picked())
+           {
+             for (vector<packagesource>::iterator i =
+                  sourceversion.sources ()->begin();
+                  i != sourceversion.sources ()->end(); ++i)
+               e += download_one (*i, owner);
+           }
          errors += e;
 #if 0
          if (e)
@@ -219,7 +318,7 @@ do_download_thread (HINSTANCE h, HWND owner)
     next_dialog = IDD_S_INSTALL;
 }
 
-static void
+static DWORD WINAPI
 do_download_reflector (void *p)
 {
   HANDLE *context;
@@ -230,7 +329,7 @@ do_download_reflector (void *p)
   // Tell the progress page that we're done downloading
   Progress.PostMessage (WM_APP_DOWNLOAD_THREAD_COMPLETE, 0, next_dialog);
 
-  _endthread ();
+  ExitThread(0);
 }
 
 static HANDLE context[2];
@@ -241,5 +340,6 @@ do_download (HINSTANCE h, HWND owner)
   context[0] = h;
   context[1] = owner;
 
-  _beginthread (do_download_reflector, 0, context);
+  DWORD threadID;
+  CreateThread (NULL, 0, do_download_reflector, context, 0, &threadID);
 }
This page took 0.033933 seconds and 5 git commands to generate.