]> cygwin.com Git - cygwin-apps/setup.git/blame - install.cc
* desktop.cc: added logic to handle to the new dialog and to
[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 }
157
158 int df = diskfull (root_dir);
159 SendMessage (ins_diskfull, PBM_SETPOS, (WPARAM) df, 0);
160}
161
162static void
163badrename (char *o, char *n)
164{
165 char buf[1000];
166 char *err = strerror (errno);
167 if (!err)
168 err = "(unknown error)";
169 note (IDS_ERR_RENAME, o, n, err);
170}
171
904d24fe 172static char *standard_dirs[] = {
1a18aed7 173 "/bin",
904d24fe 174 "/etc",
1a18aed7 175 "/lib",
904d24fe 176 "/tmp",
4a83b7b0 177 "/usr",
1a18aed7
DD
178 "/usr/bin",
179 "/usr/lib",
4a83b7b0 180 "/usr/local",
1a18aed7
DD
181 "/usr/local/bin",
182 "/usr/local/etc",
183 "/usr/local/lib",
904d24fe 184 "/usr/tmp",
1a18aed7 185 "/var/run",
904d24fe
DD
186 "/var/tmp",
187 0
188};
189
4a83b7b0
DD
190void
191hash::add_subdirs (char *path)
192{
193 char *nonp, *pp;
194 for (nonp = path; *nonp == '\\' || *nonp == '/'; nonp++);
195 for (pp = path + strlen(path) - 1; pp>nonp; pp--)
196 if (*pp == '/' || *pp == '\\')
197 {
198 int i, s=0;
199 char c = *pp;
200 *pp = 0;
201 for (i=0; standard_dirs[i]; i++)
202 if (strcmp (standard_dirs[i]+1, path) == 0)
203 {
204 s = 1;
205 break;
206 }
207 if (s == 0)
208 add (path);
209 *pp = c;
210 }
211}
212
213char *
214map_filename (char *fn)
215{
216 char *dest_file;
217 while (*fn == '/' || *fn == '\\')
218 fn++;
219 if (strncmp (fn, "usr/bin/", 8) == 0)
220 dest_file = concat (root_dir, "/bin/", fn+8, 0);
221 else if (strncmp (fn, "usr/lib/", 8) == 0)
222 dest_file = concat (root_dir, "/lib/", fn+8, 0);
223 else
224 dest_file = concat (root_dir, "/", fn, 0);
225 return dest_file;
226}
227
23c9e63c
DD
228#define pi (package[i].info[package[i].trust])
229
230#define LOOP_PACKAGES \
231 for (i=0; i<npackages; i++) \
b11b49f3
DD
232 if ((package[i].action == ACTION_NEW \
233 || package[i].action == ACTION_UPGRADE) \
234 && pi.install)
23c9e63c
DD
235
236void
237do_install (HINSTANCE h)
238{
4a83b7b0 239 int i, num_installs = 0, num_uninstalls = 0;
50225eae 240 next_dialog = IDD_DESKTOP;
23c9e63c 241
904d24fe
DD
242 mkdir_p (1, root_dir);
243
244 for (i=0; standard_dirs[i]; i++)
245 {
246 char *p = concat (root_dir, standard_dirs[i], 0);
247 mkdir_p (1, p);
248 free (p);
249 }
250
1a18aed7
DD
251 /* Create /var/run/utmp */
252 char *utmp = concat (root_dir, "/var/run/utmp", 0);
253 FILE *ufp = fopen (utmp, "wb");
254 if (ufp)
255 fclose (ufp);
256 free (utmp);
257
23c9e63c
DD
258 dismiss_url_status_dialog ();
259
260 init_dialog ();
261
262 total_bytes = 0;
263 total_bytes_sofar = 0;
264
265 LOOP_PACKAGES
266 {
267 total_bytes += pi.install_size;
268 }
269
4a83b7b0 270 for (i=0; i<npackages; i++)
23c9e63c 271 {
4a83b7b0
DD
272 if (package[i].action == ACTION_UNINSTALL
273 || (package[i].action == ACTION_UPGRADE && pi.install))
274 {
275 hash dirs;
276 char line[_MAX_PATH];
23c9e63c 277
4a83b7b0
DD
278 gzFile lst = gzopen (concat (root_dir, "/etc/setup/",
279 package[i].name, ".lst.gz", 0),
280 "rb");
281 if (lst)
282 {
283 SetWindowText (ins_pkgname, package[i].name);
284 SetWindowText (ins_action, "Uninstalling...");
285 log (0, "Uninstalling %s", package[i].name);
23c9e63c 286
4a83b7b0
DD
287 while (gzgets (lst, line, sizeof (line)))
288 {
289 if (line[strlen(line)-1] == '\n')
290 line[strlen(line)-1] = 0;
291
292 dirs.add_subdirs (line);
293
294 char *d = map_filename (line);
295 DWORD dw = GetFileAttributes (d);
296 if (dw != 0xffffffff && !(dw & FILE_ATTRIBUTE_DIRECTORY))
297 {
298 log (LOG_BABBLE, "unlink %s", d);
299 DeleteFile (d);
300 }
301 }
302 gzclose (lst);
23c9e63c 303
4a83b7b0
DD
304 dirs.reverse_sort ();
305 char *subdir = 0;
306 while ((subdir = dirs.enumerate (subdir)) != 0)
307 {
308 char *d = map_filename (subdir);
309 if (RemoveDirectory (d))
310 log (LOG_BABBLE, "rmdir %s", d);
311 }
312 num_uninstalls ++;
313 }
314 }
23c9e63c 315
4a83b7b0
DD
316 if ((package[i].action == ACTION_NEW
317 || package[i].action == ACTION_UPGRADE)
318 && pi.install)
23c9e63c 319 {
4a83b7b0 320 char *local = pi.install, *cp, *fn, *base;
23c9e63c 321
4a83b7b0
DD
322 base = local;
323 for (cp=pi.install; *cp; cp++)
324 if (*cp == '/' || *cp == '\\' || *cp == ':')
325 base = cp+1;
326 SetWindowText (ins_pkgname, base);
23c9e63c 327
4a83b7b0
DD
328 gzFile lst = gzopen (concat (root_dir, "/etc/setup/",
329 package[i].name, ".lst.gz", 0),
330 "wb9");
23c9e63c 331
4a83b7b0 332 package_bytes = pi.install_size;
23c9e63c 333
4a83b7b0
DD
334 switch (package[i].action)
335 {
336 case ACTION_NEW:
337 SetWindowText (ins_action, "Installing...");
338 break;
339 case ACTION_UPGRADE:
340 SetWindowText (ins_action, "Upgrading...");
341 break;
342 }
23c9e63c 343
4a83b7b0
DD
344 log (0, "Installing %s", local);
345 tar_open (local);
346 while (fn = tar_next_file ())
347 {
348 char *dest_file;
23c9e63c 349
4a83b7b0
DD
350 if (lst)
351 gzprintf (lst, "%s\n", fn);
23c9e63c 352
4a83b7b0 353 dest_file = map_filename (fn);
23c9e63c 354
4a83b7b0
DD
355 SetWindowText (ins_filename, dest_file);
356 log (LOG_BABBLE, "Installing file %s", dest_file);
357 tar_read_file (dest_file);
23c9e63c 358
4a83b7b0
DD
359 progress (tar_ftell ());
360 num_installs ++;
361 }
362 tar_close ();
363
364 total_bytes_sofar += pi.install_size;
365 progress (0);
366
367 if (lst)
368 gzclose (lst);
369 }
370 } // end of big package loop
371
372 ShowWindow (ins_dialog, SW_HIDE);
23c9e63c
DD
373
374 char *odbn = concat (root_dir, "/etc/setup/installed.db", 0);
375 char *ndbn = concat (root_dir, "/etc/setup/installed.db.new", 0);
376 char *sdbn = concat (root_dir, "/etc/setup/installed.db.old", 0);
377
378 mkdir_p (0, ndbn);
379
380 FILE *odb = fopen (odbn, "rt");
381 FILE *ndb = fopen (ndbn, "wb");
382
383 if (!ndb)
384 {
385 char *err = strerror (errno);
386 if (!err)
387 err = "(unknown error)";
388 fatal (IDS_ERR_OPEN_WRITE, ndb, err);
389 }
390
391 if (odb)
392 {
393 char line[1000], pkg[1000];
394 int printit;
395 while (fgets (line, 1000, odb))
396 {
397 printit = 1;
1fd6d0a2 398 sscanf (line, "%s", pkg);
4a83b7b0 399 for (i=0; i<npackages; i++)
23c9e63c
DD
400 {
401 if (strcmp (pkg, package[i].name) == 0)
4a83b7b0
DD
402 switch (package[i].action)
403 {
404 case ACTION_NEW:
405 case ACTION_UPGRADE:
406 case ACTION_UNINSTALL:
407 printit = 0;
408 break;
409 }
23c9e63c
DD
410 }
411 if (printit)
412 fputs (line, ndb);
413 }
414
415 }
4a83b7b0 416
23c9e63c
DD
417 LOOP_PACKAGES
418 {
419 fprintf (ndb, "%s %s %d\n", package[i].name,
420 pi.install, pi.install_size);
421 }
422
423 if (odb)
424 fclose (odb);
425 fclose (ndb);
426
427 remove (sdbn);
428 if (odb && rename (odbn, sdbn))
429 badrename (odbn, sdbn);
430
431 remove (odbn);
432 if (rename (ndbn, odbn))
433 badrename (ndbn, odbn);
434
4a83b7b0
DD
435 if (num_installs == 0 && num_uninstalls == 0)
436 {
437 exit_msg = IDS_NOTHING_INSTALLED;
438 return;
439 }
440 if (num_installs == 0)
441 {
442 exit_msg = IDS_UNINSTALL_COMPLETE;
443 return;
444 }
445
24e259bb 446 remove_mount ("/");
23c9e63c 447 remove_mount ("/usr");
24e259bb
DD
448 remove_mount ("/usr/bin");
449 remove_mount ("/usr/lib");
23c9e63c
DD
450 remove_mount ("/var");
451 remove_mount ("/lib");
452 remove_mount ("/bin");
453 remove_mount ("/etc");
454
455 int istext = (root_text == IDC_ROOT_TEXT) ? 1 : 0;
24e259bb 456 int issystem = (root_scope == IDC_ROOT_SYSTEM) ? 1 : 0;
23c9e63c 457
24e259bb
DD
458 create_mount ("/", root_dir, istext, issystem);
459 create_mount ("/usr/bin", concat (root_dir, "/bin", 0), istext, issystem);
460 create_mount ("/usr/lib", concat (root_dir, "/lib", 0), istext, issystem);
23c9e63c 461
f57c332f 462 exit_msg = IDS_INSTALL_COMPLETE;
23c9e63c 463}
This page took 0.064783 seconds and 5 git commands to generate.