]> cygwin.com Git - cygwin-apps/setup.git/blame - download.cc
2002-07-15 Robert Collins <rbtcollins@hotmail.com>
[cygwin-apps/setup.git] / download.cc
CommitLineData
23c9e63c 1/*
9fe1181b 2 * Copyright (c) 2000, 2001, Red Hat, Inc.
23c9e63c
DD
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * A copy of the GNU General Public License can be found at
10 * http://www.gnu.org/
11 *
12 * Written by DJ Delorie <dj@cygnus.com>
13 *
14 */
15
16/* The purpose of this file is to download all the files we need to
17 do the installation. */
18
b24c88b3
RC
19#if 0
20static const char *cvsid =
21 "\n%%% $Id$\n";
22#endif
8507f105 23
aa1e3b4d
RC
24#include "download.h"
25
23c9e63c
DD
26#include "win32.h"
27
28#include <stdio.h>
42bf5b92 29#include <unistd.h>
ab57ceaa 30#include <process.h>
23c9e63c
DD
31
32#include "resource.h"
33#include "msg.h"
23c9e63c 34#include "dialog.h"
3c054baf 35#include "String++.h"
23c9e63c
DD
36#include "geturl.h"
37#include "state.h"
aa1e3b4d 38#include "LogSingleton.h"
341988b9 39#include "filemanip.h"
23c9e63c 40
bb849dbd
RC
41#include "io_stream.h"
42
43#include "package_db.h"
44#include "package_meta.h"
45#include "package_version.h"
46#include "package_source.h"
47
48#include "rfc1738.h"
49
ab57ceaa 50#include "threebar.h"
58ee6135
RC
51
52#include "md5.h"
53
54#include "Exception.h"
55
ab57ceaa
RC
56extern ThreeBarProgressPage Progress;
57
aa1e3b4d
RC
58
59bool
60validateCachedPackage (String const &fullname, packagesource & pkgsource)
61{
62 if (pkgsource.md5.isSet())
63 {
64 // check the MD5 sum of the cached file here
65 io_stream *thefile = io_stream::open (fullname, "rb");
66 if (!thefile)
67 return 0;
68 md5_state_t pns;
69 md5_init (&pns);
70
71 log (LOG_BABBLE) << "Checking MD5 for " << fullname << endLog;
72
73 Progress.SetText1 ((String ("Checking MD5 for ") + pkgsource.Base()).cstr_oneuse());
74 Progress.SetText4 ("Progress:");
75 Progress.SetBar1 (0);
76
77 unsigned char buffer[16384];
78 ssize_t count;
79 while ((count = thefile->read (buffer, 16384)) > 0)
80 {
81 md5_append (&pns, buffer, count);
82 Progress.SetBar1 (thefile->tell(), thefile->get_size());
83 }
84 delete thefile;
85 if (count < 0)
86 throw new Exception ("__LINE__ __FILE__", (String ("IO Error reading ") + pkgsource.Cached()).cstr_oneuse(), APPERR_IO_ERROR);
87
88 md5_byte_t tempdigest[16];
89 md5_finish(&pns, tempdigest);
90 md5 tempMD5;
91 tempMD5.set (tempdigest);
92
93 log (LOG_BABBLE) << "For file '" << fullname <<
94 " ini digest is " << pkgsource.md5.print() <<
95 " file digest is " << tempMD5.print() << endLog;
96
97 if (pkgsource.md5 != tempMD5)
98 return false;
99 }
100 return true;
101}
102
bb849dbd
RC
103/* 0 on failure
104 */
58ee6135 105int
bb849dbd 106check_for_cached (packagesource & pkgsource)
3b9077d4 107{
bb849dbd
RC
108 /* search algo:
109 1) is there a legacy version in the cache dir available.
110 (Note that the cache dir is represented by a mirror site of
111 file://local_dir
112 */
3b9077d4 113
58ee6135
RC
114 // Already found one.
115 if (pkgsource.Cached())
116 return 1;
e0a4db64
RC
117
118 String prefix = String ("file://") + local_dir + "/";
88a77116 119 DWORD size;
e0a4db64 120 if ((size = get_file_size (prefix + pkgsource.Canonical ())) > 0)
bb849dbd
RC
121 if (size == pkgsource.size)
122 {
aa1e3b4d
RC
123 if (validateCachedPackage (prefix + pkgsource.Canonical (), pkgsource))
124 pkgsource.set_cached (prefix + pkgsource.Canonical ());
125 else
126 throw new Exception ("__LINE__ __FILE__", (String ("Package validation failure for ") + prefix + pkgsource.Canonical ()).cstr_oneuse(), APPERR_CORRUPT_PACKAGE);
bb849dbd
RC
127 return 1;
128 }
3b9077d4 129
bb849dbd
RC
130 /*
131 2) is there a version from one of the selected mirror sites available ?
132 */
3f34f364
RC
133 for (packagesource::sitestype::const_iterator n = pkgsource.sites.begin();
134 n != pkgsource.sites.end(); ++n)
58ee6135 135 {
3f34f364 136 String fullname = prefix + rfc1738_escape_part (n->key) + "/" +
58ee6135 137 pkgsource.Canonical ();
e0a4db64 138 if ((size = get_file_size (fullname)) > 0)
bb849dbd
RC
139 if (size == pkgsource.size)
140 {
aa1e3b4d
RC
141 if (validateCachedPackage (fullname, pkgsource))
142 pkgsource.set_cached (fullname );
143 else
144 throw new Exception ("__LINE__ __FILE__", (String ("Package validation failure for ") + fullname).cstr_oneuse(), APPERR_CORRUPT_PACKAGE);
bb849dbd
RC
145 return 1;
146 }
aa1e3b4d 147 }
bb849dbd
RC
148 return 0;
149}
150
151/* download a file from a mirror site to the local cache. */
152static int
ab57ceaa 153download_one (packagesource & pkgsource, HWND owner)
bb849dbd 154{
58ee6135
RC
155 try
156 {
157 if (check_for_cached (pkgsource))
158 return 0;
159 }
160 catch (Exception * e)
161 {
162 // We know what to do with these..
163 if (e->errNo() == APPERR_CORRUPT_PACKAGE)
164 {
165 fatal (owner, IDS_CORRUPT_PACKAGE, pkgsource.Canonical());
166 return 1;
167 }
168 // Unexpected exception.
169 throw e;
170 }
bb849dbd
RC
171 /* try the download sites one after another */
172
173 int success = 0;
3f34f364
RC
174 for (packagesource::sitestype::const_iterator n = pkgsource.sites.begin();
175 n != pkgsource.sites.end() && !success; ++n)
d4a4527d 176 {
3c054baf 177 String const local = local_dir + "/" +
3f34f364 178 rfc1738_escape_part (n->key) + "/" +
3c054baf 179 pkgsource.Canonical ();
1ac649ed 180 io_stream::mkpath_p (PATH_TO_FILE, String ("file://") + local);
3c054baf 181
3f34f364 182 if (get_url_to_file(n->key + "/" + pkgsource.Canonical (),
1ac649ed 183 local + ".tmp", pkgsource.size, owner))
3b9077d4 184 {
bb849dbd
RC
185 /* FIXME: note new source ? */
186 continue;
3b9077d4
DD
187 }
188 else
189 {
e0a4db64 190 size_t size = get_file_size (String("file://") + local + ".tmp");
bb849dbd
RC
191 if (size == pkgsource.size)
192 {
aa1e3b4d 193 log (LOG_PLAIN) << "Downloaded " << local << endLog;
3c054baf
RC
194 if (_access (local.cstr_oneuse(), 0) == 0)
195 remove (local.cstr_oneuse());
196 rename ((local + ".tmp").cstr_oneuse(), local.cstr_oneuse());
bb849dbd 197 success = 1;
3c054baf
RC
198 pkgsource.set_cached (String ("file://") + local);
199 // FIXME: move the downloaded file to the
200 // original locations - without the mirror site dir in the way
bb849dbd
RC
201 continue;
202 }
203 else
204 {
aa1e3b4d
RC
205 log (LOG_PLAIN) << "Download " << local << " wrong size (" <<
206 size << " actual vs " << pkgsource.size << " expected)" <<
207 endLog;
3c054baf 208 remove ((local + ".tmp").cstr_oneuse());
bb849dbd
RC
209 continue;
210 }
3b9077d4
DD
211 }
212 }
bb849dbd
RC
213 if (success)
214 return 0;
215 /* FIXME: Do we want to note this? if so how? */
216 return 1;
3b9077d4
DD
217}
218
ab57ceaa
RC
219static void
220do_download_thread (HINSTANCE h, HWND owner)
23c9e63c 221{
2a1a01e0 222 int errors = 0;
2f9645a1
CV
223 total_download_bytes = 0;
224 total_download_bytes_sofar = 0;
225
bb849dbd
RC
226 packagedb db;
227 /* calculate the amount needed */
cfae3b8d
RC
228 for (vector <packagemeta *>::iterator i = db.packages.begin ();
229 i != db.packages.end (); ++i)
cbfc4215 230 {
cfae3b8d 231 packagemeta & pkg = **i;
3c196821 232 if (pkg.desired.changeRequested())
ab57ceaa 233 {
3c196821
RC
234 packageversion version = pkg.desired;
235 packageversion sourceversion = version.sourcePackage();
58ee6135
RC
236 try
237 {
3c196821
RC
238 if (version.picked() && !check_for_cached (*version.source()))
239 total_download_bytes += version.source()->size;
240 if (sourceversion.picked ()
241 && !check_for_cached (*sourceversion.source()))
242 total_download_bytes += sourceversion.source()->size;
58ee6135
RC
243 }
244 catch (Exception * e)
245 {
246 // We know what to do with these..
247 if (e->errNo() == APPERR_CORRUPT_PACKAGE)
248 fatal (owner, IDS_CORRUPT_PACKAGE, pkg.name.cstr_oneuse());
249 // Unexpected exception.
250 throw e;
251 }
ab57ceaa 252 }
cbfc4215 253 }
23c9e63c 254
bb849dbd
RC
255 /* and do the download. FIXME: This here we assign a new name for the cached version
256 * and check that above.
257 */
cfae3b8d
RC
258 for (vector <packagemeta *>::iterator i = db.packages.begin ();
259 i != db.packages.end (); ++i)
cbfc4215 260 {
cfae3b8d 261 packagemeta & pkg = **i;
3c196821 262 if (pkg.desired.changeRequested())
ab57ceaa
RC
263 {
264 int e = 0;
3c196821
RC
265 packageversion version = pkg.desired;
266 packageversion sourceversion = version.sourcePackage();
267 if (version.picked())
268 e += download_one (*version.source(), owner);
269 if (sourceversion && sourceversion.picked())
4f591f9d 270 e += download_one (*sourceversion.source(), owner);
ab57ceaa 271 errors += e;
bb849dbd 272#if 0
ab57ceaa
RC
273 if (e)
274 pkg->action = ACTION_ERROR;
bb849dbd 275#endif
ab57ceaa 276 }
cbfc4215 277 }
23c9e63c 278
2a1a01e0
DD
279 if (errors)
280 {
ab57ceaa 281 if (yesno (owner, IDS_DOWNLOAD_INCOMPLETE) == IDYES)
2a1a01e0
DD
282 {
283 next_dialog = IDD_SITE;
284 return;
285 }
286 }
287
bf1d5889
DD
288 if (source == IDC_SOURCE_DOWNLOAD)
289 {
2a1a01e0
DD
290 if (errors)
291 exit_msg = IDS_DOWNLOAD_INCOMPLETE;
292 else
293 exit_msg = IDS_DOWNLOAD_COMPLETE;
bf1d5889
DD
294 next_dialog = 0;
295 }
296 else
297 next_dialog = IDD_S_INSTALL;
23c9e63c 298}
ab57ceaa 299
45e01f23 300static DWORD WINAPI
ab57ceaa
RC
301do_download_reflector (void *p)
302{
303 HANDLE *context;
304 context = (HANDLE *) p;
305
306 do_download_thread ((HINSTANCE) context[0], (HWND) context[1]);
307
308 // Tell the progress page that we're done downloading
309 Progress.PostMessage (WM_APP_DOWNLOAD_THREAD_COMPLETE, 0, next_dialog);
310
45e01f23 311 ExitThread(0);
ab57ceaa
RC
312}
313
314static HANDLE context[2];
315
316void
317do_download (HINSTANCE h, HWND owner)
318{
319 context[0] = h;
320 context[1] = owner;
321
45e01f23
RC
322 DWORD threadID;
323 CreateThread (NULL, 0, do_download_reflector, context, 0, &threadID);
ab57ceaa 324}
This page took 0.069099 seconds and 5 git commands to generate.