]> cygwin.com Git - cygwin-apps/setup.git/blame - download.cc
2003-02-16 Pavel Tsekov <ptsekov@gmx.net>
[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
6625e635
RC
56using namespace std;
57
ab57ceaa
RC
58extern ThreeBarProgressPage Progress;
59
aa1e3b4d
RC
60
61bool
62validateCachedPackage (String const &fullname, packagesource & pkgsource)
63{
64 if (pkgsource.md5.isSet())
65 {
66 // check the MD5 sum of the cached file here
67 io_stream *thefile = io_stream::open (fullname, "rb");
68 if (!thefile)
69 return 0;
70 md5_state_t pns;
71 md5_init (&pns);
72
73 log (LOG_BABBLE) << "Checking MD5 for " << fullname << endLog;
74
75 Progress.SetText1 ((String ("Checking MD5 for ") + pkgsource.Base()).cstr_oneuse());
76 Progress.SetText4 ("Progress:");
77 Progress.SetBar1 (0);
78
79 unsigned char buffer[16384];
80 ssize_t count;
81 while ((count = thefile->read (buffer, 16384)) > 0)
82 {
83 md5_append (&pns, buffer, count);
84 Progress.SetBar1 (thefile->tell(), thefile->get_size());
85 }
86 delete thefile;
87 if (count < 0)
f37b36a3 88 throw new Exception ("__LINE__ __FILE__", String ("IO Error reading ") + pkgsource.Cached(), APPERR_IO_ERROR);
aa1e3b4d
RC
89
90 md5_byte_t tempdigest[16];
91 md5_finish(&pns, tempdigest);
92 md5 tempMD5;
93 tempMD5.set (tempdigest);
94
95 log (LOG_BABBLE) << "For file '" << fullname <<
96 " ini digest is " << pkgsource.md5.print() <<
97 " file digest is " << tempMD5.print() << endLog;
98
99 if (pkgsource.md5 != tempMD5)
100 return false;
101 }
102 return true;
103}
104
bb849dbd
RC
105/* 0 on failure
106 */
58ee6135 107int
bb849dbd 108check_for_cached (packagesource & pkgsource)
3b9077d4 109{
bb849dbd
RC
110 /* search algo:
111 1) is there a legacy version in the cache dir available.
112 (Note that the cache dir is represented by a mirror site of
113 file://local_dir
114 */
3b9077d4 115
58ee6135
RC
116 // Already found one.
117 if (pkgsource.Cached())
118 return 1;
e0a4db64
RC
119
120 String prefix = String ("file://") + local_dir + "/";
88a77116 121 DWORD size;
e0a4db64 122 if ((size = get_file_size (prefix + pkgsource.Canonical ())) > 0)
bb849dbd
RC
123 if (size == pkgsource.size)
124 {
aa1e3b4d
RC
125 if (validateCachedPackage (prefix + pkgsource.Canonical (), pkgsource))
126 pkgsource.set_cached (prefix + pkgsource.Canonical ());
127 else
f37b36a3 128 throw new Exception ("__LINE__ __FILE__", String ("Package validation failure for ") + prefix + pkgsource.Canonical (), APPERR_CORRUPT_PACKAGE);
bb849dbd
RC
129 return 1;
130 }
3b9077d4 131
bb849dbd
RC
132 /*
133 2) is there a version from one of the selected mirror sites available ?
134 */
3f34f364
RC
135 for (packagesource::sitestype::const_iterator n = pkgsource.sites.begin();
136 n != pkgsource.sites.end(); ++n)
58ee6135 137 {
3f34f364 138 String fullname = prefix + rfc1738_escape_part (n->key) + "/" +
58ee6135 139 pkgsource.Canonical ();
e0a4db64 140 if ((size = get_file_size (fullname)) > 0)
bb849dbd
RC
141 if (size == pkgsource.size)
142 {
aa1e3b4d
RC
143 if (validateCachedPackage (fullname, pkgsource))
144 pkgsource.set_cached (fullname );
145 else
f37b36a3 146 throw new Exception ("__LINE__ __FILE__", String ("Package validation failure for ") + fullname, APPERR_CORRUPT_PACKAGE);
bb849dbd
RC
147 return 1;
148 }
aa1e3b4d 149 }
bb849dbd
RC
150 return 0;
151}
152
153/* download a file from a mirror site to the local cache. */
154static int
ab57ceaa 155download_one (packagesource & pkgsource, HWND owner)
bb849dbd 156{
58ee6135
RC
157 try
158 {
159 if (check_for_cached (pkgsource))
160 return 0;
161 }
162 catch (Exception * e)
163 {
164 // We know what to do with these..
165 if (e->errNo() == APPERR_CORRUPT_PACKAGE)
166 {
167 fatal (owner, IDS_CORRUPT_PACKAGE, pkgsource.Canonical());
168 return 1;
169 }
170 // Unexpected exception.
171 throw e;
172 }
bb849dbd
RC
173 /* try the download sites one after another */
174
175 int success = 0;
3f34f364
RC
176 for (packagesource::sitestype::const_iterator n = pkgsource.sites.begin();
177 n != pkgsource.sites.end() && !success; ++n)
d4a4527d 178 {
3c054baf 179 String const local = local_dir + "/" +
3f34f364 180 rfc1738_escape_part (n->key) + "/" +
3c054baf 181 pkgsource.Canonical ();
1ac649ed 182 io_stream::mkpath_p (PATH_TO_FILE, String ("file://") + local);
3c054baf 183
3f34f364 184 if (get_url_to_file(n->key + "/" + pkgsource.Canonical (),
1ac649ed 185 local + ".tmp", pkgsource.size, owner))
3b9077d4 186 {
bb849dbd
RC
187 /* FIXME: note new source ? */
188 continue;
3b9077d4
DD
189 }
190 else
191 {
e0a4db64 192 size_t size = get_file_size (String("file://") + local + ".tmp");
bb849dbd
RC
193 if (size == pkgsource.size)
194 {
aa1e3b4d 195 log (LOG_PLAIN) << "Downloaded " << local << endLog;
3c054baf
RC
196 if (_access (local.cstr_oneuse(), 0) == 0)
197 remove (local.cstr_oneuse());
198 rename ((local + ".tmp").cstr_oneuse(), local.cstr_oneuse());
bb849dbd 199 success = 1;
3c054baf
RC
200 pkgsource.set_cached (String ("file://") + local);
201 // FIXME: move the downloaded file to the
202 // original locations - without the mirror site dir in the way
bb849dbd
RC
203 continue;
204 }
205 else
206 {
aa1e3b4d
RC
207 log (LOG_PLAIN) << "Download " << local << " wrong size (" <<
208 size << " actual vs " << pkgsource.size << " expected)" <<
209 endLog;
3c054baf 210 remove ((local + ".tmp").cstr_oneuse());
bb849dbd
RC
211 continue;
212 }
3b9077d4
DD
213 }
214 }
bb849dbd
RC
215 if (success)
216 return 0;
217 /* FIXME: Do we want to note this? if so how? */
218 return 1;
3b9077d4
DD
219}
220
ab57ceaa
RC
221static void
222do_download_thread (HINSTANCE h, HWND owner)
23c9e63c 223{
2a1a01e0 224 int errors = 0;
2f9645a1
CV
225 total_download_bytes = 0;
226 total_download_bytes_sofar = 0;
227
bb849dbd
RC
228 packagedb db;
229 /* calculate the amount needed */
cfae3b8d
RC
230 for (vector <packagemeta *>::iterator i = db.packages.begin ();
231 i != db.packages.end (); ++i)
cbfc4215 232 {
cfae3b8d 233 packagemeta & pkg = **i;
3c196821 234 if (pkg.desired.changeRequested())
ab57ceaa 235 {
3c196821
RC
236 packageversion version = pkg.desired;
237 packageversion sourceversion = version.sourcePackage();
58ee6135
RC
238 try
239 {
ec13f13c
RC
240 if (version.picked())
241 {
242 for (vector<packagesource>::iterator i =
243 version.sources ()->begin();
244 i != version.sources ()->end(); ++i)
245 if (!check_for_cached (*i))
246 total_download_bytes += i->size;
247 }
248 if (sourceversion.picked ())
249 {
250 for (vector<packagesource>::iterator i =
251 sourceversion.sources ()->begin();
252 i != sourceversion.sources ()->end(); ++i)
253 if (!check_for_cached (*i))
254 total_download_bytes += i->size;
255 }
58ee6135
RC
256 }
257 catch (Exception * e)
258 {
259 // We know what to do with these..
260 if (e->errNo() == APPERR_CORRUPT_PACKAGE)
261 fatal (owner, IDS_CORRUPT_PACKAGE, pkg.name.cstr_oneuse());
262 // Unexpected exception.
263 throw e;
264 }
ab57ceaa 265 }
cbfc4215 266 }
23c9e63c 267
bb849dbd
RC
268 /* and do the download. FIXME: This here we assign a new name for the cached version
269 * and check that above.
270 */
cfae3b8d
RC
271 for (vector <packagemeta *>::iterator i = db.packages.begin ();
272 i != db.packages.end (); ++i)
cbfc4215 273 {
cfae3b8d 274 packagemeta & pkg = **i;
3c196821 275 if (pkg.desired.changeRequested())
ab57ceaa
RC
276 {
277 int e = 0;
3c196821
RC
278 packageversion version = pkg.desired;
279 packageversion sourceversion = version.sourcePackage();
280 if (version.picked())
ec13f13c
RC
281 {
282 for (vector<packagesource>::iterator i =
283 version.sources ()->begin();
284 i != version.sources ()->end(); ++i)
285 e += download_one (*i, owner);
286 }
3c196821 287 if (sourceversion && sourceversion.picked())
ec13f13c
RC
288 {
289 for (vector<packagesource>::iterator i =
290 sourceversion.sources ()->begin();
291 i != sourceversion.sources ()->end(); ++i)
292 e += download_one (*i, owner);
293 }
ab57ceaa 294 errors += e;
bb849dbd 295#if 0
ab57ceaa
RC
296 if (e)
297 pkg->action = ACTION_ERROR;
bb849dbd 298#endif
ab57ceaa 299 }
cbfc4215 300 }
23c9e63c 301
2a1a01e0
DD
302 if (errors)
303 {
ab57ceaa 304 if (yesno (owner, IDS_DOWNLOAD_INCOMPLETE) == IDYES)
2a1a01e0
DD
305 {
306 next_dialog = IDD_SITE;
307 return;
308 }
309 }
310
bf1d5889
DD
311 if (source == IDC_SOURCE_DOWNLOAD)
312 {
2a1a01e0
DD
313 if (errors)
314 exit_msg = IDS_DOWNLOAD_INCOMPLETE;
f2ff9838 315 else if (!unattended_mode)
2a1a01e0 316 exit_msg = IDS_DOWNLOAD_COMPLETE;
bf1d5889
DD
317 next_dialog = 0;
318 }
319 else
320 next_dialog = IDD_S_INSTALL;
23c9e63c 321}
ab57ceaa 322
45e01f23 323static DWORD WINAPI
ab57ceaa
RC
324do_download_reflector (void *p)
325{
326 HANDLE *context;
327 context = (HANDLE *) p;
328
329 do_download_thread ((HINSTANCE) context[0], (HWND) context[1]);
330
331 // Tell the progress page that we're done downloading
332 Progress.PostMessage (WM_APP_DOWNLOAD_THREAD_COMPLETE, 0, next_dialog);
333
45e01f23 334 ExitThread(0);
ab57ceaa
RC
335}
336
337static HANDLE context[2];
338
339void
340do_download (HINSTANCE h, HWND owner)
341{
342 context[0] = h;
343 context[1] = owner;
344
45e01f23
RC
345 DWORD threadID;
346 CreateThread (NULL, 0, do_download_reflector, context, 0, &threadID);
ab57ceaa 347}
This page took 0.071579 seconds and 5 git commands to generate.