]> cygwin.com Git - cygwin-apps/setup.git/blob - install.cc
* ini.h: add source actions
[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 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
22 static char *cvsid = "\n%%% $Id$\n";
23
24 #include "win32.h"
25 #include "commctrl.h"
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <unistd.h>
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"
46 #include "log.h"
47 #include "hash.h"
48
49 #include "port.h"
50
51 static HWND ins_dialog = 0;
52 static HWND ins_action = 0;
53 static HWND ins_pkgname = 0;
54 static HWND ins_filename = 0;
55 static HWND ins_pprogress = 0;
56 static HWND ins_iprogress = 0;
57 static HWND ins_diskfull = 0;
58 static HANDLE init_event;
59
60 static int total_bytes = 0;
61 static int total_bytes_sofar = 0;
62 static int package_bytes = 0;
63
64 static BOOL
65 dialog_cmd (HWND h, int id, HWND hwndctl, UINT code)
66 {
67 switch (id)
68 {
69 case IDCANCEL:
70 exit_setup (1);
71 }
72 }
73
74 static BOOL CALLBACK
75 dialog_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;
83 ins_action = GetDlgItem (h, IDC_INS_ACTION);
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:
92 return HANDLE_WM_COMMAND (h, wParam, lParam, dialog_cmd);
93 }
94 return FALSE;
95 }
96
97 static WINAPI DWORD
98 dialog (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
114 static DWORD start_tics;
115
116 static void
117 init_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
141 static void
142 progress (int bytes)
143 {
144 int perc;
145
146 if (package_bytes > 100)
147 {
148 perc = bytes / (package_bytes / 100);
149 SendMessage (ins_pprogress, PBM_SETPOS, (WPARAM) perc, 0);
150 }
151
152 if (total_bytes > 100)
153 {
154 perc = (total_bytes_sofar + bytes) / (total_bytes / 100);
155 SendMessage (ins_iprogress, PBM_SETPOS, (WPARAM) perc, 0);
156 }
157 }
158
159 static void
160 badrename (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
169 static char *standard_dirs[] = {
170 "/bin",
171 "/etc",
172 "/lib",
173 "/tmp",
174 "/usr",
175 "/usr/bin",
176 "/usr/lib",
177 "/usr/local",
178 "/usr/local/bin",
179 "/usr/local/etc",
180 "/usr/local/lib",
181 "/usr/tmp",
182 "/var/run",
183 "/var/tmp",
184 0
185 };
186
187 void
188 hash::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
210 char *
211 map_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
225 #define pi (package[i].info[package[i].trust])
226
227 #define LOOP_PACKAGES \
228 for (i=0; i<npackages; i++) \
229 if ((package[i].action == ACTION_NEW \
230 || package[i].action == ACTION_UPGRADE) \
231 && pi.install)
232
233 static int
234 exists (char *file)
235 {
236 if (_access (file, 0) == 0)
237 return 1;
238 return 0;
239 }
240
241
242 static int num_installs, num_uninstalls;
243
244 static void
245 uninstall_one (char *name, int action)
246 {
247 hash dirs;
248 char line[_MAX_PATH];
249
250 gzFile lst = gzopen (concat (root_dir, "/etc/setup/",
251 name, ".lst.gz", 0),
252 "rb");
253 if (lst)
254 {
255 SetWindowText (ins_pkgname, name);
256 SetWindowText (ins_action, "Uninstalling...");
257 if (action == ACTION_UPGRADE)
258 log (0, "Uninstalling old %s", name);
259 else
260 log (0, "Uninstalling %s", name);
261
262 while (gzgets (lst, line, sizeof (line)))
263 {
264 if (line[strlen(line)-1] == '\n')
265 line[strlen(line)-1] = 0;
266
267 dirs.add_subdirs (line);
268
269 char *d = map_filename (line);
270 DWORD dw = GetFileAttributes (d);
271 if (dw != 0xffffffff && !(dw & FILE_ATTRIBUTE_DIRECTORY))
272 {
273 log (LOG_BABBLE, "unlink %s", d);
274 DeleteFile (d);
275 }
276 }
277 gzclose (lst);
278
279 remove (concat (root_dir, "/etc/setup/", name, ".lst.gz", 0));
280
281 dirs.reverse_sort ();
282 char *subdir = 0;
283 while ((subdir = dirs.enumerate (subdir)) != 0)
284 {
285 char *d = map_filename (subdir);
286 if (RemoveDirectory (d))
287 log (LOG_BABBLE, "rmdir %s", d);
288 }
289 num_uninstalls ++;
290 }
291 }
292
293
294 static int
295 install_one (char *name, char *file, int file_size, int action)
296 {
297 int errors = 0;
298 char *local = file, *cp, *fn, *base;
299
300 base = local;
301 for (cp=local; *cp; cp++)
302 if (*cp == '/' || *cp == '\\' || *cp == ':')
303 base = cp+1;
304 SetWindowText (ins_pkgname, base);
305
306 if (!exists (local) && exists (base))
307 local = base;
308 if (!exists (local))
309 {
310 note (IDS_ERR_OPEN_READ, local, "No such file");
311 return 1;
312 }
313
314 gzFile lst = gzopen (concat (root_dir, "/etc/setup/",
315 name, ".lst.gz", 0),
316 "wb9");
317
318 package_bytes = file_size;
319
320 switch (action)
321 {
322 case ACTION_NEW:
323 SetWindowText (ins_action, "Installing...");
324 break;
325 case ACTION_UPGRADE:
326 SetWindowText (ins_action, "Upgrading...");
327 break;
328 }
329
330 log (0, "Installing %s", local);
331 tar_open (local);
332 while (fn = tar_next_file ())
333 {
334 char *dest_file;
335
336 if (lst)
337 gzprintf (lst, "%s\n", fn);
338
339 dest_file = map_filename (fn);
340
341 SetWindowText (ins_filename, dest_file);
342 log (LOG_BABBLE, "Installing file %s", dest_file);
343 if (tar_read_file (dest_file) != 0)
344 {
345 log (0, "Unable to install file %s", dest_file);
346 errors ++;
347 }
348
349 progress (tar_ftell ());
350 num_installs ++;
351 }
352 tar_close ();
353
354 total_bytes_sofar += file_size;
355 progress (0);
356
357 int df = diskfull (root_dir);
358 SendMessage (ins_diskfull, PBM_SETPOS, (WPARAM) df, 0);
359
360 if (lst)
361 gzclose (lst);
362
363 return errors;
364 }
365
366 void
367 do_install (HINSTANCE h)
368 {
369 int i;
370 int errors = 0;
371
372 num_installs = 0, num_uninstalls = 0;
373
374 next_dialog = IDD_DESKTOP;
375
376 mkdir_p (1, root_dir);
377
378 for (i=0; standard_dirs[i]; i++)
379 {
380 char *p = concat (root_dir, standard_dirs[i], 0);
381 mkdir_p (1, p);
382 free (p);
383 }
384
385 /* Create /var/run/utmp */
386 char *utmp = concat (root_dir, "/var/run/utmp", 0);
387 FILE *ufp = fopen (utmp, "wb");
388 if (ufp)
389 fclose (ufp);
390 free (utmp);
391
392 dismiss_url_status_dialog ();
393
394 init_dialog ();
395
396 total_bytes = 0;
397 total_bytes_sofar = 0;
398
399 int df = diskfull (root_dir);
400 SendMessage (ins_diskfull, PBM_SETPOS, (WPARAM) df, 0);
401
402 LOOP_PACKAGES
403 {
404 total_bytes += pi.install_size;
405 }
406
407 for (i=0; i<npackages; i++)
408 {
409 if (package[i].action == ACTION_UNINSTALL
410 || (package[i].action == ACTION_UPGRADE && pi.install))
411 {
412 uninstall_one (package[i].name, package[i].action);
413 uninstall_one (concat (package[i].name, "-src", 0), package[i].action);
414 }
415
416 if ((package[i].action == ACTION_NEW
417 || package[i].action == ACTION_UPGRADE)
418 && pi.install)
419 {
420 int e = install_one (package[i].name, pi.install, pi.install_size, package[i].action);
421 if (package[i].srcaction == SRCACTION_YES && pi.source)
422 e += install_one (concat (package[i].name, "-src", 0), pi.source, pi.source_size,
423 package[i].action);
424 if (e)
425 {
426 package[i].action = ACTION_ERROR;
427 errors++;
428 }
429 }
430 } // end of big package loop
431
432 ShowWindow (ins_dialog, SW_HIDE);
433
434 char *odbn = concat (root_dir, "/etc/setup/installed.db", 0);
435 char *ndbn = concat (root_dir, "/etc/setup/installed.db.new", 0);
436 char *sdbn = concat (root_dir, "/etc/setup/installed.db.old", 0);
437
438 mkdir_p (0, ndbn);
439
440 FILE *odb = fopen (odbn, "rt");
441 FILE *ndb = fopen (ndbn, "wb");
442
443 if (!ndb)
444 {
445 char *err = strerror (errno);
446 if (!err)
447 err = "(unknown error)";
448 fatal (IDS_ERR_OPEN_WRITE, ndb, err);
449 }
450
451 if (odb)
452 {
453 char line[1000], pkg[1000];
454 int printit;
455 while (fgets (line, 1000, odb))
456 {
457 printit = 1;
458 sscanf (line, "%s", pkg);
459 for (i=0; i<npackages; i++)
460 {
461 if (strcmp (pkg, package[i].name) == 0)
462 switch (package[i].action)
463 {
464 case ACTION_NEW:
465 case ACTION_UPGRADE:
466 case ACTION_UNINSTALL:
467 printit = 0;
468 break;
469 }
470 }
471 if (printit)
472 fputs (line, ndb);
473 }
474
475 }
476
477 LOOP_PACKAGES
478 {
479 if (package[i].srcaction == SRCACTION_YES)
480 fprintf (ndb, "%s %s %d %s %d\n", package[i].name,
481 pi.install, pi.install_size,
482 pi.source, pi.source_size);
483 else
484 fprintf (ndb, "%s %s %d\n", package[i].name,
485 pi.install, pi.install_size);
486 }
487
488 if (odb)
489 fclose (odb);
490 fclose (ndb);
491
492 remove (sdbn);
493 if (odb && rename (odbn, sdbn))
494 badrename (odbn, sdbn);
495
496 remove (odbn);
497 if (rename (ndbn, odbn))
498 badrename (ndbn, odbn);
499
500 if (num_installs == 0 && num_uninstalls == 0)
501 {
502 exit_msg = IDS_NOTHING_INSTALLED;
503 return;
504 }
505 if (num_installs == 0)
506 {
507 exit_msg = IDS_UNINSTALL_COMPLETE;
508 return;
509 }
510
511 remove_mount ("/");
512 remove_mount ("/usr");
513 remove_mount ("/usr/bin");
514 remove_mount ("/usr/lib");
515 remove_mount ("/var");
516 remove_mount ("/lib");
517 remove_mount ("/bin");
518 remove_mount ("/etc");
519
520 int istext = (root_text == IDC_ROOT_TEXT) ? 1 : 0;
521 int issystem = (root_scope == IDC_ROOT_SYSTEM) ? 1 : 0;
522
523 create_mount ("/", root_dir, istext, issystem);
524 create_mount ("/usr/bin", concat (root_dir, "/bin", 0), istext, issystem);
525 create_mount ("/usr/lib", concat (root_dir, "/lib", 0), istext, issystem);
526
527 if (errors)
528 exit_msg = IDS_INSTALL_INCOMPLETE;
529 else
530 exit_msg = IDS_INSTALL_COMPLETE;
531 }
This page took 0.060464 seconds and 6 git commands to generate.