]> cygwin.com Git - cygwin-apps/setup.git/blame - download.cc
Suggest URLs for updated setup based on build architecture
[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
946198be
MB
19#include "csu_util/rfc1738.h"
20
aa1e3b4d
RC
21#include "download.h"
22
23c9e63c
DD
23#include "win32.h"
24
25#include <stdio.h>
42bf5b92 26#include <unistd.h>
ab57ceaa 27#include <process.h>
dcbcbef3 28#include <vector>
23c9e63c
DD
29
30#include "resource.h"
31#include "msg.h"
23c9e63c 32#include "dialog.h"
23c9e63c
DD
33#include "geturl.h"
34#include "state.h"
5fa64c3c 35#include "LogFile.h"
341988b9 36#include "filemanip.h"
23c9e63c 37
bb849dbd
RC
38#include "io_stream.h"
39
40#include "package_db.h"
41#include "package_meta.h"
bb849dbd
RC
42#include "package_source.h"
43
ab57ceaa 44#include "threebar.h"
58ee6135 45
58ee6135
RC
46#include "Exception.h"
47
ab57ceaa
RC
48extern ThreeBarProgressPage Progress;
49
ff2cd3f4
KB
50// Return true if selected checks pass, false if they don't and the
51// user chooses to delete the file; otherwise throw an exception.
6beebaa3 52static bool
ff2cd3f4
KB
53validateCachedPackage (const std::string& fullname, packagesource & pkgsource,
54 HWND owner, bool check_hash, bool check_size)
aa1e3b4d 55{
ff2cd3f4
KB
56 try
57 {
58 if (check_size)
59 pkgsource.check_size_and_cache (fullname);
60 if (check_hash)
61 pkgsource.check_hash ();
62 return true;
63 }
64 catch (Exception *e)
65 {
66 pkgsource.set_cached ("");
67 const char *filename = fullname.c_str ();
68 if (strncmp (filename, "file://", 7) == 0)
69 filename += 7;
70 if (e->errNo() == APPERR_CORRUPT_PACKAGE
71 && yesno (owner, IDS_QUERY_CORRUPT, filename) == IDYES)
72 remove (filename);
73 else
74 throw e;
75 }
76 return false;
aa1e3b4d
RC
77}
78
ff2cd3f4 79/* 0 if not cached; may throw exception if validation fails.
bb849dbd 80 */
58ee6135 81int
ff2cd3f4
KB
82check_for_cached (packagesource & pkgsource, HWND owner, bool mirror_mode,
83 bool check_hash)
3b9077d4 84{
2ec74bb7
JT
85 /* If the packagesource doesn't have a filename, it can't possibly be in the
86 cache */
87 if (!pkgsource.Canonical())
88 {
89 return 0;
90 }
91
249e9360 92 /* Note that the cache dir is represented by a mirror site of file://local_dir */
2bba98e8 93 std::string prefix = "file://" + local_dir + "/";
2ec74bb7 94 std::string fullname = prefix + pkgsource.Canonical();
249e9360 95
f1486891
CV
96 if (mirror_mode)
97 {
98 /* Just assume correctness of mirror. */
ff2cd3f4
KB
99 if (!pkgsource.Cached())
100 pkgsource.set_cached (fullname);
f1486891
CV
101 return 1;
102 }
249e9360 103
ff2cd3f4
KB
104 // Already found one, which we can assume to have the right size.
105 if (pkgsource.Cached())
106 {
107 if (validateCachedPackage (pkgsource.Cached(), pkgsource, owner,
108 check_hash, false))
109 return 1;
110 // If we get here, pkgsource.Cached() was corrupt and deleted.
111 pkgsource.set_cached ("");
112 }
113
249e9360
JT
114 /*
115 1) is there a legacy version in the cache dir available.
116 */
f1486891
CV
117 if (io_stream::exists (fullname))
118 {
ff2cd3f4
KB
119 if (validateCachedPackage (fullname, pkgsource, owner, check_hash, true))
120 return 1;
121 // If we get here, fullname was corrupt and deleted, but it
122 // might have been cached.
123 pkgsource.set_cached ("");
f1486891 124 }
3b9077d4 125
bb849dbd
RC
126 /*
127 2) is there a version from one of the selected mirror sites available ?
249e9360 128 */
3f34f364
RC
129 for (packagesource::sitestype::const_iterator n = pkgsource.sites.begin();
130 n != pkgsource.sites.end(); ++n)
6beebaa3 131 {
2bba98e8 132 std::string fullname = prefix + rfc1738_escape_part (n->key) + "/" +
6beebaa3
MB
133 pkgsource.Canonical ();
134 if (io_stream::exists(fullname))
ff2cd3f4
KB
135 {
136 if (validateCachedPackage (fullname, pkgsource, owner, check_hash,
137 true))
138 return 1;
139 // If we get here, fullname was corrupt and deleted, but it
140 // might have been cached.
141 pkgsource.set_cached ("");
142 }
6beebaa3 143 }
bb849dbd
RC
144 return 0;
145}
146
147/* download a file from a mirror site to the local cache. */
148static int
ab57ceaa 149download_one (packagesource & pkgsource, HWND owner)
bb849dbd 150{
58ee6135
RC
151 try
152 {
ff2cd3f4 153 if (check_for_cached (pkgsource, owner))
58ee6135
RC
154 return 0;
155 }
156 catch (Exception * e)
157 {
158 // We know what to do with these..
159 if (e->errNo() == APPERR_CORRUPT_PACKAGE)
160 {
161 fatal (owner, IDS_CORRUPT_PACKAGE, pkgsource.Canonical());
162 return 1;
163 }
164 // Unexpected exception.
165 throw e;
166 }
bb849dbd
RC
167 /* try the download sites one after another */
168
169 int success = 0;
3f34f364
RC
170 for (packagesource::sitestype::const_iterator n = pkgsource.sites.begin();
171 n != pkgsource.sites.end() && !success; ++n)
d4a4527d 172 {
2bba98e8 173 const std::string local = local_dir + "/" +
3f34f364 174 rfc1738_escape_part (n->key) + "/" +
3c054baf 175 pkgsource.Canonical ();
d2a5fdfb 176 io_stream::mkpath_p (PATH_TO_FILE, "file://" + local, 0);
3c054baf 177
46826f23 178 if (get_url_to_file(n->key + pkgsource.Canonical (),
1ac649ed 179 local + ".tmp", pkgsource.size, owner))
3b9077d4 180 {
bb849dbd
RC
181 /* FIXME: note new source ? */
182 continue;
3b9077d4
DD
183 }
184 else
185 {
ff2cd3f4 186 try
bb849dbd 187 {
d2a3615c
MB
188 if (_access (local.c_str(), 0) == 0)
189 remove (local.c_str());
190 rename ((local + ".tmp").c_str(), local.c_str());
ff2cd3f4
KB
191 pkgsource.check_size_and_cache ("file://" + local);
192 pkgsource.check_hash ();
193 Log (LOG_PLAIN) << "Downloaded " << local << endLog;
bb849dbd 194 success = 1;
3c054baf
RC
195 // FIXME: move the downloaded file to the
196 // original locations - without the mirror site dir in the way
bb849dbd
RC
197 continue;
198 }
ff2cd3f4 199 catch (Exception *e)
bb849dbd 200 {
ff2cd3f4
KB
201 remove (local.c_str());
202 pkgsource.set_cached ("");
203 if (e->errNo() == APPERR_CORRUPT_PACKAGE)
204 {
205 Log (LOG_PLAIN) << "Downloaded file " << local
206 << " is corrupt; deleting." << endLog;
207 continue;
208 }
209 else
210 {
211 Log (LOG_PLAIN) << "Unexpected exception while validating "
212 << "downloaded file " << local
213 << "; deleting." << endLog;
214 throw e;
215 }
bb849dbd 216 }
3b9077d4
DD
217 }
218 }
bb849dbd
RC
219 if (success)
220 return 0;
bb849dbd 221 return 1;
3b9077d4
DD
222}
223
dcbcbef3
KB
224static std::vector <packageversion> download_failures;
225static std::string download_warn_pkgs;
226
227static INT_PTR CALLBACK
228download_error_proc (HWND h, UINT message, WPARAM wParam, LPARAM lParam)
229{
230 switch (message)
231 {
232 case WM_INITDIALOG:
233 eset (h, IDC_DOWNLOAD_EDIT, download_warn_pkgs);
234 SetFocus (GetDlgItem(h, IDRETRY));
235 return FALSE;
236
237 case WM_COMMAND:
238 switch (LOWORD (wParam))
239 {
240 case IDRETRY:
241 case IDC_BACK:
242 case IDIGNORE:
243 case IDABORT:
244 EndDialog (h, LOWORD (wParam));
245 default:
246 // Not reached.
247 return 0;
248 }
249
250 default:
251 // Not handled.
252 return FALSE;
253 }
254 return TRUE;
255}
256
257static int
258query_download_errors (HINSTANCE h, HWND owner)
259{
260 download_warn_pkgs = "";
261 Log (LOG_PLAIN) << "The following package(s) had download errors:" << endLog;
262 for (std::vector <packageversion>::const_iterator i = download_failures.begin (); i != download_failures.end (); i++)
263 {
264 packageversion pv = *i;
265 std::string pvs = pv.Name () + "-" + pv.Canonical_version ();
266 Log (LOG_PLAIN) << " " << pvs << endLog;
267 download_warn_pkgs += pvs + "\r\n";
268 }
269 return DialogBox (h, MAKEINTRESOURCE (IDD_DOWNLOAD_ERROR), owner,
270 download_error_proc);
271}
272
49560a44 273static int
ab57ceaa 274do_download_thread (HINSTANCE h, HWND owner)
23c9e63c 275{
2a1a01e0 276 int errors = 0;
2f9645a1
CV
277 total_download_bytes = 0;
278 total_download_bytes_sofar = 0;
dcbcbef3 279 download_failures.clear ();
2f9645a1 280
b3cc8ab6 281 Progress.SetText1 (IDS_PROGRESS_CHECKING);
39ae968f
JT
282 Progress.SetText2 ("");
283 Progress.SetText3 ("");
284
bb849dbd 285 packagedb db;
64f45db2
JT
286 const SolverTransactionList &t = db.solution.transactions();
287
288 /* calculate the total size of the download */
289 for (SolverTransactionList::const_iterator i = t.begin (); i != t.end (); ++i)
cbfc4215 290 {
c1f4069d
KB
291 if (i->type != SolverTransaction::transInstall)
292 continue;
64f45db2
JT
293 packageversion version = i->version;
294
295 try
296 {
297 if (!check_for_cached (*version.source(), owner))
298 total_download_bytes += version.source()->size;
299 }
300 catch (Exception * e)
301 {
302 // We know what to do with these..
303 if (e->errNo() == APPERR_CORRUPT_PACKAGE)
304 fatal (owner, IDS_CORRUPT_PACKAGE, version.Name().c_str());
305 // Unexpected exception.
306 throw e;
307 }
d014df0a 308 Progress.SetBar2(std::distance(t.begin(), i) + 1, t.size());
cbfc4215 309 }
23c9e63c 310
bb849dbd
RC
311 /* and do the download. FIXME: This here we assign a new name for the cached version
312 * and check that above.
313 */
64f45db2 314 for (SolverTransactionList::const_iterator i = t.begin (); i != t.end (); ++i)
cbfc4215 315 {
c1f4069d
KB
316 if (i->type != SolverTransaction::transInstall)
317 continue;
64f45db2
JT
318 packageversion version = i->version;
319
ab57ceaa
RC
320 {
321 int e = 0;
64f45db2 322 e += download_one (*version.source(), owner);
ab57ceaa 323 errors += e;
dcbcbef3
KB
324 if (e)
325 download_failures.push_back (version);
bb849dbd 326#if 0
ab57ceaa
RC
327 if (e)
328 pkg->action = ACTION_ERROR;
bb849dbd 329#endif
ab57ceaa 330 }
cbfc4215 331 }
23c9e63c 332
2a1a01e0
DD
333 if (errors)
334 {
0a9f27ce 335 // In unattended mode we retry the download, but not forever.
8311c03f 336 static int retries = 5;
dcbcbef3 337 int rc;
8311c03f 338 if (unattended_mode && --retries <= 0)
c7c7a4e0 339 {
157dc2b8 340 Log (LOG_PLAIN) << "download error in unattended_mode: out of retries" << endLog;
dcbcbef3 341 rc = IDABORT;
c7c7a4e0
DK
342 }
343 else if (unattended_mode)
344 {
157dc2b8 345 Log (LOG_PLAIN) << "download error in unattended_mode: " << retries
c7c7a4e0 346 << (retries > 1 ? " retries" : " retry") << " remaining." << endLog;
dcbcbef3
KB
347 rc = IDRETRY;
348 }
349 else
350 rc = query_download_errors (h, owner);
351 switch (rc)
352 {
353 case IDRETRY:
0a9f27ce
KB
354 Progress.SetActivateTask (WM_APP_START_DOWNLOAD);
355 return IDD_INSTATUS;
dcbcbef3
KB
356 case IDC_BACK:
357 return IDD_CHOOSE;
358 case IDABORT:
359 Logger ().setExitMsg (IDS_DOWNLOAD_INCOMPLETE_EXIT);
360 Logger ().exit (1);
361 case IDIGNORE:
362 break;
363 default:
364 break;
2a1a01e0
DD
365 }
366 }
367
bf1d5889
DD
368 if (source == IDC_SOURCE_DOWNLOAD)
369 {
2a1a01e0 370 if (errors)
94d2919d 371 Logger ().setExitMsg (IDS_DOWNLOAD_INCOMPLETE_EXIT);
f2ff9838 372 else if (!unattended_mode)
5fa64c3c 373 Logger ().setExitMsg (IDS_DOWNLOAD_COMPLETE);
6c8daadf 374 return IDD_DESKTOP;
bf1d5889
DD
375 }
376 else
49560a44 377 return IDD_S_INSTALL;
23c9e63c 378}
ab57ceaa 379
45e01f23 380static DWORD WINAPI
ab57ceaa
RC
381do_download_reflector (void *p)
382{
383 HANDLE *context;
384 context = (HANDLE *) p;
385
069cfbb4
JT
386 SetThreadUILanguage(langid);
387
072fb49a
MB
388 try
389 {
49560a44
MB
390 int next_dialog =
391 do_download_thread ((HINSTANCE) context[0], (HWND) context[1]);
ab57ceaa 392
072fb49a 393 // Tell the progress page that we're done downloading
6ab6abae 394 Progress.PostMessageNow (WM_APP_DOWNLOAD_THREAD_COMPLETE, 0, next_dialog);
072fb49a 395 }
703f1a44 396 TOPLEVEL_CATCH((HWND) context[1], "download");
ab57ceaa 397
45e01f23 398 ExitThread(0);
ab57ceaa
RC
399}
400
401static HANDLE context[2];
402
403void
404do_download (HINSTANCE h, HWND owner)
405{
406 context[0] = h;
407 context[1] = owner;
408
45e01f23
RC
409 DWORD threadID;
410 CreateThread (NULL, 0, do_download_reflector, context, 0, &threadID);
ab57ceaa 411}
This page took 0.220481 seconds and 5 git commands to generate.