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