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