Mercurial > hg > xemacs-beta
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 } |