]> cygwin.com Git - cygwin-apps/setup.git/blame - install.cc
2002-01-04 Jan Nieuwenhuizen <janneke@gnu.org>
[cygwin-apps/setup.git] / install.cc
CommitLineData
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
RC
22#if 0
23static const char *cvsid =
24 "\n%%% $Id$\n";
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"
41#include "ini.h"
42#include "dialog.h"
43#include "concat.h"
44#include "geturl.h"
45#include "mkdir.h"
46#include "state.h"
23c9e63c
DD
47#include "diskfull.h"
48#include "msg.h"
49#include "mount.h"
89b1a15b 50#include "log.h"
a351e48c 51#include "mount.h"
c46a33a9 52#include "filemanip.h"
b24c88b3
RC
53#include "io_stream.h"
54#include "compress.h"
55#include "compress_gz.h"
56#include "archive.h"
57#include "archive_tar.h"
8e9aa511 58#include "script.h"
4a83b7b0 59
fa0c0d10
RC
60#include "package_db.h"
61#include "package_meta.h"
bb849dbd
RC
62#include "package_version.h"
63#include "package_source.h"
fa0c0d10 64
4a83b7b0 65#include "port.h"
23c9e63c 66
ab57ceaa
RC
67#include "threebar.h"
68extern ThreeBarProgressPage Progress;
23c9e63c
DD
69
70static int total_bytes = 0;
71static int total_bytes_sofar = 0;
72static int package_bytes = 0;
73
23c9e63c
DD
74static void
75init_dialog ()
76{
ab57ceaa
RC
77 Progress.SetText2 ("");
78 Progress.SetText3 ("");
23c9e63c
DD
79}
80
81static void
82progress (int bytes)
83{
ab57ceaa 84 if (package_bytes > 0)
23c9e63c 85 {
ab57ceaa 86 Progress.SetBar1 (bytes, package_bytes);
23c9e63c
DD
87 }
88
ab57ceaa 89 if (total_bytes > 0)
23c9e63c 90 {
ab57ceaa 91 Progress.SetBar2 (total_bytes_sofar + bytes, total_bytes);
23c9e63c 92 }
23c9e63c
DD
93}
94
b24c88b3 95static const char *standard_dirs[] = {
1a18aed7 96 "/bin",
904d24fe 97 "/etc",
1a18aed7 98 "/lib",
904d24fe 99 "/tmp",
4a83b7b0 100 "/usr",
1a18aed7
DD
101 "/usr/bin",
102 "/usr/lib",
ef45c299 103 "/usr/src",
4a83b7b0 104 "/usr/local",
1a18aed7
DD
105 "/usr/local/bin",
106 "/usr/local/etc",
107 "/usr/local/lib",
904d24fe 108 "/usr/tmp",
1a18aed7 109 "/var/run",
904d24fe
DD
110 "/var/tmp",
111 0
112};
113
3b9077d4
DD
114static int num_installs, num_uninstalls;
115
fa0c0d10 116/* FIXME: upgrades should be a method too */
3b9077d4 117static void
cbfc4215 118uninstall_one (packagemeta & pkgm)
3b9077d4 119{
ab57ceaa
RC
120 Progress.SetText1 ("Uninstalling...");
121 Progress.SetText2 (pkgm.name);
122 log (0, "Uninstalling %s", pkgm.name);
123 pkgm.uninstall ();
124 num_uninstalls++;
3b9077d4
DD
125}
126
42bf5b92 127
bb849dbd
RC
128
129/* install one source at a given prefix. */
3b9077d4 130static int
bb849dbd
RC
131install_one_source (packagemeta & pkgm, packagesource & source,
132 char const *prefix, package_type_t type)
3b9077d4
DD
133{
134 int errors = 0;
ab57ceaa 135 Progress.SetText2 (source.Base ());
bb849dbd 136 if (!io_stream::exists (source.Cached ()))
c46a33a9 137 {
ab57ceaa 138 note (NULL, IDS_ERR_OPEN_READ, source.Cached (), "No such file");
bb849dbd 139 return 1;
c46a33a9 140 }
bb849dbd
RC
141 io_stream *lst = 0;
142 if (type == package_binary)
c46a33a9 143 {
bb849dbd
RC
144 io_stream *tmp =
145 io_stream::
146 open (concat ("cygfile:///etc/setup/", pkgm.name, ".lst.gz", 0),
147 "wb");
148 lst = new compress_gz (tmp, "w9");
149 if (lst->error ())
150 {
151 delete lst;
152 lst = NULL;
153 }
c46a33a9 154 }
b24c88b3 155
bb849dbd 156 package_bytes = source.size;
3b9077d4 157
bb849dbd
RC
158 char msg[64];
159 strcpy (msg, "Installing");
ab57ceaa 160 Progress.SetText1 (msg);
bb849dbd
RC
161 log (0, "%s%s", msg, source.Cached ());
162 io_stream *tmp = io_stream::open (source.Cached (), "rb");
163 archive *thefile = 0;
164 if (tmp)
d4a4527d 165 {
bb849dbd
RC
166 io_stream *tmp2 = compress::decompress (tmp);
167 if (tmp2)
168 thefile = archive::extract (tmp2);
169 else
170 thefile = archive::extract (tmp);
3b9077d4 171 }
bb849dbd
RC
172 /* FIXME: potential leak of either *tmp or *tmp2 */
173 if (thefile)
d4a4527d 174 {
bb849dbd
RC
175 const char *fn;
176 while ((fn = thefile->next_file_name ()))
177 {
178 if (lst)
179 lst->write (concat (fn, "\n", 0), strlen (fn) + 1);
180
181 /* FIXME: concat leaks memory */
ab57ceaa 182 Progress.SetText3 (concat (prefix, fn, 0));
bb849dbd
RC
183 log (LOG_BABBLE, "Installing file %s%s", prefix, fn);
184 if (archive::extract_file (thefile, prefix) != 0)
185 {
186 log (0, "Unable to install file %s%s", prefix, fn);
187 errors++;
188 }
189
190 progress (tmp->tell ());
191 num_installs++;
192 }
193 delete thefile;
194
195 total_bytes_sofar += package_bytes;
d4a4527d 196 }
3b9077d4 197
90d14922 198
bb849dbd
RC
199 progress (0);
200
201 int df = diskfull (get_root_dir ());
ab57ceaa 202 Progress.SetBar3 (df);
bb849dbd
RC
203
204 if (lst)
205 delete lst;
206
207 return errors;
208}
209
210/* install a package, install both the binary and source aspects if needed */
211static int
212install_one (packagemeta & pkg)
213{
214 int errors = 0;
215
216 if (pkg.desired->binpicked)
ab57ceaa 217 {
bb849dbd 218 errors +=
ab57ceaa
RC
219 install_one_source (pkg, pkg.desired->bin, "cygfile:///",
220 package_binary);
221 if (!errors)
222 pkg.installed = pkg.desired;
223 }
224 if (pkg.desired->srcpicked)
225 errors +=
226 install_one_source (pkg, pkg.desired->src, "cygfile:///usr/src",
227 package_source);
bb849dbd
RC
228
229 /* FIXME: make a upgrade method and reinstate this */
230#if 0
c46a33a9
CF
231 char msg[64];
232 if (!pkg->installed)
233 strcpy (msg, "Installing");
234 else
235 {
236 int n = strcmp (pi->version, pkg->installed->version);
237 if (n < 0)
238 strcpy (msg, "Reverting");
239 else if (n == 0)
240 strcpy (msg, "Reinstalling");
241 else
242 strcpy (msg, "Upgrading");
243 }
244
245 switch (pkg->action)
3b9077d4 246 {
c46a33a9
CF
247 case ACTION_PREV:
248 strcat (msg, " previous version...");
3b9077d4 249 break;
c46a33a9
CF
250 case ACTION_CURR:
251 strcat (msg, "...");
3b9077d4 252 break;
c46a33a9
CF
253 case ACTION_TEST:
254 strcat (msg, " test version...");
42bf5b92 255 break;
b24c88b3
RC
256 default:
257 /* FIXME: log this somehow */
258 break;
3b9077d4 259 }
c46a33a9
CF
260 SetWindowText (ins_action, msg);
261 log (0, "%s%s", msg, file);
bb849dbd 262#endif
c46a33a9 263
3b9077d4
DD
264 return errors;
265}
266
72fd1d1e
CF
267static void
268check_for_old_cygwin ()
269{
270 char buf[_MAX_PATH + sizeof ("\\cygwin1.dll")];
271 if (!GetSystemDirectory (buf, sizeof (buf)))
272 return;
273 strcat (buf, "\\cygwin1.dll");
274 if (_access (buf, 0) != 0)
275 return;
276
277 char msg[sizeof (buf) + 132];
b24c88b3
RC
278 sprintf (msg,
279 "An old version of cygwin1.dll was found here:\r\n%s\r\nDelete?",
280 buf);
281 switch (MessageBox
282 (NULL, msg, "What's that doing there?",
283 MB_YESNO | MB_ICONQUESTION | MB_TASKMODAL))
72fd1d1e
CF
284 {
285 case IDYES:
286 if (!DeleteFile (buf))
287 {
288 sprintf (msg, "Couldn't delete file %s.\r\n"
b24c88b3 289 "Is the DLL in use by another application?\r\n"
7c7034e8
RC
290 "You should delete the old version of cygwin1.dll\r\n"
291 "at your earliest convenience.", buf);
b24c88b3
RC
292 MessageBox (NULL, buf, "Couldn't delete file",
293 MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL);
72fd1d1e
CF
294 }
295 break;
296 default:
b24c88b3 297 break;
72fd1d1e
CF
298 }
299
300 return;
301}
302
ab57ceaa
RC
303static void
304do_install_thread (HINSTANCE h, HWND owner)
23c9e63c 305{
3b9077d4 306 int i;
2a1a01e0
DD
307 int errors = 0;
308
3b9077d4
DD
309 num_installs = 0, num_uninstalls = 0;
310
50225eae 311 next_dialog = IDD_DESKTOP;
23c9e63c 312
85b43844 313 mkdir_p (1, get_root_dir ());
904d24fe 314
b24c88b3 315 for (i = 0; standard_dirs[i]; i++)
904d24fe 316 {
a351e48c 317 char *p = cygpath (standard_dirs[i], 0);
904d24fe
DD
318 mkdir_p (1, p);
319 free (p);
320 }
321
1a18aed7 322 /* Create /var/run/utmp */
b24c88b3
RC
323 io_stream *utmp = io_stream::open ("cygfile:///var/run/utmp", "wb");
324 delete utmp;
1a18aed7 325
23c9e63c
DD
326 init_dialog ();
327
328 total_bytes = 0;
329 total_bytes_sofar = 0;
330
85b43844 331 int df = diskfull (get_root_dir ());
ab57ceaa 332 Progress.SetBar3 (df);
d07591a3 333
0af2d779
CF
334 int istext = (root_text == IDC_ROOT_TEXT) ? 1 : 0;
335 int issystem = (root_scope == IDC_ROOT_SYSTEM) ? 1 : 0;
336
337 create_mount ("/", get_root_dir (), istext, issystem);
338 create_mount ("/usr/bin", cygpath ("/bin", 0), istext, issystem);
339 create_mount ("/usr/lib", cygpath ("/lib", 0), istext, issystem);
340 set_cygdrive_flags (istext, issystem);
341
8e9aa511
RC
342 /* Let's hope people won't uninstall packages before installing [b]ash */
343 init_run_script ();
344
bb849dbd 345 packagedb db;
cbfc4215
RC
346 for (size_t n = 1; n < db.packages.number (); n++)
347 {
ab57ceaa
RC
348 packagemeta & pkg = *db.packages[n];
349
350 if (pkg.desired && (pkg.desired->srcpicked || pkg.desired->binpicked))
351 {
352 if (pkg.desired->srcpicked)
353 total_bytes += pkg.desired->src.size;
354 if (pkg.desired->binpicked)
355 total_bytes += pkg.desired->bin.size;
356 }
cbfc4215 357 }
bb849dbd 358
cbfc4215 359 for (size_t n = 1; n < db.packages.number (); n++)
23c9e63c 360 {
ab57ceaa 361 packagemeta & pkg = *db.packages[n];
cbfc4215 362 if (pkg.installed && (!pkg.desired || pkg.desired != pkg.installed))
4a83b7b0 363 {
fa0c0d10 364 uninstall_one (pkg);
4a83b7b0 365 }
23c9e63c 366
ab57ceaa 367 if (pkg.desired && (pkg.desired->srcpicked || pkg.desired->binpicked))
23c9e63c 368 {
c46a33a9 369 int e = 0;
cbfc4215 370 e += install_one (pkg);
3b9077d4 371 if (e)
40aef45e 372 {
3b9077d4 373 errors++;
40aef45e 374 }
4a83b7b0 375 }
b24c88b3 376 } // end of big package loop
4a83b7b0 377
7c7034e8
RC
378 int temperr;
379 if ((temperr = db.flush ()))
23c9e63c 380 {
7c7034e8 381 const char *err = strerror (temperr);
23c9e63c
DD
382 if (!err)
383 err = "(unknown error)";
ab57ceaa 384 fatal (owner, IDS_ERR_OPEN_WRITE, err);
23c9e63c
DD
385 }
386
72fd1d1e
CF
387 if (!errors)
388 check_for_old_cygwin ();
4a83b7b0
DD
389 if (num_installs == 0 && num_uninstalls == 0)
390 {
391 exit_msg = IDS_NOTHING_INSTALLED;
392 return;
393 }
394 if (num_installs == 0)
395 {
396 exit_msg = IDS_UNINSTALL_COMPLETE;
397 return;
398 }
399
2a1a01e0
DD
400 if (errors)
401 exit_msg = IDS_INSTALL_INCOMPLETE;
402 else
403 exit_msg = IDS_INSTALL_COMPLETE;
23c9e63c 404}
ab57ceaa
RC
405
406static void
407do_install_reflector (void *p)
408{
409 HANDLE *context;
410 context = (HANDLE *) p;
411
412 do_install_thread ((HINSTANCE) context[0], (HWND) context[1]);
413
414 // Tell the progress page that we're done downloading
415 Progress.PostMessage (WM_APP_INSTALL_THREAD_COMPLETE);
416
417 _endthread ();
418}
419
420static HANDLE context[2];
421
422void
423do_install (HINSTANCE h, HWND owner)
424{
425 context[0] = h;
426 context[1] = owner;
427
428 _beginthread (do_install_reflector, 0, context);
429}
This page took 0.075631 seconds and 5 git commands to generate.