Initial revision
[chise/xemacs-chise.git] / netinstall / uninstall.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 #include <io.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <ctype.h>
26 #ifndef WIN32_NATIVE
27 #include <unistd.h>
28 #endif
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <errno.h>
32 #include <zlib.h>
33
34 #include "win32.h"
35 #include "commctrl.h"
36
37 #include "resource.h"
38 #include "ini.h"
39 #include "dialog.h"
40 #include "concat.h"
41 #include "geturl.h"
42 #include "mkdir.h"
43 #include "state.h"
44 #include "tar.h"
45 #include "diskfull.h"
46 #include "msg.h"
47 #include "regedit.h"
48 #include "reginfo.h"
49 #include "log.h"
50 #include "hash.h"
51
52 #include "port.h"
53
54 #define XM_DONE (WM_USER + 101)
55
56 static HWND unins_dialog = 0;
57 static HWND unins_action = 0;
58 static HWND unins_pkgname = 0;
59 static HWND unins_filename = 0;
60 static HWND unins_pprogress = 0;
61 static HWND unins_iprogress = 0;
62 static HWND unins_diskfull = 0;
63 static HANDLE init_event;
64
65 static int package_bytes = 0;
66 static int uninstall_started = 0;
67
68 extern char * map_filename (char *fn, int type);
69 void remove_desktop_setup ();
70 static void start_uninstall ();
71 extern char* find_xemacs_exe_name();
72
73 char *
74 base (char *s);
75
76 static BOOL
77 dialog_cmd (HWND h, int id, HWND hwndctl, UINT code)
78 {
79   switch (id)
80     {
81     case IDCANCEL:
82       exit_setup (1);
83     case IDOK:
84       if (uninstall_started == 0) {
85         uninstall_started = 1;
86         start_uninstall();
87       }
88       else
89         exit_setup(0);
90       break;
91     }
92   return FALSE;
93 }
94
95 static BOOL CALLBACK
96 dialog_proc (HWND h, UINT message, WPARAM wParam, LPARAM lParam)
97 {
98   switch (message)
99     {
100     case WM_INITDIALOG:
101       unins_dialog = h;
102       unins_action = GetDlgItem (h, IDC_UNINS_ACTION);
103       unins_pkgname = GetDlgItem (h, IDC_UNINS_PKG);
104       unins_filename = GetDlgItem (h, IDC_UNINS_FILE);
105       unins_pprogress = GetDlgItem (h, IDC_UNINS_PPROGRESS);
106       unins_iprogress = GetDlgItem (h, IDC_UNINS_IPROGRESS);
107       unins_diskfull = GetDlgItem (h, IDC_UNINS_DISKFULL);
108       SendMessage (unins_pprogress, PBM_SETRANGE, 0, MAKELPARAM (0, 100));
109       SendMessage (unins_iprogress, PBM_SETRANGE, 0, MAKELPARAM (0, 100));
110       SendMessage (unins_diskfull, PBM_SETRANGE, 0, MAKELPARAM (0, 100));
111       SetWindowText (unins_pkgname, "");
112       SetWindowText (unins_filename, "");
113       SendMessage (unins_pprogress, PBM_SETPOS, (WPARAM) 0, 0);
114       SendMessage (unins_iprogress, PBM_SETPOS, (WPARAM) 0, 0);
115       SendMessage (unins_diskfull, PBM_SETPOS, (WPARAM) 0, 0);
116       return FALSE;
117
118     case XM_DONE:
119       {
120         SetWindowText (GetDlgItem (h, IDOK), "Ok");
121         LONG style = GetWindowLong (GetDlgItem (h, IDCANCEL),
122                                     GWL_STYLE);
123         SetWindowLong (GetDlgItem (h, IDCANCEL),
124                        GWL_STYLE, style & WS_DISABLED);
125       }
126       return FALSE;
127       
128     case WM_COMMAND:
129       return HANDLE_WM_COMMAND (h, wParam, lParam, dialog_cmd);
130     }
131   return DefWindowProc (h, message, wParam, lParam);
132 }
133
134 static DWORD WINAPI uninstall_all (void *);
135
136 static void
137 start_uninstall ()
138 {
139   DWORD tid;
140   HANDLE thread;
141   init_event = CreateEvent (0, 0, 0, 0);
142   thread = CreateThread (0, 0, uninstall_all, 0, 0, &tid);
143   WaitForSingleObject (init_event, 10000);
144   CloseHandle (init_event);
145 }
146
147 static void
148 progress (int bytes, int num)
149 {
150   int perc;
151   if (package_bytes > 100)
152     {
153       perc = (bytes * 100) / package_bytes;
154       SendMessage (unins_pprogress, PBM_SETPOS, (WPARAM) perc, 0);
155     }
156
157   if (npackages > 0)
158     {
159       perc = (num * 100) / npackages;
160       SendMessage (unins_iprogress, PBM_SETPOS, (WPARAM) perc, 0);
161     }
162 }
163
164 static int num_installs, num_uninstalls;
165
166 static void
167 uninstall_one (char *name, int type, int num)
168 {
169   hash dirs;
170   char line[_MAX_PATH];
171   char* fname = (type == TY_GENERIC ? 
172                  concat (root_dir, XEMACS_PACKAGE_DIR, "pkginfo/MANIFEST.",
173                          name,  0) :
174                  concat (root_dir, XEMACS_SETUP_DIR, "MANIFEST.", name,  0));
175
176   FILE* lst = fopen (fname, "rb");
177   int pos = 0;
178
179   if (lst)
180     {
181       fseek (lst, 0, SEEK_END);
182       package_bytes = ftell (lst);
183       fseek (lst, 0, SEEK_SET);
184   
185       SetWindowText (unins_pkgname, name);
186       SetWindowText (unins_action, "Uninstalling...");
187       log (0, "uninstalling %s", name);
188
189       while (fgets (line, sizeof (line), lst))
190         {
191           progress (pos, num);
192           pos += strlen(line);
193           if (line[strlen(line)-1] == '\n')
194             line[strlen(line)-1] = 0;
195
196           dirs.add_subdirs (line);
197
198           char *d = map_filename (line, type);
199           DWORD dw = GetFileAttributes (d);
200           if (dw != 0xffffffff && !(dw & FILE_ATTRIBUTE_DIRECTORY))
201             {
202               log (LOG_BABBLE, "unlink %s", d);
203               DeleteFile (d);
204             }
205         }
206       fclose (lst);
207       remove (fname);
208
209       dirs.reverse_sort ();
210       char *subdir = 0;
211       while ((subdir = dirs.enumerate (subdir)) != 0)
212         {
213           char *d = map_filename (subdir, type);
214           if (RemoveDirectory (d))
215             log (LOG_BABBLE, "rmdir %s", d);
216         }
217       num_uninstalls ++;
218     }
219 }
220
221 void
222 do_uninstall (HINSTANCE h)
223 {
224   num_installs = 0, num_uninstalls = 0;
225
226   next_dialog = 0;              // we're done after this
227
228   if (!root_dir)
229     fatal ("no installation found");
230
231   int rv = DialogBox (h, MAKEINTRESOURCE (IDD_UNINSTALL), 0, dialog_proc);
232   if (rv == -1)
233     fatal (IDS_DIALOG_FAILED);
234 }
235
236 static void
237 read_installed_db ()
238 {
239   if (!root_dir)
240     return;
241
242   char line[1000], pkg[1000], inst[1000], src[1000];
243   int instsz, srcsz;
244
245   FILE *db = fopen (concat (root_dir, XEMACS_SETUP_DIR, "installed.db", 0), "rt");
246   if (!db)
247     return;
248
249   while (fgets (line, 1000, db))
250     {
251       src[0] = 0;
252       srcsz = 0;
253       sscanf (line, "%s %s %d %s %d", pkg, inst, &instsz, src, &srcsz);
254
255       log (0, "read %s", pkg);
256       Package* np = new_package(strdup(pkg));
257       pinfo(*np).install = inst;
258       pinfo(*np).install_size = instsz;
259       // pick up versoin
260       char *v, *d;
261       for (v=base (inst); *v; v++)
262         if (*v == '-' && isdigit(v[1]))
263           {
264             v++;
265             break;
266           }
267       if (!v)
268         v = inst;
269       for (d=v; *d; d++)
270         if (strncmp (d, ".tar", 4) == 0
271             || strncmp (d, "-pkg", 4) == 0)
272           {
273             *d = 0;
274             break;
275           }
276       if (v[0])
277         pinfo(*np).version = strdup (v);
278       else
279         pinfo(*np).version = "0";
280       // Crude but effective
281       if (pkg != 0)
282         if (strncmp ("xemacs-i686", pkg, 11) == 0
283             || (strncmp ("xemacs-i586", pkg, 11) == 0))
284           {
285             np->type = install_type;
286             xemacs_package = np;
287           }
288     }
289   fclose (db);
290 }
291
292 static DWORD WINAPI
293 uninstall_all (void *)
294 {
295   int i;
296   SetEvent (init_event);
297
298   int df = diskfull (root_dir);
299   SendMessage (unins_diskfull, PBM_SETPOS, (WPARAM) df, 0);
300
301   read_installed_db();
302
303   log (0, "There are %d packages\n", npackages);
304   for (i=0; i<npackages; i++)
305     {
306       log (0, "uninstalling %s\n", package[i].name);
307       uninstall_one (package[i].name, package[i].type, i);
308     }
309
310   PostMessage (unins_dialog, XM_DONE, 0, 0);
311
312   remove (concat (root_dir, XEMACS_SETUP_DIR, "installed.db.old", 0));
313   remove (concat (root_dir, XEMACS_SETUP_DIR, "installed.db", 0));
314
315   remove_desktop_setup();
316   remove_xemacs_root();
317   remove_uninstall_path();
318
319   if (num_installs == 0)
320     {
321       //      exit_msg = IDS_UNINSTALL_COMPLETE;
322       return FALSE;
323     }
324
325   return FALSE;
326 }