]> cygwin.com Git - cygwin-apps/setup.git/blame - install.cc
* net.cc (do_net): Default to direct download.
[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
20 files in /etc/setup/* and create the mount points. */
21
8507f105
DD
22static char *cvsid = "\n%%% $Id$\n";
23
23c9e63c
DD
24#include "win32.h"
25#include "commctrl.h"
26
27#include <stdio.h>
904d24fe 28#include <stdlib.h>
4a83b7b0 29#include <unistd.h>
23c9e63c
DD
30#include <sys/types.h>
31#include <sys/stat.h>
32#include <errno.h>
33#include "zlib/zlib.h"
34
35#include "resource.h"
36#include "ini.h"
37#include "dialog.h"
38#include "concat.h"
39#include "geturl.h"
40#include "mkdir.h"
41#include "state.h"
42#include "tar.h"
43#include "diskfull.h"
44#include "msg.h"
45#include "mount.h"
89b1a15b 46#include "log.h"
4a83b7b0
DD
47#include "hash.h"
48
49#include "port.h"
23c9e63c
DD
50
51static HWND ins_dialog = 0;
4a83b7b0 52static HWND ins_action = 0;
23c9e63c
DD
53static HWND ins_pkgname = 0;
54static HWND ins_filename = 0;
55static HWND ins_pprogress = 0;
56static HWND ins_iprogress = 0;
57static HWND ins_diskfull = 0;
58static HANDLE init_event;
59
60static int total_bytes = 0;
61static int total_bytes_sofar = 0;
62static int package_bytes = 0;
63
64static BOOL
65dialog_cmd (HWND h, int id, HWND hwndctl, UINT code)
66{
67 switch (id)
68 {
69 case IDCANCEL:
89b1a15b 70 exit_setup (1);
23c9e63c
DD
71 }
72}
73
74static BOOL CALLBACK
75dialog_proc (HWND h, UINT message, WPARAM wParam, LPARAM lParam)
76{
77 int i, j;
78 HWND listbox;
79 switch (message)
80 {
81 case WM_INITDIALOG:
82 ins_dialog = h;
4a83b7b0 83 ins_action = GetDlgItem (h, IDC_INS_ACTION);
23c9e63c
DD
84 ins_pkgname = GetDlgItem (h, IDC_INS_PKG);
85 ins_filename = GetDlgItem (h, IDC_INS_FILE);
86 ins_pprogress = GetDlgItem (h, IDC_INS_PPROGRESS);
87 ins_iprogress = GetDlgItem (h, IDC_INS_IPROGRESS);
88 ins_diskfull = GetDlgItem (h, IDC_INS_DISKFULL);
89 SetEvent (init_event);
90 return FALSE;
91 case WM_COMMAND:
1fd6d0a2 92 return HANDLE_WM_COMMAND (h, wParam, lParam, dialog_cmd);
23c9e63c
DD
93 }
94 return FALSE;
95}
96
97static WINAPI DWORD
98dialog (void *)
99{
100 int rv = 0;
101 MSG m;
ed96c6da 102 HWND ins_dialog = CreateDialog (hinstance, MAKEINTRESOURCE (IDD_INSTATUS),
23c9e63c
DD
103 0, dialog_proc);
104 if (ins_dialog == 0)
105 fatal ("create dialog");
106 ShowWindow (ins_dialog, SW_SHOWNORMAL);
107 UpdateWindow (ins_dialog);
108 while (GetMessage (&m, 0, 0, 0) > 0) {
109 TranslateMessage (&m);
110 DispatchMessage (&m);
111 }
112}
113
114static DWORD start_tics;
115
116static void
117init_dialog ()
118{
119 if (ins_dialog == 0)
120 {
121 DWORD tid;
122 HANDLE thread;
123 init_event = CreateEvent (0, 0, 0, 0);
124 thread = CreateThread (0, 0, dialog, 0, 0, &tid);
125 WaitForSingleObject (init_event, 10000);
126 CloseHandle (init_event);
127 SendMessage (ins_pprogress, PBM_SETRANGE, 0, MAKELPARAM (0, 100));
128 SendMessage (ins_iprogress, PBM_SETRANGE, 0, MAKELPARAM (0, 100));
129 SendMessage (ins_diskfull, PBM_SETRANGE, 0, MAKELPARAM (0, 100));
130 }
131
132 SetWindowText (ins_pkgname, "");
133 SetWindowText (ins_filename, "");
134 SendMessage (ins_pprogress, PBM_SETPOS, (WPARAM) 0, 0);
135 SendMessage (ins_iprogress, PBM_SETPOS, (WPARAM) 0, 0);
136 SendMessage (ins_diskfull, PBM_SETPOS, (WPARAM) 0, 0);
137 ShowWindow (ins_dialog, SW_SHOWNORMAL);
138 SetForegroundWindow (ins_dialog);
139}
140
141static void
142progress (int bytes)
143{
144 int perc;
145
bf1d5889 146 if (package_bytes > 100)
23c9e63c 147 {
bf1d5889 148 perc = bytes / (package_bytes / 100);
23c9e63c
DD
149 SendMessage (ins_pprogress, PBM_SETPOS, (WPARAM) perc, 0);
150 }
151
bf1d5889 152 if (total_bytes > 100)
23c9e63c 153 {
bf1d5889 154 perc = (total_bytes_sofar + bytes) / (total_bytes / 100);
23c9e63c
DD
155 SendMessage (ins_iprogress, PBM_SETPOS, (WPARAM) perc, 0);
156 }
23c9e63c
DD
157}
158
159static void
160badrename (char *o, char *n)
161{
162 char buf[1000];
163 char *err = strerror (errno);
164 if (!err)
165 err = "(unknown error)";
166 note (IDS_ERR_RENAME, o, n, err);
167}
168
904d24fe 169static char *standard_dirs[] = {
1a18aed7 170 "/bin",
904d24fe 171 "/etc",
1a18aed7 172 "/lib",
904d24fe 173 "/tmp",
4a83b7b0 174 "/usr",
1a18aed7
DD
175 "/usr/bin",
176 "/usr/lib",
ef45c299 177 "/usr/src",
4a83b7b0 178 "/usr/local",
1a18aed7
DD
179 "/usr/local/bin",
180 "/usr/local/etc",
181 "/usr/local/lib",
904d24fe 182 "/usr/tmp",
1a18aed7 183 "/var/run",
904d24fe
DD
184 "/var/tmp",
185 0
186};
187
4a83b7b0
DD
188void
189hash::add_subdirs (char *path)
190{
191 char *nonp, *pp;
192 for (nonp = path; *nonp == '\\' || *nonp == '/'; nonp++);
193 for (pp = path + strlen(path) - 1; pp>nonp; pp--)
194 if (*pp == '/' || *pp == '\\')
195 {
196 int i, s=0;
197 char c = *pp;
198 *pp = 0;
199 for (i=0; standard_dirs[i]; i++)
200 if (strcmp (standard_dirs[i]+1, path) == 0)
201 {
202 s = 1;
203 break;
204 }
205 if (s == 0)
206 add (path);
207 *pp = c;
208 }
209}
210
211char *
ef45c299 212map_filename (char *fn, const char *extra = 0)
4a83b7b0
DD
213{
214 char *dest_file;
ef45c299 215 char *root_dir_with_extra = concat (root_dir, extra, 0);
4a83b7b0
DD
216 while (*fn == '/' || *fn == '\\')
217 fn++;
218 if (strncmp (fn, "usr/bin/", 8) == 0)
ef45c299 219 dest_file = concat (root_dir_with_extra, "/bin/", fn+8, 0);
4a83b7b0 220 else if (strncmp (fn, "usr/lib/", 8) == 0)
ef45c299 221 dest_file = concat (root_dir_with_extra, "/lib/", fn+8, 0);
4a83b7b0 222 else
ef45c299 223 dest_file = concat (root_dir_with_extra, "/", fn, 0);
4a83b7b0
DD
224 return dest_file;
225}
226
40aef45e
DD
227static int
228exists (char *file)
229{
230 if (_access (file, 0) == 0)
231 return 1;
232 return 0;
233}
234
3b9077d4
DD
235
236static int num_installs, num_uninstalls;
237
238static void
239uninstall_one (char *name, int action)
240{
241 hash dirs;
242 char line[_MAX_PATH];
243
244 gzFile lst = gzopen (concat (root_dir, "/etc/setup/",
245 name, ".lst.gz", 0),
246 "rb");
247 if (lst)
248 {
249 SetWindowText (ins_pkgname, name);
250 SetWindowText (ins_action, "Uninstalling...");
251 if (action == ACTION_UPGRADE)
252 log (0, "Uninstalling old %s", name);
253 else
254 log (0, "Uninstalling %s", name);
255
256 while (gzgets (lst, line, sizeof (line)))
257 {
258 if (line[strlen(line)-1] == '\n')
259 line[strlen(line)-1] = 0;
260
261 dirs.add_subdirs (line);
262
263 char *d = map_filename (line);
264 DWORD dw = GetFileAttributes (d);
265 if (dw != 0xffffffff && !(dw & FILE_ATTRIBUTE_DIRECTORY))
266 {
267 log (LOG_BABBLE, "unlink %s", d);
268 DeleteFile (d);
269 }
270 }
271 gzclose (lst);
272
273 remove (concat (root_dir, "/etc/setup/", name, ".lst.gz", 0));
274
275 dirs.reverse_sort ();
276 char *subdir = 0;
277 while ((subdir = dirs.enumerate (subdir)) != 0)
278 {
279 char *d = map_filename (subdir);
280 if (RemoveDirectory (d))
281 log (LOG_BABBLE, "rmdir %s", d);
282 }
fb087b80 283 num_uninstalls++;
3b9077d4
DD
284 }
285}
286
287
288static int
ef45c299 289install_one (char *name, char *file, int file_size, int action, BOOL isSrc)
3b9077d4
DD
290{
291 int errors = 0;
292 char *local = file, *cp, *fn, *base;
293
294 base = local;
295 for (cp=local; *cp; cp++)
296 if (*cp == '/' || *cp == '\\' || *cp == ':')
297 base = cp+1;
298 SetWindowText (ins_pkgname, base);
299
300 if (!exists (local) && exists (base))
301 local = base;
302 if (!exists (local))
303 {
304 note (IDS_ERR_OPEN_READ, local, "No such file");
305 return 1;
306 }
307
308 gzFile lst = gzopen (concat (root_dir, "/etc/setup/",
309 name, ".lst.gz", 0),
310 "wb9");
311
312 package_bytes = file_size;
313
314 switch (action)
315 {
316 case ACTION_NEW:
317 SetWindowText (ins_action, "Installing...");
318 break;
319 case ACTION_UPGRADE:
320 SetWindowText (ins_action, "Upgrading...");
321 break;
322 }
323
324 log (0, "Installing %s", local);
325 tar_open (local);
326 while (fn = tar_next_file ())
327 {
328 char *dest_file;
329
330 if (lst)
331 gzprintf (lst, "%s\n", fn);
332
ef45c299 333 dest_file = map_filename (fn, isSrc?"/usr/src":NULL);
3b9077d4
DD
334
335 SetWindowText (ins_filename, dest_file);
336 log (LOG_BABBLE, "Installing file %s", dest_file);
337 if (tar_read_file (dest_file) != 0)
338 {
339 log (0, "Unable to install file %s", dest_file);
fb087b80 340 errors++;
3b9077d4
DD
341 }
342
343 progress (tar_ftell ());
fb087b80 344 num_installs++;
3b9077d4
DD
345 }
346 tar_close ();
347
348 total_bytes_sofar += file_size;
349 progress (0);
350
351 int df = diskfull (root_dir);
352 SendMessage (ins_diskfull, PBM_SETPOS, (WPARAM) df, 0);
353
354 if (lst)
355 gzclose (lst);
356
357 return errors;
358}
359
23c9e63c
DD
360void
361do_install (HINSTANCE h)
362{
3b9077d4 363 int i;
2a1a01e0
DD
364 int errors = 0;
365
3b9077d4
DD
366 num_installs = 0, num_uninstalls = 0;
367
50225eae 368 next_dialog = IDD_DESKTOP;
23c9e63c 369
904d24fe
DD
370 mkdir_p (1, root_dir);
371
372 for (i=0; standard_dirs[i]; i++)
373 {
374 char *p = concat (root_dir, standard_dirs[i], 0);
375 mkdir_p (1, p);
376 free (p);
377 }
378
1a18aed7
DD
379 /* Create /var/run/utmp */
380 char *utmp = concat (root_dir, "/var/run/utmp", 0);
381 FILE *ufp = fopen (utmp, "wb");
382 if (ufp)
383 fclose (ufp);
384 free (utmp);
385
23c9e63c
DD
386 dismiss_url_status_dialog ();
387
388 init_dialog ();
389
390 total_bytes = 0;
391 total_bytes_sofar = 0;
392
d07591a3
DD
393 int df = diskfull (root_dir);
394 SendMessage (ins_diskfull, PBM_SETPOS, (WPARAM) df, 0);
395
23c9e63c
DD
396 LOOP_PACKAGES
397 {
398 total_bytes += pi.install_size;
ef45c299
CV
399 if (package[i].srcaction == SRCACTION_YES)
400 total_bytes += pi.source_size;
23c9e63c
DD
401 }
402
4a83b7b0 403 for (i=0; i<npackages; i++)
23c9e63c 404 {
4a83b7b0
DD
405 if (package[i].action == ACTION_UNINSTALL
406 || (package[i].action == ACTION_UPGRADE && pi.install))
407 {
3b9077d4
DD
408 uninstall_one (package[i].name, package[i].action);
409 uninstall_one (concat (package[i].name, "-src", 0), package[i].action);
4a83b7b0 410 }
23c9e63c 411
4a83b7b0
DD
412 if ((package[i].action == ACTION_NEW
413 || package[i].action == ACTION_UPGRADE)
414 && pi.install)
23c9e63c 415 {
ef45c299 416 int e = install_one (package[i].name, pi.install, pi.install_size, package[i].action, FALSE);
3b9077d4
DD
417 if (package[i].srcaction == SRCACTION_YES && pi.source)
418 e += install_one (concat (package[i].name, "-src", 0), pi.source, pi.source_size,
ef45c299 419 package[i].action, TRUE);
3b9077d4 420 if (e)
40aef45e
DD
421 {
422 package[i].action = ACTION_ERROR;
3b9077d4 423 errors++;
40aef45e 424 }
4a83b7b0
DD
425 }
426 } // end of big package loop
427
428 ShowWindow (ins_dialog, SW_HIDE);
23c9e63c
DD
429
430 char *odbn = concat (root_dir, "/etc/setup/installed.db", 0);
431 char *ndbn = concat (root_dir, "/etc/setup/installed.db.new", 0);
432 char *sdbn = concat (root_dir, "/etc/setup/installed.db.old", 0);
433
434 mkdir_p (0, ndbn);
435
436 FILE *odb = fopen (odbn, "rt");
437 FILE *ndb = fopen (ndbn, "wb");
438
439 if (!ndb)
440 {
441 char *err = strerror (errno);
442 if (!err)
443 err = "(unknown error)";
444 fatal (IDS_ERR_OPEN_WRITE, ndb, err);
445 }
446
447 if (odb)
448 {
449 char line[1000], pkg[1000];
450 int printit;
451 while (fgets (line, 1000, odb))
452 {
453 printit = 1;
1fd6d0a2 454 sscanf (line, "%s", pkg);
4a83b7b0 455 for (i=0; i<npackages; i++)
23c9e63c
DD
456 {
457 if (strcmp (pkg, package[i].name) == 0)
4a83b7b0
DD
458 switch (package[i].action)
459 {
460 case ACTION_NEW:
461 case ACTION_UPGRADE:
462 case ACTION_UNINSTALL:
463 printit = 0;
464 break;
465 }
23c9e63c
DD
466 }
467 if (printit)
468 fputs (line, ndb);
469 }
470
471 }
4a83b7b0 472
23c9e63c
DD
473 LOOP_PACKAGES
474 {
3b9077d4
DD
475 if (package[i].srcaction == SRCACTION_YES)
476 fprintf (ndb, "%s %s %d %s %d\n", package[i].name,
477 pi.install, pi.install_size,
478 pi.source, pi.source_size);
479 else
480 fprintf (ndb, "%s %s %d\n", package[i].name,
481 pi.install, pi.install_size);
23c9e63c
DD
482 }
483
484 if (odb)
485 fclose (odb);
486 fclose (ndb);
487
488 remove (sdbn);
489 if (odb && rename (odbn, sdbn))
490 badrename (odbn, sdbn);
491
492 remove (odbn);
493 if (rename (ndbn, odbn))
494 badrename (ndbn, odbn);
495
4a83b7b0
DD
496 if (num_installs == 0 && num_uninstalls == 0)
497 {
498 exit_msg = IDS_NOTHING_INSTALLED;
499 return;
500 }
501 if (num_installs == 0)
502 {
503 exit_msg = IDS_UNINSTALL_COMPLETE;
504 return;
505 }
506
24e259bb 507 remove_mount ("/");
23c9e63c 508 remove_mount ("/usr");
24e259bb
DD
509 remove_mount ("/usr/bin");
510 remove_mount ("/usr/lib");
23c9e63c
DD
511 remove_mount ("/var");
512 remove_mount ("/lib");
513 remove_mount ("/bin");
514 remove_mount ("/etc");
515
516 int istext = (root_text == IDC_ROOT_TEXT) ? 1 : 0;
24e259bb 517 int issystem = (root_scope == IDC_ROOT_SYSTEM) ? 1 : 0;
23c9e63c 518
24e259bb
DD
519 create_mount ("/", root_dir, istext, issystem);
520 create_mount ("/usr/bin", concat (root_dir, "/bin", 0), istext, issystem);
521 create_mount ("/usr/lib", concat (root_dir, "/lib", 0), istext, issystem);
f8a6415f 522 set_cygdrive_flags (istext, issystem);
23c9e63c 523
2a1a01e0
DD
524 if (errors)
525 exit_msg = IDS_INSTALL_INCOMPLETE;
526 else
527 exit_msg = IDS_INSTALL_COMPLETE;
23c9e63c 528}
This page took 0.071612 seconds and 5 git commands to generate.