]> cygwin.com Git - cygwin-apps/setup.git/blob - install.cc
2001-01-04 Robert Collins <rbtcollins@hotmail.com>
[cygwin-apps/setup.git] / install.cc
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 install 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
20 files in /etc/setup/\* and create the mount points. */
21
22 #if 0
23 static const char *cvsid =
24 "\n%%% $Id$\n";
25 #endif
26
27 #include "win32.h"
28 #include "commctrl.h"
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <unistd.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <errno.h>
36 #include <process.h>
37
38 #include "zlib/zlib.h"
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"
47 #include "diskfull.h"
48 #include "msg.h"
49 #include "mount.h"
50 #include "log.h"
51 #include "mount.h"
52 #include "filemanip.h"
53 #include "io_stream.h"
54 #include "compress.h"
55 #include "compress_gz.h"
56 #include "archive.h"
57 #include "archive_tar.h"
58 #include "script.h"
59
60 #include "package_db.h"
61 #include "package_meta.h"
62 #include "package_version.h"
63 #include "package_source.h"
64
65 #include "port.h"
66
67 #include "threebar.h"
68 extern ThreeBarProgressPage Progress;
69
70 static int total_bytes = 0;
71 static int total_bytes_sofar = 0;
72 static int package_bytes = 0;
73
74 static void
75 init_dialog ()
76 {
77 Progress.SetText2 ("");
78 Progress.SetText3 ("");
79 }
80
81 static void
82 progress (int bytes)
83 {
84 if (package_bytes > 0)
85 {
86 Progress.SetBar1 (bytes, package_bytes);
87 }
88
89 if (total_bytes > 0)
90 {
91 Progress.SetBar2 (total_bytes_sofar + bytes, total_bytes);
92 }
93 }
94
95 static const char *standard_dirs[] = {
96 "/bin",
97 "/etc",
98 "/lib",
99 "/tmp",
100 "/usr",
101 "/usr/bin",
102 "/usr/lib",
103 "/usr/src",
104 "/usr/local",
105 "/usr/local/bin",
106 "/usr/local/etc",
107 "/usr/local/lib",
108 "/usr/tmp",
109 "/var/run",
110 "/var/tmp",
111 0
112 };
113
114 static int num_installs, num_uninstalls;
115
116 /* FIXME: upgrades should be a method too */
117 static void
118 uninstall_one (packagemeta & pkgm)
119 {
120 Progress.SetText1 ("Uninstalling...");
121 Progress.SetText2 (pkgm.name);
122 log (0, "Uninstalling %s", pkgm.name);
123 pkgm.uninstall ();
124 num_uninstalls++;
125 }
126
127
128
129 /* install one source at a given prefix. */
130 static int
131 install_one_source (packagemeta & pkgm, packagesource & source,
132 char const *prefix, package_type_t type)
133 {
134 int errors = 0;
135 Progress.SetText2 (source.Base ());
136 if (!io_stream::exists (source.Cached ()))
137 {
138 note (NULL, IDS_ERR_OPEN_READ, source.Cached (), "No such file");
139 return 1;
140 }
141 io_stream *lst = 0;
142 if (type == package_binary)
143 {
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 }
154 }
155
156 package_bytes = source.size;
157
158 char msg[64];
159 strcpy (msg, "Installing");
160 Progress.SetText1 (msg);
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)
165 {
166 io_stream *tmp2 = compress::decompress (tmp);
167 if (tmp2)
168 thefile = archive::extract (tmp2);
169 else
170 thefile = archive::extract (tmp);
171 }
172 /* FIXME: potential leak of either *tmp or *tmp2 */
173 if (thefile)
174 {
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 */
182 Progress.SetText3 (concat (prefix, fn, 0));
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;
196 }
197
198
199 progress (0);
200
201 int df = diskfull (get_root_dir ());
202 Progress.SetBar3 (df);
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 */
211 static int
212 install_one (packagemeta & pkg)
213 {
214 int errors = 0;
215
216 if (pkg.desired->binpicked)
217 {
218 errors +=
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);
228
229 /* FIXME: make a upgrade method and reinstate this */
230 #if 0
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)
246 {
247 case ACTION_PREV:
248 strcat (msg, " previous version...");
249 break;
250 case ACTION_CURR:
251 strcat (msg, "...");
252 break;
253 case ACTION_TEST:
254 strcat (msg, " test version...");
255 break;
256 default:
257 /* FIXME: log this somehow */
258 break;
259 }
260 SetWindowText (ins_action, msg);
261 log (0, "%s%s", msg, file);
262 #endif
263
264 return errors;
265 }
266
267 static void
268 check_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];
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))
284 {
285 case IDYES:
286 if (!DeleteFile (buf))
287 {
288 sprintf (msg, "Couldn't delete file %s.\r\n"
289 "Is the DLL in use by another application?\r\n"
290 "You should delete the old version of cygwin1.dll\r\n"
291 "at your earliest convenience.", buf);
292 MessageBox (NULL, buf, "Couldn't delete file",
293 MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL);
294 }
295 break;
296 default:
297 break;
298 }
299
300 return;
301 }
302
303 static void
304 do_install_thread (HINSTANCE h, HWND owner)
305 {
306 int i;
307 int errors = 0;
308
309 num_installs = 0, num_uninstalls = 0;
310
311 next_dialog = IDD_DESKTOP;
312
313 mkdir_p (1, get_root_dir ());
314
315 for (i = 0; standard_dirs[i]; i++)
316 {
317 char *p = cygpath (standard_dirs[i], 0);
318 mkdir_p (1, p);
319 free (p);
320 }
321
322 /* Create /var/run/utmp */
323 io_stream *utmp = io_stream::open ("cygfile:///var/run/utmp", "wb");
324 delete utmp;
325
326 init_dialog ();
327
328 total_bytes = 0;
329 total_bytes_sofar = 0;
330
331 int df = diskfull (get_root_dir ());
332 Progress.SetBar3 (df);
333
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
342 /* Let's hope people won't uninstall packages before installing [b]ash */
343 init_run_script ();
344
345 packagedb db;
346 for (size_t n = 1; n <= db.packages.number (); n++)
347 {
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 }
357 }
358
359 for (size_t n = 1; n <= db.packages.number (); n++)
360 {
361 packagemeta & pkg = *db.packages[n];
362 if (pkg.installed && (!pkg.desired || pkg.desired != pkg.installed))
363 {
364 uninstall_one (pkg);
365 }
366
367 if (pkg.desired && (pkg.desired->srcpicked || pkg.desired->binpicked))
368 {
369 int e = 0;
370 e += install_one (pkg);
371 if (e)
372 {
373 errors++;
374 }
375 }
376 } // end of big package loop
377
378 int temperr;
379 if ((temperr = db.flush ()))
380 {
381 const char *err = strerror (temperr);
382 if (!err)
383 err = "(unknown error)";
384 fatal (owner, IDS_ERR_OPEN_WRITE, err);
385 }
386
387 if (!errors)
388 check_for_old_cygwin ();
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
400 if (errors)
401 exit_msg = IDS_INSTALL_INCOMPLETE;
402 else
403 exit_msg = IDS_INSTALL_COMPLETE;
404 }
405
406 static void
407 do_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
420 static HANDLE context[2];
421
422 void
423 do_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.060594 seconds and 5 git commands to generate.