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