handling two tasks in one thread. We also create or update all the
files in /etc/setup/* and create the mount points. */
+static char *cvsid = "\n%%% $Id$\n";
+
#include "win32.h"
#include "commctrl.h"
#include <stdio.h>
#include <stdlib.h>
+#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include "diskfull.h"
#include "msg.h"
#include "mount.h"
+#include "log.h"
+#include "hash.h"
+
+#include "port.h"
static HWND ins_dialog = 0;
+static HWND ins_action = 0;
static HWND ins_pkgname = 0;
static HWND ins_filename = 0;
static HWND ins_pprogress = 0;
switch (id)
{
case IDCANCEL:
- ExitProcess(0);
+ exit_setup (1);
}
}
{
case WM_INITDIALOG:
ins_dialog = h;
+ ins_action = GetDlgItem (h, IDC_INS_ACTION);
ins_pkgname = GetDlgItem (h, IDC_INS_PKG);
ins_filename = GetDlgItem (h, IDC_INS_FILE);
ins_pprogress = GetDlgItem (h, IDC_INS_PPROGRESS);
SetEvent (init_event);
return FALSE;
case WM_COMMAND:
- return HANDLE_WM_COMMAND(h, wParam, lParam, dialog_cmd);
+ return HANDLE_WM_COMMAND (h, wParam, lParam, dialog_cmd);
}
return FALSE;
}
perc = (total_bytes_sofar + bytes) / (total_bytes / 100);
SendMessage (ins_iprogress, PBM_SETPOS, (WPARAM) perc, 0);
}
-
- int df = diskfull (root_dir);
- SendMessage (ins_diskfull, PBM_SETPOS, (WPARAM) df, 0);
}
static void
"/etc",
"/lib",
"/tmp",
+ "/usr",
"/usr/bin",
"/usr/lib",
+ "/usr/local",
"/usr/local/bin",
"/usr/local/etc",
"/usr/local/lib",
0
};
+void
+hash::add_subdirs (char *path)
+{
+ char *nonp, *pp;
+ for (nonp = path; *nonp == '\\' || *nonp == '/'; nonp++);
+ for (pp = path + strlen(path) - 1; pp>nonp; pp--)
+ if (*pp == '/' || *pp == '\\')
+ {
+ int i, s=0;
+ char c = *pp;
+ *pp = 0;
+ for (i=0; standard_dirs[i]; i++)
+ if (strcmp (standard_dirs[i]+1, path) == 0)
+ {
+ s = 1;
+ break;
+ }
+ if (s == 0)
+ add (path);
+ *pp = c;
+ }
+}
+
+char *
+map_filename (char *fn)
+{
+ char *dest_file;
+ while (*fn == '/' || *fn == '\\')
+ fn++;
+ if (strncmp (fn, "usr/bin/", 8) == 0)
+ dest_file = concat (root_dir, "/bin/", fn+8, 0);
+ else if (strncmp (fn, "usr/lib/", 8) == 0)
+ dest_file = concat (root_dir, "/lib/", fn+8, 0);
+ else
+ dest_file = concat (root_dir, "/", fn, 0);
+ return dest_file;
+}
+
#define pi (package[i].info[package[i].trust])
#define LOOP_PACKAGES \
for (i=0; i<npackages; i++) \
- if (package[i].action == ACTION_NEW \
- || package[i].action == ACTION_UPGRADE)
+ if ((package[i].action == ACTION_NEW \
+ || package[i].action == ACTION_UPGRADE) \
+ && pi.install)
+
+static int
+exists (char *file)
+{
+ if (_access (file, 0) == 0)
+ return 1;
+ return 0;
+}
+
+
+static int num_installs, num_uninstalls;
+
+static void
+uninstall_one (char *name, int action)
+{
+ hash dirs;
+ char line[_MAX_PATH];
+
+ gzFile lst = gzopen (concat (root_dir, "/etc/setup/",
+ name, ".lst.gz", 0),
+ "rb");
+ if (lst)
+ {
+ SetWindowText (ins_pkgname, name);
+ SetWindowText (ins_action, "Uninstalling...");
+ if (action == ACTION_UPGRADE)
+ log (0, "Uninstalling old %s", name);
+ else
+ log (0, "Uninstalling %s", name);
+
+ while (gzgets (lst, line, sizeof (line)))
+ {
+ if (line[strlen(line)-1] == '\n')
+ line[strlen(line)-1] = 0;
+
+ dirs.add_subdirs (line);
+
+ char *d = map_filename (line);
+ DWORD dw = GetFileAttributes (d);
+ if (dw != 0xffffffff && !(dw & FILE_ATTRIBUTE_DIRECTORY))
+ {
+ log (LOG_BABBLE, "unlink %s", d);
+ DeleteFile (d);
+ }
+ }
+ gzclose (lst);
+
+ remove (concat (root_dir, "/etc/setup/", name, ".lst.gz", 0));
+
+ dirs.reverse_sort ();
+ char *subdir = 0;
+ while ((subdir = dirs.enumerate (subdir)) != 0)
+ {
+ char *d = map_filename (subdir);
+ if (RemoveDirectory (d))
+ log (LOG_BABBLE, "rmdir %s", d);
+ }
+ num_uninstalls ++;
+ }
+}
+
+
+static int
+install_one (char *name, char *file, int file_size, int action)
+{
+ int errors = 0;
+ char *local = file, *cp, *fn, *base;
+
+ base = local;
+ for (cp=local; *cp; cp++)
+ if (*cp == '/' || *cp == '\\' || *cp == ':')
+ base = cp+1;
+ SetWindowText (ins_pkgname, base);
+
+ if (!exists (local) && exists (base))
+ local = base;
+ if (!exists (local))
+ {
+ note (IDS_ERR_OPEN_READ, local, "No such file");
+ return 1;
+ }
+
+ gzFile lst = gzopen (concat (root_dir, "/etc/setup/",
+ name, ".lst.gz", 0),
+ "wb9");
+
+ package_bytes = file_size;
+
+ switch (action)
+ {
+ case ACTION_NEW:
+ SetWindowText (ins_action, "Installing...");
+ break;
+ case ACTION_UPGRADE:
+ SetWindowText (ins_action, "Upgrading...");
+ break;
+ }
+
+ log (0, "Installing %s", local);
+ tar_open (local);
+ while (fn = tar_next_file ())
+ {
+ char *dest_file;
+
+ if (lst)
+ gzprintf (lst, "%s\n", fn);
+
+ dest_file = map_filename (fn);
+
+ SetWindowText (ins_filename, dest_file);
+ log (LOG_BABBLE, "Installing file %s", dest_file);
+ if (tar_read_file (dest_file) != 0)
+ {
+ log (0, "Unable to install file %s", dest_file);
+ errors ++;
+ }
+
+ progress (tar_ftell ());
+ num_installs ++;
+ }
+ tar_close ();
+
+ total_bytes_sofar += file_size;
+ progress (0);
+
+ int df = diskfull (root_dir);
+ SendMessage (ins_diskfull, PBM_SETPOS, (WPARAM) df, 0);
+
+ if (lst)
+ gzclose (lst);
+
+ return errors;
+}
void
do_install (HINSTANCE h)
{
- int i, num_installs = 0;
- next_dialog = IDD_S_DESKTOP;
+ int i;
+ int errors = 0;
+
+ num_installs = 0, num_uninstalls = 0;
+
+ next_dialog = IDD_DESKTOP;
mkdir_p (1, root_dir);
total_bytes = 0;
total_bytes_sofar = 0;
+ int df = diskfull (root_dir);
+ SendMessage (ins_diskfull, PBM_SETPOS, (WPARAM) df, 0);
+
LOOP_PACKAGES
{
total_bytes += pi.install_size;
}
- LOOP_PACKAGES
+ for (i=0; i<npackages; i++)
{
- char *local = pi.install, *cp, *fn, *base;
-
- base = local;
- for (cp=pi.install; *cp; cp++)
- if (*cp == '/' || *cp == '\\' || *cp == ':')
- base = cp+1;
- SetWindowText (ins_pkgname, base);
-
- gzFile lst = gzopen (concat (root_dir, "/etc/setup/",
- package[i].name, ".lst.gz", 0),
- "wb9");
-
- package_bytes = pi.install_size;
-
- tar_open (local);
- while (fn = tar_next_file ())
+ if (package[i].action == ACTION_UNINSTALL
+ || (package[i].action == ACTION_UPGRADE && pi.install))
{
- char *dest_file;
-
- while (*fn == '/' || *fn == '\\')
- fn++;
-
- if (lst)
- gzprintf(lst, "%s\n", fn);
-
- if (strncmp (fn, "usr/bin/", 8) == 0)
- dest_file = concat(root_dir, "/bin/", fn+8, 0);
- else if (strncmp (fn, "usr/lib/", 8) == 0)
- dest_file = concat(root_dir, "/lib/", fn+8, 0);
- else
- dest_file = concat(root_dir, "/", fn, 0);
-
- SetWindowText (ins_filename, dest_file);
- tar_read_file (dest_file);
-
- progress (tar_ftell ());
- num_installs ++;
+ uninstall_one (package[i].name, package[i].action);
+ uninstall_one (concat (package[i].name, "-src", 0), package[i].action);
}
- tar_close ();
-
- total_bytes_sofar += pi.install_size;
- progress (0);
- if (lst)
- gzclose (lst);
- }
+ if ((package[i].action == ACTION_NEW
+ || package[i].action == ACTION_UPGRADE)
+ && pi.install)
+ {
+ int e = install_one (package[i].name, pi.install, pi.install_size, package[i].action);
+ if (package[i].srcaction == SRCACTION_YES && pi.source)
+ e += install_one (concat (package[i].name, "-src", 0), pi.source, pi.source_size,
+ package[i].action);
+ if (e)
+ {
+ package[i].action = ACTION_ERROR;
+ errors++;
+ }
+ }
+ } // end of big package loop
ShowWindow (ins_dialog, SW_HIDE);
- if (num_installs == 0)
- {
- exit_msg = IDS_NOTHING_INSTALLED;
- return;
- }
-
char *odbn = concat (root_dir, "/etc/setup/installed.db", 0);
char *ndbn = concat (root_dir, "/etc/setup/installed.db.new", 0);
char *sdbn = concat (root_dir, "/etc/setup/installed.db.old", 0);
while (fgets (line, 1000, odb))
{
printit = 1;
- sscanf(line, "%s", pkg);
- LOOP_PACKAGES
+ sscanf (line, "%s", pkg);
+ for (i=0; i<npackages; i++)
{
if (strcmp (pkg, package[i].name) == 0)
- {
- printit = 0;
- break;
- }
+ switch (package[i].action)
+ {
+ case ACTION_NEW:
+ case ACTION_UPGRADE:
+ case ACTION_UNINSTALL:
+ printit = 0;
+ break;
+ }
}
if (printit)
fputs (line, ndb);
}
}
+
LOOP_PACKAGES
{
- fprintf (ndb, "%s %s %d\n", package[i].name,
- pi.install, pi.install_size);
+ if (package[i].srcaction == SRCACTION_YES)
+ fprintf (ndb, "%s %s %d %s %d\n", package[i].name,
+ pi.install, pi.install_size,
+ pi.source, pi.source_size);
+ else
+ fprintf (ndb, "%s %s %d\n", package[i].name,
+ pi.install, pi.install_size);
}
if (odb)
if (rename (ndbn, odbn))
badrename (ndbn, odbn);
+ if (num_installs == 0 && num_uninstalls == 0)
+ {
+ exit_msg = IDS_NOTHING_INSTALLED;
+ return;
+ }
+ if (num_installs == 0)
+ {
+ exit_msg = IDS_UNINSTALL_COMPLETE;
+ return;
+ }
+
remove_mount ("/");
remove_mount ("/usr");
remove_mount ("/usr/bin");
create_mount ("/usr/bin", concat (root_dir, "/bin", 0), istext, issystem);
create_mount ("/usr/lib", concat (root_dir, "/lib", 0), istext, issystem);
- exit_msg = IDS_INSTALL_COMPLETE;
+ if (errors)
+ exit_msg = IDS_INSTALL_INCOMPLETE;
+ else
+ exit_msg = IDS_INSTALL_COMPLETE;
}