X-Git-Url: https://cygwin.com/git/?a=blobdiff_plain;f=download.cc;h=6a375a9c84172106369d039e1c58ee41388bfefb;hb=ec13f13ca57fba24a53d873e9aa80527fc0b8134;hp=aef6048c321043e0a593064ed67a16c9b0fcc029;hpb=3b9077d47e1f278beb96490180ebf65b0b01ef71;p=cygwin-apps%2Fsetup.git diff --git a/download.cc b/download.cc index aef6048c..6a375a9c 100644 --- a/download.cc +++ b/download.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, Red Hat, Inc. + * Copyright (c) 2000, 2001, Red Hat, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,88 +16,290 @@ /* The purpose of this file is to download all the files we need to do the installation. */ -static char *cvsid = "\n%%% $Id$\n"; +#if 0 +static const char *cvsid = + "\n%%% $Id$\n"; +#endif +#include "download.h" + #include "win32.h" #include -#include -#include +#include +#include #include "resource.h" #include "msg.h" -#include "ini.h" #include "dialog.h" -#include "concat.h" +#include "String++.h" #include "geturl.h" #include "state.h" -#include "mkdir.h" -#include "log.h" +#include "LogSingleton.h" +#include "filemanip.h" -#define pi (package[i].info[package[i].trust]) +#include "io_stream.h" -static int -download_one (char *name, int expected_size) +#include "package_db.h" +#include "package_meta.h" +#include "package_version.h" +#include "package_source.h" + +#include "rfc1738.h" + +#include "threebar.h" + +#include "md5.h" + +#include "Exception.h" + +extern ThreeBarProgressPage Progress; + + +bool +validateCachedPackage (String const &fullname, packagesource & pkgsource) { - char *local = name; - int errors = 0; + 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; +} - struct stat s; - if (stat (local, &s) >= 0) - if (s.st_size == expected_size) - return 0; +/* 0 on failure + */ +int +check_for_cached (packagesource & pkgsource) +{ + /* search algo: + 1) is there a legacy version in the cache dir available. + (Note that the cache dir is represented by a mirror site of + file://local_dir + */ - mkdir_p (0, local); + // Already found one. + if (pkgsource.Cached()) + return 1; + + String prefix = String ("file://") + local_dir + "/"; + DWORD size; + if ((size = get_file_size (prefix + pkgsource.Canonical ())) > 0) + if (size == pkgsource.size) + { + 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; + } - if (get_url_to_file (concat (MIRROR_SITE, "/", name, 0), - concat (local, ".tmp", 0), - expected_size)) + /* + 2) is there a version from one of the selected mirror sites available ? + */ + for (packagesource::sitestype::const_iterator n = pkgsource.sites.begin(); + n != pkgsource.sites.end(); ++n) { - note (IDS_DOWNLOAD_FAILED, name); - return 1; + String fullname = prefix + rfc1738_escape_part (n->key) + "/" + + pkgsource.Canonical (); + if ((size = get_file_size (fullname)) > 0) + if (size == pkgsource.size) + { + 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; + } } - else + return 0; +} + +/* download a file from a mirror site to the local cache. */ +static int +download_one (packagesource & pkgsource, HWND owner) +{ + try + { + if (check_for_cached (pkgsource)) + return 0; + } + catch (Exception * e) { - stat (concat (local, ".tmp", 0), &s); - if (s.st_size == expected_size) + // We know what to do with these.. + if (e->errNo() == APPERR_CORRUPT_PACKAGE) { - log (0, "Downloaded %s", local); - rename (concat (local, ".tmp", 0), local); + fatal (owner, IDS_CORRUPT_PACKAGE, pkgsource.Canonical()); + return 1; + } + // Unexpected exception. + throw e; + } + /* try the download sites one after another */ + + int success = 0; + for (packagesource::sitestype::const_iterator n = pkgsource.sites.begin(); + n != pkgsource.sites.end() && !success; ++n) + { + String const local = local_dir + "/" + + rfc1738_escape_part (n->key) + "/" + + pkgsource.Canonical (); + io_stream::mkpath_p (PATH_TO_FILE, String ("file://") + local); + + if (get_url_to_file(n->key + "/" + pkgsource.Canonical (), + local + ".tmp", pkgsource.size, owner)) + { + /* FIXME: note new source ? */ + continue; } else { - log (0, "Download %s wrong size (%d actual vs %d expected)", - local, s.st_size, expected_size); - note (IDS_DOWNLOAD_SHORT, local, s.st_size, expected_size); - return 1; + size_t size = get_file_size (String("file://") + local + ".tmp"); + if (size == pkgsource.size) + { + 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()); + success = 1; + pkgsource.set_cached (String ("file://") + local); + // FIXME: move the downloaded file to the + // original locations - without the mirror site dir in the way + continue; + } + else + { + log (LOG_PLAIN) << "Download " << local << " wrong size (" << + size << " actual vs " << pkgsource.size << " expected)" << + endLog; + remove ((local + ".tmp").cstr_oneuse()); + continue; + } } } - - return 0; + if (success) + return 0; + /* FIXME: Do we want to note this? if so how? */ + return 1; } -void -do_download (HINSTANCE h) +static void +do_download_thread (HINSTANCE h, HWND owner) { - int i; int errors = 0; + total_download_bytes = 0; + total_download_bytes_sofar = 0; - for (i=0; i::iterator i = db.packages.begin (); + i != db.packages.end (); ++i) + { + packagemeta & pkg = **i; + if (pkg.desired.changeRequested()) + { + packageversion version = pkg.desired; + packageversion sourceversion = version.sourcePackage(); + try + { + if (version.picked()) + { + for (vector::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::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; + } + } + } - dismiss_url_status_dialog (); + /* and do the download. FIXME: This here we assign a new name for the cached version + * and check that above. + */ + for (vector ::iterator i = db.packages.begin (); + i != db.packages.end (); ++i) + { + packagemeta & pkg = **i; + if (pkg.desired.changeRequested()) + { + int e = 0; + packageversion version = pkg.desired; + packageversion sourceversion = version.sourcePackage(); + if (version.picked()) + { + for (vector::iterator i = + version.sources ()->begin(); + i != version.sources ()->end(); ++i) + e += download_one (*i, owner); + } + if (sourceversion && sourceversion.picked()) + { + for (vector::iterator i = + sourceversion.sources ()->begin(); + i != sourceversion.sources ()->end(); ++i) + e += download_one (*i, owner); + } + errors += e; +#if 0 + if (e) + pkg->action = ACTION_ERROR; +#endif + } + } if (errors) { - if (yesno (IDS_DOWNLOAD_INCOMPLETE) == IDYES) + if (yesno (owner, IDS_DOWNLOAD_INCOMPLETE) == IDYES) { next_dialog = IDD_SITE; return; @@ -115,3 +317,29 @@ do_download (HINSTANCE h) else next_dialog = IDD_S_INSTALL; } + +static DWORD WINAPI +do_download_reflector (void *p) +{ + HANDLE *context; + context = (HANDLE *) p; + + do_download_thread ((HINSTANCE) context[0], (HWND) context[1]); + + // Tell the progress page that we're done downloading + Progress.PostMessage (WM_APP_DOWNLOAD_THREAD_COMPLETE, 0, next_dialog); + + ExitThread(0); +} + +static HANDLE context[2]; + +void +do_download (HINSTANCE h, HWND owner) +{ + context[0] = h; + context[1] = owner; + + DWORD threadID; + CreateThread (NULL, 0, do_download_reflector, context, 0, &threadID); +}