]>
Commit | Line | Data |
---|---|---|
23c9e63c DD |
1 | /* |
2 | * Copyright (c) 2000, 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 | ||
8e9aa511 | 16 | /* The purpose of this file is to install all the packages selected in |
23c9e63c DD |
17 | the install list (in ini.h). Note that we use a separate thread to |
18 | maintain the progress dialog, so we avoid the complexity of | |
19 | handling two tasks in one thread. We also create or update all the | |
b24c88b3 | 20 | files in /etc/setup/\* and create the mount points. */ |
23c9e63c | 21 | |
b24c88b3 | 22 | #if 0 |
ad3c7385 | 23 | static const char *cvsid = "\n%%% $Id$\n"; |
b24c88b3 | 24 | #endif |
8507f105 | 25 | |
23c9e63c DD |
26 | #include "win32.h" |
27 | #include "commctrl.h" | |
28 | ||
29 | #include <stdio.h> | |
904d24fe | 30 | #include <stdlib.h> |
4a83b7b0 | 31 | #include <unistd.h> |
23c9e63c DD |
32 | #include <sys/types.h> |
33 | #include <sys/stat.h> | |
34 | #include <errno.h> | |
ab57ceaa RC |
35 | #include <process.h> |
36 | ||
87c42361 | 37 | #include "zlib/zlib.h" |
23c9e63c DD |
38 | |
39 | #include "resource.h" | |
23c9e63c | 40 | #include "dialog.h" |
23c9e63c | 41 | #include "geturl.h" |
23c9e63c | 42 | #include "state.h" |
23c9e63c DD |
43 | #include "diskfull.h" |
44 | #include "msg.h" | |
45 | #include "mount.h" | |
89b1a15b | 46 | #include "log.h" |
a351e48c | 47 | #include "mount.h" |
c46a33a9 | 48 | #include "filemanip.h" |
b24c88b3 RC |
49 | #include "io_stream.h" |
50 | #include "compress.h" | |
51 | #include "compress_gz.h" | |
52 | #include "archive.h" | |
53 | #include "archive_tar.h" | |
8e9aa511 | 54 | #include "script.h" |
4a83b7b0 | 55 | |
fa0c0d10 RC |
56 | #include "package_db.h" |
57 | #include "package_meta.h" | |
bb849dbd RC |
58 | #include "package_version.h" |
59 | #include "package_source.h" | |
fa0c0d10 | 60 | |
4a83b7b0 | 61 | #include "port.h" |
23c9e63c | 62 | |
ab57ceaa | 63 | #include "threebar.h" |
58ee6135 RC |
64 | |
65 | #include "md5.h" | |
66 | ||
67 | #include "Exception.h" | |
a75ed5ce | 68 | #include "getopt++/BoolOption.h" |
58ee6135 | 69 | |
6625e635 RC |
70 | using namespace std; |
71 | ||
ab57ceaa | 72 | extern ThreeBarProgressPage Progress; |
23c9e63c DD |
73 | |
74 | static int total_bytes = 0; | |
75 | static int total_bytes_sofar = 0; | |
76 | static int package_bytes = 0; | |
77 | ||
a75ed5ce RC |
78 | static BoolOption NoReplaceOnReboot (false, 'r', "no-replaceonreboot", |
79 | "Disable replacing in-use files on next " | |
80 | "reboot."); | |
81 | ||
23c9e63c DD |
82 | static void |
83 | init_dialog () | |
84 | { | |
ab57ceaa RC |
85 | Progress.SetText2 (""); |
86 | Progress.SetText3 (""); | |
23c9e63c DD |
87 | } |
88 | ||
89 | static void | |
90 | progress (int bytes) | |
91 | { | |
ab57ceaa | 92 | if (package_bytes > 0) |
23c9e63c | 93 | { |
ab57ceaa | 94 | Progress.SetBar1 (bytes, package_bytes); |
23c9e63c DD |
95 | } |
96 | ||
ab57ceaa | 97 | if (total_bytes > 0) |
23c9e63c | 98 | { |
ab57ceaa | 99 | Progress.SetBar2 (total_bytes_sofar + bytes, total_bytes); |
23c9e63c | 100 | } |
23c9e63c DD |
101 | } |
102 | ||
b24c88b3 | 103 | static const char *standard_dirs[] = { |
1a18aed7 | 104 | "/bin", |
904d24fe | 105 | "/etc", |
1a18aed7 | 106 | "/lib", |
904d24fe | 107 | "/tmp", |
4a83b7b0 | 108 | "/usr", |
1a18aed7 DD |
109 | "/usr/bin", |
110 | "/usr/lib", | |
ef45c299 | 111 | "/usr/src", |
4a83b7b0 | 112 | "/usr/local", |
1a18aed7 DD |
113 | "/usr/local/bin", |
114 | "/usr/local/etc", | |
115 | "/usr/local/lib", | |
904d24fe | 116 | "/usr/tmp", |
1a18aed7 | 117 | "/var/run", |
904d24fe DD |
118 | "/var/tmp", |
119 | 0 | |
120 | }; | |
121 | ||
ad3c7385 RC |
122 | static int num_installs, num_replacements, num_uninstalls; |
123 | static void uninstall_one (packagemeta &); | |
124 | static int replace_one (packagemeta &); | |
3c054baf RC |
125 | static int install_one_source (packagemeta &, packagesource &, String const &, |
126 | String const &, package_type_t); | |
ad3c7385 | 127 | static bool rebootneeded; |
3b9077d4 | 128 | |
fa0c0d10 | 129 | /* FIXME: upgrades should be a method too */ |
3b9077d4 | 130 | static void |
cbfc4215 | 131 | uninstall_one (packagemeta & pkgm) |
3b9077d4 | 132 | { |
ab57ceaa | 133 | Progress.SetText1 ("Uninstalling..."); |
3c054baf | 134 | Progress.SetText2 (pkgm.name.cstr_oneuse()); |
1ac649ed | 135 | log (LOG_PLAIN, String("Uninstalling ") + pkgm.name); |
ab57ceaa RC |
136 | pkgm.uninstall (); |
137 | num_uninstalls++; | |
3b9077d4 DD |
138 | } |
139 | ||
ad3c7385 RC |
140 | /* uninstall and install a package, preserving configuration |
141 | * files and the like. | |
142 | * This method should also know about replacing in-use file. | |
143 | * ASSUMPTIONS: pkgm is installed. | |
144 | * pkgm has a desired package. | |
145 | */ | |
146 | static int | |
147 | replace_one (packagemeta & pkg) | |
148 | { | |
149 | int errors = 0; | |
150 | Progress.SetText1 ("Replacing..."); | |
3c054baf | 151 | Progress.SetText2 (pkg.name.cstr_oneuse()); |
1ac649ed | 152 | log (LOG_PLAIN, String( "Replacing ") + pkg.name); |
ad3c7385 RC |
153 | pkg.uninstall (); |
154 | ||
155 | errors += | |
3c196821 | 156 | install_one_source (pkg, *pkg.desired.source(), "cygfile://","/", package_binary); |
ad3c7385 RC |
157 | if (!errors) |
158 | pkg.installed = pkg.desired; | |
159 | num_replacements++; | |
160 | return errors; | |
161 | } | |
42bf5b92 | 162 | |
bb849dbd RC |
163 | |
164 | /* install one source at a given prefix. */ | |
3b9077d4 | 165 | static int |
bb849dbd | 166 | install_one_source (packagemeta & pkgm, packagesource & source, |
3c054baf | 167 | String const &prefixURL, String const &prefixPath, package_type_t type) |
3b9077d4 DD |
168 | { |
169 | int errors = 0; | |
ab57ceaa | 170 | Progress.SetText2 (source.Base ()); |
7c6ef2c3 | 171 | if (!source.Cached () || !io_stream::exists (source.Cached ())) |
c46a33a9 | 172 | { |
ab57ceaa | 173 | note (NULL, IDS_ERR_OPEN_READ, source.Cached (), "No such file"); |
bb849dbd | 174 | return 1; |
c46a33a9 | 175 | } |
bb849dbd RC |
176 | io_stream *lst = 0; |
177 | if (type == package_binary) | |
c46a33a9 | 178 | { |
bb849dbd RC |
179 | io_stream *tmp = |
180 | io_stream:: | |
3c054baf | 181 | open (String ("cygfile:///etc/setup/") + pkgm.name + ".lst.gz", |
bb849dbd RC |
182 | "wb"); |
183 | lst = new compress_gz (tmp, "w9"); | |
184 | if (lst->error ()) | |
185 | { | |
186 | delete lst; | |
187 | lst = NULL; | |
188 | } | |
c46a33a9 | 189 | } |
b24c88b3 | 190 | |
bb849dbd | 191 | package_bytes = source.size; |
3b9077d4 | 192 | |
bb849dbd RC |
193 | char msg[64]; |
194 | strcpy (msg, "Installing"); | |
ab57ceaa | 195 | Progress.SetText1 (msg); |
1ac649ed | 196 | log (LOG_PLAIN, String (msg) + " " + source.Cached ()); |
58ee6135 RC |
197 | |
198 | if (source.md5.isSet()) | |
199 | { | |
200 | // check the MD5 sum of the cached file here | |
201 | io_stream *thefile = io_stream::open (source.Cached (), "rb"); | |
202 | if (!thefile) | |
203 | return 0; | |
204 | md5_state_t pns; | |
205 | md5_init (&pns); | |
206 | ||
207 | unsigned char buffer[16384]; | |
208 | ssize_t count; | |
209 | while ((count = thefile->read (buffer, 16384)) > 0) | |
210 | md5_append (&pns, buffer, count); | |
211 | delete thefile; | |
212 | if (count < 0) | |
213 | throw new Exception ("__LINE__ __FILE__", (String ("IO Error reading ") + source.Cached()).cstr_oneuse(), APPERR_IO_ERROR); | |
214 | ||
215 | md5_byte_t tempdigest[16]; | |
216 | md5_finish(&pns, tempdigest); | |
217 | md5 tempMD5; | |
218 | tempMD5.set (tempdigest); | |
219 | ||
3a8d1127 | 220 | log (LOG_BABBLE, String ("For file ") + source.Cached() + " ini digest is " + source.md5.print() + " file digest is " + tempMD5.print()); |
58ee6135 RC |
221 | |
222 | if (source.md5 != tempMD5) | |
223 | throw new Exception ("__LINE__ __FILE__", (String ("Checksum failure for ") + source.Cached()).cstr_oneuse(), APPERR_CORRUPT_PACKAGE); | |
224 | } | |
bb849dbd RC |
225 | io_stream *tmp = io_stream::open (source.Cached (), "rb"); |
226 | archive *thefile = 0; | |
227 | if (tmp) | |
d4a4527d | 228 | { |
bb849dbd RC |
229 | io_stream *tmp2 = compress::decompress (tmp); |
230 | if (tmp2) | |
231 | thefile = archive::extract (tmp2); | |
232 | else | |
233 | thefile = archive::extract (tmp); | |
3b9077d4 | 234 | } |
bb849dbd RC |
235 | /* FIXME: potential leak of either *tmp or *tmp2 */ |
236 | if (thefile) | |
d4a4527d | 237 | { |
3c054baf RC |
238 | String fn; |
239 | while ((fn = thefile->next_file_name ()).size()) | |
bb849dbd RC |
240 | { |
241 | if (lst) | |
3c054baf RC |
242 | { |
243 | String tmp=fn + "\n"; | |
2fa7c5a4 | 244 | lst->write (tmp.cstr_oneuse(), tmp.size()); |
3c054baf RC |
245 | } |
246 | ||
247 | String canonicalfn = prefixPath + fn; | |
bb849dbd | 248 | |
3c054baf RC |
249 | Progress.SetText3 (canonicalfn.cstr_oneuse()); |
250 | log (LOG_BABBLE, String("Installing file ") + prefixURL + prefixPath + fn); | |
6dc75764 | 251 | if (archive::extract_file (thefile, prefixURL, prefixPath) != 0) |
bb849dbd | 252 | { |
a75ed5ce RC |
253 | if (NoReplaceOnReboot) |
254 | { | |
255 | ++errors; | |
256 | log (LOG_PLAIN, String("Not replacing in-use file ") + | |
257 | prefixURL + prefixPath + fn); | |
258 | } | |
259 | else | |
ad3c7385 | 260 | //extract to temp location |
6dc75764 | 261 | if (archive::extract_file (thefile, prefixURL, prefixPath, ".new") != 0) |
ad3c7385 | 262 | { |
1ac649ed RC |
263 | log (LOG_PLAIN, |
264 | String("Unable to install file ") + | |
265 | prefixURL + prefixPath + fn); | |
ad3c7385 RC |
266 | errors++; |
267 | } | |
268 | else | |
269 | //switch Win32::OS | |
270 | { | |
271 | switch (Win32::OS ()) | |
272 | { | |
273 | case Win32::Win9x:{ | |
274 | /* Get the short file names */ | |
275 | char source[MAX_PATH]; | |
276 | unsigned int len = | |
1ac649ed RC |
277 | GetShortPathName (cygpath (String ("/") + fn + |
278 | ".new").cstr_oneuse(), | |
ad3c7385 RC |
279 | source, MAX_PATH); |
280 | if (!len || len > MAX_PATH) | |
281 | { | |
3c054baf | 282 | log (LOG_TIMESTAMP, |
ad3c7385 | 283 | "Unable to schedule reboot replacement of file %s with %s (Win32 Error %ld)", |
1ac649ed RC |
284 | cygpath (String ("/") + fn).cstr_oneuse(), |
285 | cygpath (String ("/") + fn + | |
286 | ".new").cstr_oneuse(), | |
ad3c7385 RC |
287 | GetLastError ()); |
288 | ++errors; | |
289 | } | |
290 | else | |
291 | { | |
292 | char dest[MAX_PATH]; | |
293 | len = | |
1ac649ed RC |
294 | GetShortPathName (cygpath (String ("/") + |
295 | fn).cstr_oneuse(), | |
296 | dest, MAX_PATH); | |
ad3c7385 RC |
297 | if (!len || len > MAX_PATH) |
298 | { | |
3c054baf | 299 | log (LOG_TIMESTAMP, |
ad3c7385 | 300 | "Unable to schedule reboot replacement of file %s with %s (Win32 Error %ld)", |
1ac649ed RC |
301 | cygpath (String ("/") + fn).cstr_oneuse(), |
302 | cygpath (String ("/") + fn + | |
303 | ".new").cstr_oneuse(), | |
ad3c7385 RC |
304 | GetLastError ()); |
305 | ++errors; | |
306 | ||
307 | } | |
308 | else | |
309 | /* trigger a replacement on reboot */ | |
310 | if (!WritePrivateProfileString | |
311 | ("rename", dest, source, "WININIT.INI")) | |
312 | { | |
3c054baf | 313 | log (LOG_TIMESTAMP, |
ad3c7385 | 314 | "Unable to schedule reboot replacement of file %s with %s (Win32 Error %ld)", |
1ac649ed RC |
315 | cygpath (String ("/") + fn).cstr_oneuse(), |
316 | cygpath (String ("/") + fn + | |
317 | ".new").cstr_oneuse(), | |
ad3c7385 RC |
318 | GetLastError ()); |
319 | ++errors; | |
320 | } | |
321 | ||
322 | } | |
323 | } | |
324 | break; | |
325 | case Win32::WinNT: | |
326 | /* XXX FIXME: prefix may not be / for in use files - | |
327 | * although it most likely is | |
328 | * - we need a io method to get win32 paths | |
329 | * or to wrap this system call | |
330 | */ | |
1ac649ed RC |
331 | if (!MoveFileEx (cygpath (String ("/") + fn + |
332 | ".new").cstr_oneuse(), | |
333 | cygpath (String ("/") + fn).cstr_oneuse(), | |
ad3c7385 RC |
334 | MOVEFILE_DELAY_UNTIL_REBOOT | |
335 | MOVEFILE_REPLACE_EXISTING)) | |
336 | { | |
3c054baf | 337 | log (LOG_TIMESTAMP, |
ad3c7385 | 338 | "Unable to schedule reboot replacement of file %s with %s (Win32 Error %ld)", |
1ac649ed RC |
339 | cygpath (String ("/") + fn).cstr_oneuse(), |
340 | cygpath (String ("/") + fn + ".new").cstr_oneuse(), | |
ad3c7385 RC |
341 | GetLastError ()); |
342 | ++errors; | |
343 | } | |
344 | else | |
345 | rebootneeded = true; | |
346 | break; | |
347 | } | |
348 | } | |
bb849dbd RC |
349 | } |
350 | ||
351 | progress (tmp->tell ()); | |
352 | num_installs++; | |
353 | } | |
354 | delete thefile; | |
355 | ||
356 | total_bytes_sofar += package_bytes; | |
d4a4527d | 357 | } |
3b9077d4 | 358 | |
90d14922 | 359 | |
bb849dbd RC |
360 | progress (0); |
361 | ||
3c054baf | 362 | int df = diskfull (get_root_dir ().cstr_oneuse()); |
ab57ceaa | 363 | Progress.SetBar3 (df); |
bb849dbd RC |
364 | |
365 | if (lst) | |
366 | delete lst; | |
367 | ||
368 | return errors; | |
369 | } | |
370 | ||
371 | /* install a package, install both the binary and source aspects if needed */ | |
372 | static int | |
373 | install_one (packagemeta & pkg) | |
374 | { | |
375 | int errors = 0; | |
376 | ||
3c196821 | 377 | if (pkg.installed != pkg.desired && pkg.desired.picked()) |
ab57ceaa | 378 | { |
bb849dbd | 379 | errors += |
3c196821 | 380 | install_one_source (pkg, *pkg.desired.source(), "cygfile://","/", |
ab57ceaa RC |
381 | package_binary); |
382 | if (!errors) | |
383 | pkg.installed = pkg.desired; | |
384 | } | |
3c196821 | 385 | if (pkg.desired.sourcePackage().picked()) |
ab57ceaa | 386 | errors += |
3c196821 | 387 | install_one_source (pkg, *pkg.desired.sourcePackage().source(), "cygfile://","/usr/src/", |
ab57ceaa | 388 | package_source); |
bb849dbd RC |
389 | |
390 | /* FIXME: make a upgrade method and reinstate this */ | |
391 | #if 0 | |
1ac649ed | 392 | String msg; |
c46a33a9 | 393 | if (!pkg->installed) |
1ac649ed | 394 | msg = "Installing"; |
c46a33a9 CF |
395 | else |
396 | { | |
397 | int n = strcmp (pi->version, pkg->installed->version); | |
398 | if (n < 0) | |
1ac649ed | 399 | msg = "Reverting"; |
c46a33a9 | 400 | else if (n == 0) |
1ac649ed | 401 | msg = "Reinstalling"; |
c46a33a9 | 402 | else |
1ac649ed | 403 | msg = "Upgrading"; |
c46a33a9 CF |
404 | } |
405 | ||
406 | switch (pkg->action) | |
3b9077d4 | 407 | { |
c46a33a9 | 408 | case ACTION_PREV: |
1ac649ed | 409 | msg += " previous version..."; |
3b9077d4 | 410 | break; |
c46a33a9 | 411 | case ACTION_CURR: |
1ac649ed | 412 | msg += "..."; |
3b9077d4 | 413 | break; |
c46a33a9 | 414 | case ACTION_TEST: |
1ac649ed | 415 | msg += " test version..."; |
42bf5b92 | 416 | break; |
b24c88b3 RC |
417 | default: |
418 | /* FIXME: log this somehow */ | |
419 | break; | |
3b9077d4 | 420 | } |
1ac649ed RC |
421 | SetWindowText (ins_action, msg.cstr_oneuse()); |
422 | log (LOG_PLAIN, msg + " " + file); | |
bb849dbd | 423 | #endif |
c46a33a9 | 424 | |
3b9077d4 DD |
425 | return errors; |
426 | } | |
427 | ||
72fd1d1e CF |
428 | static void |
429 | check_for_old_cygwin () | |
430 | { | |
431 | char buf[_MAX_PATH + sizeof ("\\cygwin1.dll")]; | |
432 | if (!GetSystemDirectory (buf, sizeof (buf))) | |
433 | return; | |
434 | strcat (buf, "\\cygwin1.dll"); | |
435 | if (_access (buf, 0) != 0) | |
436 | return; | |
437 | ||
438 | char msg[sizeof (buf) + 132]; | |
b24c88b3 RC |
439 | sprintf (msg, |
440 | "An old version of cygwin1.dll was found here:\r\n%s\r\nDelete?", | |
441 | buf); | |
442 | switch (MessageBox | |
443 | (NULL, msg, "What's that doing there?", | |
444 | MB_YESNO | MB_ICONQUESTION | MB_TASKMODAL)) | |
72fd1d1e CF |
445 | { |
446 | case IDYES: | |
447 | if (!DeleteFile (buf)) | |
448 | { | |
449 | sprintf (msg, "Couldn't delete file %s.\r\n" | |
b24c88b3 | 450 | "Is the DLL in use by another application?\r\n" |
7c7034e8 RC |
451 | "You should delete the old version of cygwin1.dll\r\n" |
452 | "at your earliest convenience.", buf); | |
b24c88b3 RC |
453 | MessageBox (NULL, buf, "Couldn't delete file", |
454 | MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL); | |
72fd1d1e CF |
455 | } |
456 | break; | |
457 | default: | |
b24c88b3 | 458 | break; |
72fd1d1e CF |
459 | } |
460 | ||
461 | return; | |
462 | } | |
463 | ||
ab57ceaa RC |
464 | static void |
465 | do_install_thread (HINSTANCE h, HWND owner) | |
23c9e63c | 466 | { |
3b9077d4 | 467 | int i; |
2a1a01e0 DD |
468 | int errors = 0; |
469 | ||
ad3c7385 RC |
470 | num_installs = 0, num_uninstalls = 0, num_replacements = 0; |
471 | rebootneeded = false; | |
3b9077d4 | 472 | |
50225eae | 473 | next_dialog = IDD_DESKTOP; |
23c9e63c | 474 | |
490717ef | 475 | io_stream::mkpath_p (PATH_TO_DIR, String ("file://") + get_root_dir ()); |
904d24fe | 476 | |
b24c88b3 | 477 | for (i = 0; standard_dirs[i]; i++) |
904d24fe | 478 | { |
1ac649ed | 479 | String p = cygpath (standard_dirs[i]); |
3c054baf | 480 | if (p.size()) |
490717ef | 481 | io_stream::mkpath_p (PATH_TO_DIR, String ("file://") + p); |
904d24fe DD |
482 | } |
483 | ||
1a18aed7 | 484 | /* Create /var/run/utmp */ |
b24c88b3 RC |
485 | io_stream *utmp = io_stream::open ("cygfile:///var/run/utmp", "wb"); |
486 | delete utmp; | |
1a18aed7 | 487 | |
23c9e63c DD |
488 | init_dialog (); |
489 | ||
490 | total_bytes = 0; | |
491 | total_bytes_sofar = 0; | |
492 | ||
3c054baf | 493 | int df = diskfull (get_root_dir ().cstr_oneuse()); |
ab57ceaa | 494 | Progress.SetBar3 (df); |
d07591a3 | 495 | |
0af2d779 CF |
496 | int istext = (root_text == IDC_ROOT_TEXT) ? 1 : 0; |
497 | int issystem = (root_scope == IDC_ROOT_SYSTEM) ? 1 : 0; | |
498 | ||
1ac649ed RC |
499 | create_mount ("/", get_root_dir (), istext, issystem); |
500 | create_mount ("/usr/bin", cygpath ("/bin"), istext, issystem); | |
501 | create_mount ("/usr/lib", cygpath ("/lib"), istext, issystem); | |
0af2d779 CF |
502 | set_cygdrive_flags (istext, issystem); |
503 | ||
8e9aa511 RC |
504 | /* Let's hope people won't uninstall packages before installing [b]ash */ |
505 | init_run_script (); | |
506 | ||
bb849dbd | 507 | packagedb db; |
cfae3b8d RC |
508 | for (vector <packagemeta *>::iterator i = db.packages.begin (); |
509 | i != db.packages.end (); ++i) | |
cbfc4215 | 510 | { |
cfae3b8d | 511 | packagemeta & pkg = **i; |
ab57ceaa | 512 | |
3c196821 | 513 | if (pkg.desired.changeRequested()) |
ab57ceaa | 514 | { |
3c196821 RC |
515 | if (pkg.desired.picked()) |
516 | total_bytes += pkg.desired.source()->size; | |
517 | if (pkg.desired.sourcePackage ().picked()) | |
518 | total_bytes += pkg.desired.sourcePackage ().source()->size; | |
ab57ceaa | 519 | } |
cbfc4215 | 520 | } |
bb849dbd | 521 | |
ad3c7385 | 522 | /* start with uninstalls - remove files that new packages may replace */ |
cfae3b8d RC |
523 | for (vector <packagemeta *>::iterator i = db.packages.begin (); |
524 | i != db.packages.end (); ++i) | |
23c9e63c | 525 | { |
cfae3b8d | 526 | packagemeta & pkg = **i; |
cbfc4215 | 527 | if (pkg.installed && (!pkg.desired || pkg.desired != pkg.installed)) |
ad3c7385 RC |
528 | uninstall_one (pkg); |
529 | } | |
530 | ||
531 | /* now in-place binary upgrades/reinstalls, as these may remove fils | |
532 | * that have been moved into new packages | |
533 | */ | |
534 | ||
cfae3b8d RC |
535 | for (vector <packagemeta *>::iterator i = db.packages.begin (); |
536 | i != db.packages.end (); ++i) | |
ad3c7385 | 537 | { |
cfae3b8d | 538 | packagemeta & pkg = **i; |
3c196821 | 539 | if (pkg.installed && pkg.desired.picked()) |
4a83b7b0 | 540 | { |
58ee6135 RC |
541 | try { |
542 | int e = 0; | |
543 | e += replace_one (pkg); | |
544 | if (e) | |
545 | errors++; | |
546 | } | |
547 | catch (exception *e) | |
548 | { | |
549 | if (yesno (owner, IDS_INSTALL_ERROR, e->what()) != IDYES) | |
550 | { | |
551 | log (LOG_TIMESTAMP, String ("User cancelled setup after install error")); | |
9f4a0c62 | 552 | LogSingleton::GetInstance().exit (1); |
58ee6135 RC |
553 | return; |
554 | } | |
555 | } | |
4a83b7b0 | 556 | } |
ad3c7385 RC |
557 | } |
558 | ||
cfae3b8d RC |
559 | for (vector <packagemeta *>::iterator i = db.packages.begin (); |
560 | i != db.packages.end (); ++i) | |
ad3c7385 | 561 | { |
cfae3b8d | 562 | packagemeta & pkg = **i; |
23c9e63c | 563 | |
3c196821 | 564 | if (pkg.desired && pkg.desired.changeRequested()) |
23c9e63c | 565 | { |
58ee6135 | 566 | try |
40aef45e | 567 | { |
58ee6135 RC |
568 | int e = 0; |
569 | e += install_one (pkg); | |
570 | if (e) | |
571 | errors++; | |
572 | } | |
573 | catch (exception *e) | |
574 | { | |
575 | if (yesno (owner, IDS_INSTALL_ERROR, e->what()) != IDYES) | |
576 | { | |
577 | log (LOG_TIMESTAMP, String ("User cancelled setup after install error")); | |
9f4a0c62 | 578 | LogSingleton::GetInstance().exit (1); |
58ee6135 RC |
579 | return; |
580 | } | |
40aef45e | 581 | } |
4a83b7b0 | 582 | } |
b24c88b3 | 583 | } // end of big package loop |
4a83b7b0 | 584 | |
ad3c7385 RC |
585 | if (rebootneeded) |
586 | note (owner, IDS_REBOOT_REQUIRED); | |
587 | ||
7c7034e8 RC |
588 | int temperr; |
589 | if ((temperr = db.flush ())) | |
23c9e63c | 590 | { |
7c7034e8 | 591 | const char *err = strerror (temperr); |
23c9e63c DD |
592 | if (!err) |
593 | err = "(unknown error)"; | |
3c054baf RC |
594 | fatal (owner, IDS_ERR_OPEN_WRITE, "Package Database", |
595 | err); | |
23c9e63c DD |
596 | } |
597 | ||
72fd1d1e CF |
598 | if (!errors) |
599 | check_for_old_cygwin (); | |
4a83b7b0 DD |
600 | if (num_installs == 0 && num_uninstalls == 0) |
601 | { | |
f2ff9838 | 602 | if (!unattended_mode) exit_msg = IDS_NOTHING_INSTALLED; |
4a83b7b0 DD |
603 | return; |
604 | } | |
605 | if (num_installs == 0) | |
606 | { | |
f2ff9838 | 607 | if (!unattended_mode) exit_msg = IDS_UNINSTALL_COMPLETE; |
4a83b7b0 DD |
608 | return; |
609 | } | |
610 | ||
2a1a01e0 DD |
611 | if (errors) |
612 | exit_msg = IDS_INSTALL_INCOMPLETE; | |
f2ff9838 | 613 | else if (!unattended_mode) |
2a1a01e0 | 614 | exit_msg = IDS_INSTALL_COMPLETE; |
23c9e63c | 615 | } |
ab57ceaa | 616 | |
45e01f23 | 617 | static DWORD WINAPI |
ab57ceaa RC |
618 | do_install_reflector (void *p) |
619 | { | |
620 | HANDLE *context; | |
621 | context = (HANDLE *) p; | |
622 | ||
623 | do_install_thread ((HINSTANCE) context[0], (HWND) context[1]); | |
624 | ||
625 | // Tell the progress page that we're done downloading | |
626 | Progress.PostMessage (WM_APP_INSTALL_THREAD_COMPLETE); | |
627 | ||
45e01f23 | 628 | ExitThread (0); |
ab57ceaa RC |
629 | } |
630 | ||
631 | static HANDLE context[2]; | |
632 | ||
633 | void | |
634 | do_install (HINSTANCE h, HWND owner) | |
635 | { | |
636 | context[0] = h; | |
637 | context[1] = owner; | |
638 | ||
45e01f23 RC |
639 | DWORD threadID; |
640 | CreateThread (NULL, 0, do_install_reflector, context, 0, &threadID); | |
ab57ceaa | 641 | } |