comparison netinstall/install.cc @ 448:3078fd1074e8 r21-2-39

Import from CVS: tag r21-2-39
author cvs
date Mon, 13 Aug 2007 11:38:25 +0200
parents
children a307f9a2021d
comparison
equal deleted inserted replaced
447:4fc5f13f3bd3 448:3078fd1074e8
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 #include <io.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #ifndef WIN32_NATIVE
26 #include <unistd.h>
27 #endif
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <errno.h>
31 #include <zlib.h>
32
33 #include "win32.h"
34 #include "commctrl.h"
35
36 #include "resource.h"
37 #include "ini.h"
38 #include "dialog.h"
39 #include "concat.h"
40 #include "geturl.h"
41 #include "mkdir.h"
42 #include "state.h"
43 #include "tar.h"
44 #include "diskfull.h"
45 #include "msg.h"
46 #include "regedit.h"
47 #include "reginfo.h"
48 #include "log.h"
49 #include "hash.h"
50
51 #include "port.h"
52
53 static HWND ins_dialog = 0;
54 static HWND ins_action = 0;
55 static HWND ins_pkgname = 0;
56 static HWND ins_filename = 0;
57 static HWND ins_pprogress = 0;
58 static HWND ins_iprogress = 0;
59 static HWND ins_diskfull = 0;
60 static HANDLE init_event;
61
62 static int total_bytes = 0;
63 static int total_bytes_sofar = 0;
64 static int package_bytes = 0;
65
66 static BOOL
67 dialog_cmd (HWND h, int id, HWND hwndctl, UINT code)
68 {
69 switch (id)
70 {
71 case IDCANCEL:
72 exit_setup (1);
73 }
74 return FALSE;
75 }
76
77 static BOOL CALLBACK
78 dialog_proc (HWND h, UINT message, WPARAM wParam, LPARAM lParam)
79 {
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 DWORD WINAPI
99 dialog (void *)
100 {
101 MSG m;
102 HWND new_dialog = CreateDialog (hinstance, MAKEINTRESOURCE (IDD_INSTATUS),
103 0, dialog_proc);
104 if (new_dialog == 0)
105 fatal ("create dialog");
106 ShowWindow (new_dialog, SW_SHOWNORMAL);
107 UpdateWindow (new_dialog);
108 while (GetMessage (&m, 0, 0, 0) > 0) {
109 TranslateMessage (&m);
110 DispatchMessage (&m);
111 }
112 return FALSE;
113 }
114
115 static void
116 init_dialog ()
117 {
118 if (ins_dialog == 0)
119 {
120 DWORD tid;
121 HANDLE thread;
122 init_event = CreateEvent (0, 0, 0, 0);
123 thread = CreateThread (0, 0, dialog, 0, 0, &tid);
124 WaitForSingleObject (init_event, 10000);
125 CloseHandle (init_event);
126 SendMessage (ins_pprogress, PBM_SETRANGE, 0, MAKELPARAM (0, 100));
127 SendMessage (ins_iprogress, PBM_SETRANGE, 0, MAKELPARAM (0, 100));
128 SendMessage (ins_diskfull, PBM_SETRANGE, 0, MAKELPARAM (0, 100));
129 }
130
131 SetWindowText (ins_pkgname, "");
132 SetWindowText (ins_filename, "");
133 SendMessage (ins_pprogress, PBM_SETPOS, (WPARAM) 0, 0);
134 SendMessage (ins_iprogress, PBM_SETPOS, (WPARAM) 0, 0);
135 SendMessage (ins_diskfull, PBM_SETPOS, (WPARAM) 0, 0);
136 ShowWindow (ins_dialog, SW_SHOWNORMAL);
137 SetForegroundWindow (ins_dialog);
138 }
139
140 static void
141 progress (int bytes)
142 {
143 int perc;
144
145 if (package_bytes > 100)
146 {
147 perc = bytes / (package_bytes / 100);
148 SendMessage (ins_pprogress, PBM_SETPOS, (WPARAM) perc, 0);
149 }
150
151 if (total_bytes > 100)
152 {
153 perc = (total_bytes_sofar + bytes) / (total_bytes / 100);
154 SendMessage (ins_iprogress, PBM_SETPOS, (WPARAM) perc, 0);
155 }
156 }
157
158 static void
159 badrename (char *o, char *n)
160 {
161 char *err = strerror (errno);
162 if (!err)
163 err = "(unknown error)";
164 note (IDS_ERR_RENAME, o, n, err);
165 }
166
167 static char *standard_dirs[] = {
168 0
169 };
170
171 void
172 hash::add_subdirs (char *path)
173 {
174 char *nonp, *pp;
175 for (nonp = path; *nonp == '\\' || *nonp == '/'; nonp++);
176 for (pp = path + strlen(path) - 1; pp>nonp; pp--)
177 if (*pp == '/' || *pp == '\\')
178 {
179 int i, s=0;
180 char c = *pp;
181 *pp = 0;
182 for (i=0; standard_dirs[i]; i++)
183 if (strcmp (standard_dirs[i]+1, path) == 0)
184 {
185 s = 1;
186 break;
187 }
188 if (s == 0)
189 add (path);
190 *pp = c;
191 }
192 }
193
194 char *
195 map_filename (char *fn, int type)
196 {
197 char *dest_file;
198 while (*fn == '/' || *fn == '\\')
199 fn++;
200 if (type == TY_GENERIC)
201 dest_file = concat (root_dir, XEMACS_PACKAGE_DIR, fn, 0);
202 else // TY_CYGWIN | TY_NATIVE
203 dest_file = concat (root_dir, "/", fn, 0);
204 return dest_file;
205 }
206
207 static int
208 exists (char *file)
209 {
210 if (_access (file, 0) == 0)
211 return 1;
212 return 0;
213 }
214
215
216 static int num_installs, num_uninstalls;
217
218 static void
219 uninstall_one (char *name, int action, int type)
220 {
221 hash dirs;
222 char line[_MAX_PATH];
223 char* fname = (type == TY_GENERIC ?
224 concat (root_dir, XEMACS_PACKAGE_DIR, "pkginfo/MANIFEST.",
225 name, 0) :
226 concat (root_dir, XEMACS_SETUP_DIR, "MANIFEST.", name, 0));
227
228 FILE* lst = fopen (fname, "rb");
229
230 if (lst)
231 {
232 SetWindowText (ins_pkgname, name);
233 SetWindowText (ins_action, "Uninstalling...");
234 if (action == ACTION_UPGRADE)
235 log (0, "Uninstalling old %s", name);
236 else
237 log (0, "Uninstalling %s", name);
238
239 while (fgets (line, sizeof (line), lst))
240 {
241 if (line[strlen(line)-1] == '\n')
242 line[strlen(line)-1] = 0;
243
244 dirs.add_subdirs (line);
245
246 char *d = map_filename (line, type);
247 DWORD dw = GetFileAttributes (d);
248 if (dw != 0xffffffff && !(dw & FILE_ATTRIBUTE_DIRECTORY))
249 {
250 log (LOG_BABBLE, "unlink %s", d);
251 DeleteFile (d);
252 }
253 }
254 fclose (lst);
255
256 remove (fname);
257
258 dirs.reverse_sort ();
259 char *subdir = 0;
260 while ((subdir = dirs.enumerate (subdir)) != 0)
261 {
262 char *d = map_filename (subdir, type);
263 if (RemoveDirectory (d))
264 log (LOG_BABBLE, "rmdir %s", d);
265 }
266 num_uninstalls ++;
267 }
268 }
269
270
271 static int
272 install_one (char *name, char *file, int file_size, int action, int type)
273 {
274 int errors = 0;
275 char *local = file, *cp, *fn, *base;
276
277 base = local;
278 for (cp=local; *cp; cp++)
279 if (*cp == '/' || *cp == '\\' || *cp == ':')
280 base = cp+1;
281 SetWindowText (ins_pkgname, base);
282
283 if (!exists (local) && exists (base))
284 local = base;
285 if (!exists (local))
286 {
287 note (IDS_ERR_OPEN_READ, local, "No such file");
288 return 1;
289 }
290
291 char* fname = (type == TY_GENERIC ?
292 concat (root_dir, XEMACS_PACKAGE_DIR, "pkginfo/MANIFEST.",
293 name, 0) :
294 concat (root_dir, XEMACS_SETUP_DIR, "MANIFEST.", name, 0));
295
296 FILE* lst = fopen (fname, "wb");
297
298 package_bytes = file_size;
299
300 switch (action)
301 {
302 case ACTION_NEW:
303 SetWindowText (ins_action, "Installing...");
304 break;
305 case ACTION_UPGRADE:
306 SetWindowText (ins_action, "Upgrading...");
307 break;
308 }
309
310 log (0, "Installing %s", local);
311 tar_open (local);
312 while ((fn = tar_next_file ()))
313 {
314 char *dest_file;
315
316 if (lst)
317 fprintf (lst, "%s\n", fn);
318
319 dest_file = map_filename (fn, type);
320
321 SetWindowText (ins_filename, dest_file);
322 log (LOG_BABBLE, "Installing file %s", dest_file);
323 if (tar_read_file (dest_file) != 0)
324 {
325 log (0, "Unable to install file %s", dest_file);
326 errors ++;
327 }
328
329 progress (tar_ftell ());
330 num_installs ++;
331 }
332 tar_close ();
333
334 total_bytes_sofar += file_size;
335 progress (0);
336
337 int df = diskfull (root_dir);
338 SendMessage (ins_diskfull, PBM_SETPOS, (WPARAM) df, 0);
339
340 if (lst)
341 fclose (lst);
342
343 return errors;
344 }
345
346 void
347 do_install (HINSTANCE h)
348 {
349 int i;
350 int errors = 0;
351
352 num_installs = 0, num_uninstalls = 0;
353
354 next_dialog = IDD_DESKTOP;
355
356 mkdir_p (1, root_dir);
357
358 for (i=0; standard_dirs[i]; i++)
359 {
360 char *p = concat (root_dir, standard_dirs[i], 0);
361 mkdir_p (1, p);
362 free (p);
363 }
364
365 dismiss_url_status_dialog ();
366
367 init_dialog ();
368
369 total_bytes = 0;
370 total_bytes_sofar = 0;
371
372 int df = diskfull (root_dir);
373 SendMessage (ins_diskfull, PBM_SETPOS, (WPARAM) df, 0);
374
375 LOOP_PACKAGES
376 {
377 total_bytes += pi.install_size;
378 }
379
380 for (i=0; i<npackages; i++)
381 {
382 if (package[i].action == ACTION_UNINSTALL
383 || (package[i].action == ACTION_UPGRADE && pi.install))
384 {
385 uninstall_one (package[i].name, package[i].action,
386 package[i].type);
387 uninstall_one (concat (package[i].name, "-src", 0), package[i].action,
388 package[i].type);
389 }
390
391 if ((package[i].action == ACTION_NEW
392 || package[i].action == ACTION_UPGRADE)
393 && pi.install)
394 {
395 int e = install_one (package[i].name, pi.install, pi.install_size, package[i].action,
396 package[i].type);
397 if (package[i].srcaction == SRCACTION_YES && pi.source)
398 e += install_one (concat (package[i].name, "-src", 0), pi.source, pi.source_size,
399 package[i].action, package[i].type);
400 if (e)
401 {
402 package[i].action = ACTION_ERROR;
403 errors++;
404 }
405 }
406 } // end of big package loop
407
408 ShowWindow (ins_dialog, SW_HIDE);
409
410 char *odbn = concat (root_dir, XEMACS_SETUP_DIR, "installed.db", 0);
411 char *ndbn = concat (root_dir, XEMACS_SETUP_DIR, "installed.db.new", 0);
412 char *sdbn = concat (root_dir, XEMACS_SETUP_DIR, "installed.db.old", 0);
413
414 mkdir_p (0, ndbn);
415
416 FILE *odb = fopen (odbn, "rt");
417 FILE *ndb = fopen (ndbn, "wb");
418
419 if (!ndb)
420 {
421 char *err = strerror (errno);
422 if (!err)
423 err = "(unknown error)";
424 fatal (IDS_ERR_OPEN_WRITE, ndb, err);
425 }
426
427 if (odb)
428 {
429 char line[1000], pkg[1000];
430 int printit;
431 while (fgets (line, 1000, odb))
432 {
433 printit = 1;
434 sscanf (line, "%s", pkg);
435 for (i=0; i<npackages; i++)
436 {
437 if (strcmp (pkg, package[i].name) == 0)
438 switch (package[i].action)
439 {
440 case ACTION_NEW:
441 case ACTION_UPGRADE:
442 case ACTION_UNINSTALL:
443 printit = 0;
444 break;
445 }
446 }
447 if (printit)
448 fputs (line, ndb);
449 }
450
451 }
452
453 LOOP_PACKAGES
454 {
455 if (package[i].srcaction == SRCACTION_YES)
456 fprintf (ndb, "%s %s %d %s %d\n", package[i].name,
457 pi.install, pi.install_size,
458 pi.source, pi.source_size);
459 else
460 fprintf (ndb, "%s %s %d\n", package[i].name,
461 pi.install, pi.install_size);
462 }
463
464 if (odb)
465 fclose (odb);
466 fclose (ndb);
467
468 remove (sdbn);
469 if (odb && rename (odbn, sdbn))
470 badrename (odbn, sdbn);
471
472 remove (odbn);
473 if (rename (ndbn, odbn))
474 badrename (ndbn, odbn);
475
476 if (num_installs == 0 && num_uninstalls == 0)
477 {
478 exit_msg = IDS_NOTHING_INSTALLED;
479 return;
480 }
481 if (num_installs == 0)
482 {
483 exit_msg = IDS_UNINSTALL_COMPLETE;
484 return;
485 }
486
487 if (errors)
488 exit_msg = IDS_INSTALL_INCOMPLETE;
489 else
490 exit_msg = IDS_INSTALL_COMPLETE;
491 }