]> cygwin.com Git - cygwin-apps/setup.git/blob - download.cc
2a80a9cb99eb5bff7e76d2608f9b479206e41108
[cygwin-apps/setup.git] / download.cc
1 /*
2 * Copyright (c) 2000, 2001, Red Hat, Inc.
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
19 #if 0
20 static const char *cvsid =
21 "\n%%% $Id$\n";
22 #endif
23
24 #include "win32.h"
25
26 #include <stdio.h>
27 #include <unistd.h>
28 #include <process.h>
29
30 #include "resource.h"
31 #include "msg.h"
32 #include "dialog.h"
33 #include "String++.h"
34 #include "geturl.h"
35 #include "state.h"
36 #include "mkdir.h"
37 #include "log.h"
38 #include "filemanip.h"
39 #include "port.h"
40
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
50 #include "threebar.h"
51
52 #include "md5.h"
53
54 #include "Exception.h"
55
56 #include "download.h"
57
58 extern ThreeBarProgressPage Progress;
59
60 /* 0 on failure
61 */
62 int
63 check_for_cached (packagesource & pkgsource)
64 {
65 /* search algo:
66 1) is there a legacy version in the cache dir available.
67 (Note that the cache dir is represented by a mirror site of
68 file://local_dir
69 */
70
71 // Already found one.
72 if (pkgsource.Cached())
73 return 1;
74
75 String prefix = String ("file://") + local_dir + "/";
76 DWORD size;
77 if ((size = get_file_size (prefix + pkgsource.Canonical ())) > 0)
78 if (size == pkgsource.size)
79 {
80 pkgsource.set_cached (prefix + pkgsource.Canonical ());
81 return 1;
82 }
83
84 /*
85 2) is there a version from one of the selected mirror sites available ?
86 */
87 for (size_t n = 1; n <= pkgsource.sites.number (); n++)
88 {
89 String fullname = prefix +
90 rfc1738_escape_part (pkgsource.sites[n]->key) + "/" +
91 pkgsource.Canonical ();
92 if ((size = get_file_size (fullname)) > 0)
93 if (size == pkgsource.size)
94 {
95 if (pkgsource.md5.isSet())
96 {
97 // check the MD5 sum of the cached file here
98 io_stream *thefile = io_stream::open (fullname, "rb");
99 if (!thefile)
100 return 0;
101 md5_state_t pns;
102 md5_init (&pns);
103
104 unsigned char buffer[16384];
105 ssize_t count;
106 while ((count = thefile->read (buffer, 16384)) > 0)
107 md5_append (&pns, buffer, count);
108 delete thefile;
109 if (count < 0)
110 throw new Exception ("__LINE__ __FILE__", (String ("IO Error reading ") + pkgsource.Cached()).cstr_oneuse(), APPERR_IO_ERROR);
111
112 md5_byte_t tempdigest[16];
113 md5_finish(&pns, tempdigest);
114 md5 tempMD5;
115 tempMD5.set (tempdigest);
116
117 log (LOG_BABBLE, String ("For file '") + fullname +
118 " ini digest is " + pkgsource.md5.print() +
119 " file digest is " + tempMD5.print());
120
121 if (pkgsource.md5 != tempMD5)
122 throw new Exception ("__LINE__ __FILE__", (String ("MD5 Checksum failure for ") + pkgsource.Cached()).cstr_oneuse(), APPERR_CORRUPT_PACKAGE);
123 }
124 pkgsource.
125 set_cached (fullname );
126 return 1;
127 }
128 }
129 return 0;
130 }
131
132 /* download a file from a mirror site to the local cache. */
133 static int
134 download_one (packagesource & pkgsource, HWND owner)
135 {
136 try
137 {
138 if (check_for_cached (pkgsource))
139 return 0;
140 }
141 catch (Exception * e)
142 {
143 // We know what to do with these..
144 if (e->errNo() == APPERR_CORRUPT_PACKAGE)
145 {
146 fatal (owner, IDS_CORRUPT_PACKAGE, pkgsource.Canonical());
147 return 1;
148 }
149 // Unexpected exception.
150 throw e;
151 }
152 /* try the download sites one after another */
153
154 int success = 0;
155 for (size_t n = 1; n <= pkgsource.sites.number () && !success; n++)
156 {
157 String const local = local_dir + "/" +
158 rfc1738_escape_part (pkgsource.sites[n]->
159 key) + "/" +
160 pkgsource.Canonical ();
161 io_stream::mkpath_p (PATH_TO_FILE, String ("file://") + local);
162
163 if (get_url_to_file(pkgsource.sites[n]->key + "/" +
164 pkgsource.Canonical (),
165 local + ".tmp", pkgsource.size, owner))
166 {
167 /* FIXME: note new source ? */
168 continue;
169 }
170 else
171 {
172 size_t size = get_file_size (String("file://") + local + ".tmp");
173 if (size == pkgsource.size)
174 {
175 log (LOG_PLAIN, String ("Downloaded ") + local);
176 if (_access (local.cstr_oneuse(), 0) == 0)
177 remove (local.cstr_oneuse());
178 rename ((local + ".tmp").cstr_oneuse(), local.cstr_oneuse());
179 success = 1;
180 pkgsource.set_cached (String ("file://") + local);
181 // FIXME: move the downloaded file to the
182 // original locations - without the mirror site dir in the way
183 continue;
184 }
185 else
186 {
187 log (LOG_PLAIN,
188 "Download %s wrong size (%u actual vs %d expected)",
189 local.cstr_oneuse(), size, pkgsource.size);
190 remove ((local + ".tmp").cstr_oneuse());
191 continue;
192 }
193 }
194 }
195 if (success)
196 return 0;
197 /* FIXME: Do we want to note this? if so how? */
198 return 1;
199 }
200
201 static void
202 do_download_thread (HINSTANCE h, HWND owner)
203 {
204 int errors = 0;
205 total_download_bytes = 0;
206 total_download_bytes_sofar = 0;
207
208 packagedb db;
209 /* calculate the amount needed */
210 for (size_t n = 1; n <= db.packages.number (); n++)
211 {
212 packagemeta & pkg = *db.packages[n];
213 if (pkg.desired && (pkg.desired->srcpicked || pkg.desired->binpicked))
214 {
215 packageversion *version = pkg.desired;
216 try
217 {
218 if (!check_for_cached (version->bin) && pkg.desired->binpicked)
219 total_download_bytes += version->bin.size;
220 if (!check_for_cached (version->src) && pkg.desired->srcpicked)
221 total_download_bytes += version->src.size;
222 }
223 catch (Exception * e)
224 {
225 // We know what to do with these..
226 if (e->errNo() == APPERR_CORRUPT_PACKAGE)
227 fatal (owner, IDS_CORRUPT_PACKAGE, pkg.name.cstr_oneuse());
228 // Unexpected exception.
229 throw e;
230 }
231 }
232 }
233
234 /* and do the download. FIXME: This here we assign a new name for the cached version
235 * and check that above.
236 */
237 for (size_t n = 1; n <= db.packages.number (); n++)
238 {
239 packagemeta & pkg = *db.packages[n];
240 if (pkg.desired && (pkg.desired->srcpicked || pkg.desired->binpicked))
241 {
242 int e = 0;
243 packageversion *version = pkg.desired;
244 if (version->binpicked)
245 e += download_one (version->bin, owner);
246 if (version->srcpicked)
247 e += download_one (version->src, owner);
248 errors += e;
249 #if 0
250 if (e)
251 pkg->action = ACTION_ERROR;
252 #endif
253 }
254 }
255
256 if (errors)
257 {
258 if (yesno (owner, IDS_DOWNLOAD_INCOMPLETE) == IDYES)
259 {
260 next_dialog = IDD_SITE;
261 return;
262 }
263 }
264
265 if (source == IDC_SOURCE_DOWNLOAD)
266 {
267 if (errors)
268 exit_msg = IDS_DOWNLOAD_INCOMPLETE;
269 else
270 exit_msg = IDS_DOWNLOAD_COMPLETE;
271 next_dialog = 0;
272 }
273 else
274 next_dialog = IDD_S_INSTALL;
275 }
276
277 static DWORD WINAPI
278 do_download_reflector (void *p)
279 {
280 HANDLE *context;
281 context = (HANDLE *) p;
282
283 do_download_thread ((HINSTANCE) context[0], (HWND) context[1]);
284
285 // Tell the progress page that we're done downloading
286 Progress.PostMessage (WM_APP_DOWNLOAD_THREAD_COMPLETE, 0, next_dialog);
287
288 ExitThread(0);
289 }
290
291 static HANDLE context[2];
292
293 void
294 do_download (HINSTANCE h, HWND owner)
295 {
296 context[0] = h;
297 context[1] = owner;
298
299 DWORD threadID;
300 CreateThread (NULL, 0, do_download_reflector, context, 0, &threadID);
301 }
This page took 0.0429 seconds and 5 git commands to generate.