]> cygwin.com Git - cygwin-apps/setup.git/blame - install.cc
* download.cc (get_file_size): Remove `static'.
[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;
102 HANDLE ins_dialog = CreateDialog (hinstance, MAKEINTRESOURCE (IDD_INSTATUS),
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",
4a83b7b0 177 "/usr/local",
1a18aed7
DD
178 "/usr/local/bin",
179 "/usr/local/etc",
180 "/usr/local/lib",
904d24fe 181 "/usr/tmp",
1a18aed7 182 "/var/run",
904d24fe
DD
183 "/var/tmp",
184 0
185};
186
4a83b7b0
DD
187void
188hash::add_subdirs (char *path)
189{
190 char *nonp, *pp;
191 for (nonp = path; *nonp == '\\' || *nonp == '/'; nonp++);
192 for (pp = path + strlen(path) - 1; pp>nonp; pp--)
193 if (*pp == '/' || *pp == '\\')
194 {
195 int i, s=0;
196 char c = *pp;
197 *pp = 0;
198 for (i=0; standard_dirs[i]; i++)
199 if (strcmp (standard_dirs[i]+1, path) == 0)
200 {
201 s = 1;
202 break;
203 }
204 if (s == 0)
205 add (path);
206 *pp = c;
207 }
208}
209
210char *
211map_filename (char *fn)
212{
213 char *dest_file;
214 while (*fn == '/' || *fn == '\\')
215 fn++;
216 if (strncmp (fn, "usr/bin/", 8) == 0)
217 dest_file = concat (root_dir, "/bin/", fn+8, 0);
218 else if (strncmp (fn, "usr/lib/", 8) == 0)
219 dest_file = concat (root_dir, "/lib/", fn+8, 0);
220 else
221 dest_file = concat (root_dir, "/", fn, 0);
222 return dest_file;
223}
224
40aef45e
DD
225static int
226exists (char *file)
227{
228 if (_access (file, 0) == 0)
229 return 1;
230 return 0;
231}
232
3b9077d4
DD
233
234static int num_installs, num_uninstalls;
235
236static void
237uninstall_one (char *name, int action)
238{
239 hash dirs;
240 char line[_MAX_PATH];
241
242 gzFile lst = gzopen (concat (root_dir, "/etc/setup/",
243 name, ".lst.gz", 0),
244 "rb");
245 if (lst)
246 {
247 SetWindowText (ins_pkgname, name);
248 SetWindowText (ins_action, "Uninstalling...");
249 if (action == ACTION_UPGRADE)
250 log (0, "Uninstalling old %s", name);
251 else
252 log (0, "Uninstalling %s", name);
253
254 while (gzgets (lst, line, sizeof (line)))
255 {
256 if (line[strlen(line)-1] == '\n')
257 line[strlen(line)-1] = 0;
258
259 dirs.add_subdirs (line);
260
261 char *d = map_filename (line);
262 DWORD dw = GetFileAttributes (d);
263 if (dw != 0xffffffff && !(dw & FILE_ATTRIBUTE_DIRECTORY))
264 {
265 log (LOG_BABBLE, "unlink %s", d);
266 DeleteFile (d);
267 }
268 }
269 gzclose (lst);
270
271 remove (concat (root_dir, "/etc/setup/", name, ".lst.gz", 0));
272
273 dirs.reverse_sort ();
274 char *subdir = 0;
275 while ((subdir = dirs.enumerate (subdir)) != 0)
276 {
277 char *d = map_filename (subdir);
278 if (RemoveDirectory (d))
279 log (LOG_BABBLE, "rmdir %s", d);
280 }
281 num_uninstalls ++;
282 }
283}
284
285
286static int
287install_one (char *name, char *file, int file_size, int action)
288{
289 int errors = 0;
290 char *local = file, *cp, *fn, *base;
291
292 base = local;
293 for (cp=local; *cp; cp++)
294 if (*cp == '/' || *cp == '\\' || *cp == ':')
295 base = cp+1;
296 SetWindowText (ins_pkgname, base);
297
298 if (!exists (local) && exists (base))
299 local = base;
300 if (!exists (local))
301 {
302 note (IDS_ERR_OPEN_READ, local, "No such file");
303 return 1;
304 }
305
306 gzFile lst = gzopen (concat (root_dir, "/etc/setup/",
307 name, ".lst.gz", 0),
308 "wb9");
309
310 package_bytes = file_size;
311
312 switch (action)
313 {
314 case ACTION_NEW:
315 SetWindowText (ins_action, "Installing...");
316 break;
317 case ACTION_UPGRADE:
318 SetWindowText (ins_action, "Upgrading...");
319 break;
320 }
321
322 log (0, "Installing %s", local);
323 tar_open (local);
324 while (fn = tar_next_file ())
325 {
326 char *dest_file;
327
328 if (lst)
329 gzprintf (lst, "%s\n", fn);
330
331 dest_file = map_filename (fn);
332
333 SetWindowText (ins_filename, dest_file);
334 log (LOG_BABBLE, "Installing file %s", dest_file);
335 if (tar_read_file (dest_file) != 0)
336 {
337 log (0, "Unable to install file %s", dest_file);
338 errors ++;
339 }
340
341 progress (tar_ftell ());
342 num_installs ++;
343 }
344 tar_close ();
345
346 total_bytes_sofar += file_size;
347 progress (0);
348
349 int df = diskfull (root_dir);
350 SendMessage (ins_diskfull, PBM_SETPOS, (WPARAM) df, 0);
351
352 if (lst)
353 gzclose (lst);
354
355 return errors;
356}
357
23c9e63c
DD
358void
359do_install (HINSTANCE h)
360{
3b9077d4 361 int i;
2a1a01e0
DD
362 int errors = 0;
363
3b9077d4
DD
364 num_installs = 0, num_uninstalls = 0;
365
50225eae 366 next_dialog = IDD_DESKTOP;
23c9e63c 367
904d24fe
DD
368 mkdir_p (1, root_dir);
369
370 for (i=0; standard_dirs[i]; i++)
371 {
372 char *p = concat (root_dir, standard_dirs[i], 0);
373 mkdir_p (1, p);
374 free (p);
375 }
376
1a18aed7
DD
377 /* Create /var/run/utmp */
378 char *utmp = concat (root_dir, "/var/run/utmp", 0);
379 FILE *ufp = fopen (utmp, "wb");
380 if (ufp)
381 fclose (ufp);
382 free (utmp);
383
23c9e63c
DD
384 dismiss_url_status_dialog ();
385
386 init_dialog ();
387
388 total_bytes = 0;
389 total_bytes_sofar = 0;
390
d07591a3
DD
391 int df = diskfull (root_dir);
392 SendMessage (ins_diskfull, PBM_SETPOS, (WPARAM) df, 0);
393
23c9e63c
DD
394 LOOP_PACKAGES
395 {
396 total_bytes += pi.install_size;
397 }
398
4a83b7b0 399 for (i=0; i<npackages; i++)
23c9e63c 400 {
4a83b7b0
DD
401 if (package[i].action == ACTION_UNINSTALL
402 || (package[i].action == ACTION_UPGRADE && pi.install))
403 {
3b9077d4
DD
404 uninstall_one (package[i].name, package[i].action);
405 uninstall_one (concat (package[i].name, "-src", 0), package[i].action);
4a83b7b0 406 }
23c9e63c 407
4a83b7b0
DD
408 if ((package[i].action == ACTION_NEW
409 || package[i].action == ACTION_UPGRADE)
410 && pi.install)
23c9e63c 411 {
3b9077d4
DD
412 int e = install_one (package[i].name, pi.install, pi.install_size, package[i].action);
413 if (package[i].srcaction == SRCACTION_YES && pi.source)
414 e += install_one (concat (package[i].name, "-src", 0), pi.source, pi.source_size,
415 package[i].action);
416 if (e)
40aef45e
DD
417 {
418 package[i].action = ACTION_ERROR;
3b9077d4 419 errors++;
40aef45e 420 }
4a83b7b0
DD
421 }
422 } // end of big package loop
423
424 ShowWindow (ins_dialog, SW_HIDE);
23c9e63c
DD
425
426 char *odbn = concat (root_dir, "/etc/setup/installed.db", 0);
427 char *ndbn = concat (root_dir, "/etc/setup/installed.db.new", 0);
428 char *sdbn = concat (root_dir, "/etc/setup/installed.db.old", 0);
429
430 mkdir_p (0, ndbn);
431
432 FILE *odb = fopen (odbn, "rt");
433 FILE *ndb = fopen (ndbn, "wb");
434
435 if (!ndb)
436 {
437 char *err = strerror (errno);
438 if (!err)
439 err = "(unknown error)";
440 fatal (IDS_ERR_OPEN_WRITE, ndb, err);
441 }
442
443 if (odb)
444 {
445 char line[1000], pkg[1000];
446 int printit;
447 while (fgets (line, 1000, odb))
448 {
449 printit = 1;
1fd6d0a2 450 sscanf (line, "%s", pkg);
4a83b7b0 451 for (i=0; i<npackages; i++)
23c9e63c
DD
452 {
453 if (strcmp (pkg, package[i].name) == 0)
4a83b7b0
DD
454 switch (package[i].action)
455 {
456 case ACTION_NEW:
457 case ACTION_UPGRADE:
458 case ACTION_UNINSTALL:
459 printit = 0;
460 break;
461 }
23c9e63c
DD
462 }
463 if (printit)
464 fputs (line, ndb);
465 }
466
467 }
4a83b7b0 468
23c9e63c
DD
469 LOOP_PACKAGES
470 {
3b9077d4
DD
471 if (package[i].srcaction == SRCACTION_YES)
472 fprintf (ndb, "%s %s %d %s %d\n", package[i].name,
473 pi.install, pi.install_size,
474 pi.source, pi.source_size);
475 else
476 fprintf (ndb, "%s %s %d\n", package[i].name,
477 pi.install, pi.install_size);
23c9e63c
DD
478 }
479
480 if (odb)
481 fclose (odb);
482 fclose (ndb);
483
484 remove (sdbn);
485 if (odb && rename (odbn, sdbn))
486 badrename (odbn, sdbn);
487
488 remove (odbn);
489 if (rename (ndbn, odbn))
490 badrename (ndbn, odbn);
491
4a83b7b0
DD
492 if (num_installs == 0 && num_uninstalls == 0)
493 {
494 exit_msg = IDS_NOTHING_INSTALLED;
495 return;
496 }
497 if (num_installs == 0)
498 {
499 exit_msg = IDS_UNINSTALL_COMPLETE;
500 return;
501 }
502
24e259bb 503 remove_mount ("/");
23c9e63c 504 remove_mount ("/usr");
24e259bb
DD
505 remove_mount ("/usr/bin");
506 remove_mount ("/usr/lib");
23c9e63c
DD
507 remove_mount ("/var");
508 remove_mount ("/lib");
509 remove_mount ("/bin");
510 remove_mount ("/etc");
511
512 int istext = (root_text == IDC_ROOT_TEXT) ? 1 : 0;
24e259bb 513 int issystem = (root_scope == IDC_ROOT_SYSTEM) ? 1 : 0;
23c9e63c 514
24e259bb
DD
515 create_mount ("/", root_dir, istext, issystem);
516 create_mount ("/usr/bin", concat (root_dir, "/bin", 0), istext, issystem);
517 create_mount ("/usr/lib", concat (root_dir, "/lib", 0), istext, issystem);
f8a6415f 518 set_cygdrive_flags (istext, issystem);
23c9e63c 519
2a1a01e0
DD
520 if (errors)
521 exit_msg = IDS_INSTALL_INCOMPLETE;
522 else
523 exit_msg = IDS_INSTALL_COMPLETE;
23c9e63c 524}
This page took 0.072676 seconds and 5 git commands to generate.