]> cygwin.com Git - cygwin-apps/setup.git/blame - download.cc
2002-06-27 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 */
133 for (size_t n = 1; n <= pkgsource.sites.number (); n++)
58ee6135 134 {
e0a4db64 135 String fullname = prefix +
58ee6135
RC
136 rfc1738_escape_part (pkgsource.sites[n]->key) + "/" +
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;
174 for (size_t n = 1; n <= pkgsource.sites.number () && !success; n++)
d4a4527d 175 {
3c054baf 176 String const local = local_dir + "/" +
ab57ceaa 177 rfc1738_escape_part (pkgsource.sites[n]->
3c054baf
RC
178 key) + "/" +
179 pkgsource.Canonical ();
1ac649ed 180 io_stream::mkpath_p (PATH_TO_FILE, String ("file://") + local);
3c054baf 181
1ac649ed
RC
182 if (get_url_to_file(pkgsource.sites[n]->key + "/" +
183 pkgsource.Canonical (),
184 local + ".tmp", pkgsource.size, owner))
3b9077d4 185 {
bb849dbd
RC
186 /* FIXME: note new source ? */
187 continue;
3b9077d4
DD
188 }
189 else
190 {
e0a4db64 191 size_t size = get_file_size (String("file://") + local + ".tmp");
bb849dbd
RC
192 if (size == pkgsource.size)
193 {
aa1e3b4d 194 log (LOG_PLAIN) << "Downloaded " << local << endLog;
3c054baf
RC
195 if (_access (local.cstr_oneuse(), 0) == 0)
196 remove (local.cstr_oneuse());
197 rename ((local + ".tmp").cstr_oneuse(), local.cstr_oneuse());
bb849dbd 198 success = 1;
3c054baf
RC
199 pkgsource.set_cached (String ("file://") + local);
200 // FIXME: move the downloaded file to the
201 // original locations - without the mirror site dir in the way
bb849dbd
RC
202 continue;
203 }
204 else
205 {
aa1e3b4d
RC
206 log (LOG_PLAIN) << "Download " << local << " wrong size (" <<
207 size << " actual vs " << pkgsource.size << " expected)" <<
208 endLog;
3c054baf 209 remove ((local + ".tmp").cstr_oneuse());
bb849dbd
RC
210 continue;
211 }
3b9077d4
DD
212 }
213 }
bb849dbd
RC
214 if (success)
215 return 0;
216 /* FIXME: Do we want to note this? if so how? */
217 return 1;
3b9077d4
DD
218}
219
ab57ceaa
RC
220static void
221do_download_thread (HINSTANCE h, HWND owner)
23c9e63c 222{
2a1a01e0 223 int errors = 0;
2f9645a1
CV
224 total_download_bytes = 0;
225 total_download_bytes_sofar = 0;
226
bb849dbd
RC
227 packagedb db;
228 /* calculate the amount needed */
3bab9a49 229 for (size_t n = 1; n <= db.packages.number (); n++)
cbfc4215 230 {
ab57ceaa 231 packagemeta & pkg = *db.packages[n];
cbfc4215 232 if (pkg.desired && (pkg.desired->srcpicked || pkg.desired->binpicked))
ab57ceaa
RC
233 {
234 packageversion *version = pkg.desired;
58ee6135
RC
235 try
236 {
237 if (!check_for_cached (version->bin) && pkg.desired->binpicked)
238 total_download_bytes += version->bin.size;
239 if (!check_for_cached (version->src) && pkg.desired->srcpicked)
240 total_download_bytes += version->src.size;
241 }
242 catch (Exception * e)
243 {
244 // We know what to do with these..
245 if (e->errNo() == APPERR_CORRUPT_PACKAGE)
246 fatal (owner, IDS_CORRUPT_PACKAGE, pkg.name.cstr_oneuse());
247 // Unexpected exception.
248 throw e;
249 }
ab57ceaa 250 }
cbfc4215 251 }
23c9e63c 252
bb849dbd
RC
253 /* and do the download. FIXME: This here we assign a new name for the cached version
254 * and check that above.
255 */
3bab9a49 256 for (size_t n = 1; n <= db.packages.number (); n++)
cbfc4215 257 {
ab57ceaa
RC
258 packagemeta & pkg = *db.packages[n];
259 if (pkg.desired && (pkg.desired->srcpicked || pkg.desired->binpicked))
260 {
261 int e = 0;
262 packageversion *version = pkg.desired;
263 if (version->binpicked)
264 e += download_one (version->bin, owner);
265 if (version->srcpicked)
266 e += download_one (version->src, owner);
267 errors += e;
bb849dbd 268#if 0
ab57ceaa
RC
269 if (e)
270 pkg->action = ACTION_ERROR;
bb849dbd 271#endif
ab57ceaa 272 }
cbfc4215 273 }
23c9e63c 274
2a1a01e0
DD
275 if (errors)
276 {
ab57ceaa 277 if (yesno (owner, IDS_DOWNLOAD_INCOMPLETE) == IDYES)
2a1a01e0
DD
278 {
279 next_dialog = IDD_SITE;
280 return;
281 }
282 }
283
bf1d5889
DD
284 if (source == IDC_SOURCE_DOWNLOAD)
285 {
2a1a01e0
DD
286 if (errors)
287 exit_msg = IDS_DOWNLOAD_INCOMPLETE;
288 else
289 exit_msg = IDS_DOWNLOAD_COMPLETE;
bf1d5889
DD
290 next_dialog = 0;
291 }
292 else
293 next_dialog = IDD_S_INSTALL;
23c9e63c 294}
ab57ceaa 295
45e01f23 296static DWORD WINAPI
ab57ceaa
RC
297do_download_reflector (void *p)
298{
299 HANDLE *context;
300 context = (HANDLE *) p;
301
302 do_download_thread ((HINSTANCE) context[0], (HWND) context[1]);
303
304 // Tell the progress page that we're done downloading
305 Progress.PostMessage (WM_APP_DOWNLOAD_THREAD_COMPLETE, 0, next_dialog);
306
45e01f23 307 ExitThread(0);
ab57ceaa
RC
308}
309
310static HANDLE context[2];
311
312void
313do_download (HINSTANCE h, HWND owner)
314{
315 context[0] = h;
316 context[1] = owner;
317
45e01f23
RC
318 DWORD threadID;
319 CreateThread (NULL, 0, do_download_reflector, context, 0, &threadID);
ab57ceaa 320}
This page took 0.067799 seconds and 5 git commands to generate.