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