]> cygwin.com Git - cygwin-apps/setup.git/blobdiff - install.cc
* ini.h: add source actions
[cygwin-apps/setup.git] / install.cc
index 76e959d603bbac9f54b4d6420fecf7e2d1ce4a3b..9832121ee30ee30ab0d93b6fd3839f39b99de892 100644 (file)
    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;
@@ -59,7 +67,7 @@ dialog_cmd (HWND h, int id, HWND hwndctl, UINT code)
   switch (id)
     {
     case IDCANCEL:
-      ExitProcess(0);
+      exit_setup (1);
     }
 }
 
@@ -72,6 +80,7 @@ dialog_proc (HWND h, UINT message, WPARAM wParam, LPARAM lParam)
     {
     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);
@@ -80,7 +89,7 @@ dialog_proc (HWND h, UINT message, WPARAM wParam, LPARAM lParam)
       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;
 }
@@ -134,20 +143,17 @@ progress (int bytes)
 {
   int perc;
 
-  if (package_bytes > 0)
+  if (package_bytes > 100)
     {
-      perc = bytes * 100 / package_bytes;
+      perc = bytes / (package_bytes / 100);
       SendMessage (ins_pprogress, PBM_SETPOS, (WPARAM) perc, 0);
     }
 
-  if (total_bytes > 0)
+  if (total_bytes > 100)
     {
-      perc = (total_bytes_sofar + bytes) * 100 / total_bytes;
+      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
@@ -161,26 +167,211 @@ badrename (char *o, char *n)
 }
 
 static char *standard_dirs[] = {
+  "/bin",
   "/etc",
-  "/usr",
+  "/lib",
   "/tmp",
+  "/usr",
+  "/usr/bin",
+  "/usr/lib",
+  "/usr/local",
+  "/usr/local/bin",
+  "/usr/local/etc",
+  "/usr/local/lib",
   "/usr/tmp",
+  "/var/run",
   "/var/tmp",
   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 = 0;
+  int i;
+  int errors = 0;
+
+  num_installs = 0, num_uninstalls = 0;
+
+  next_dialog = IDD_DESKTOP;
 
   mkdir_p (1, root_dir);
 
@@ -191,6 +382,13 @@ do_install (HINSTANCE h)
       free (p);
     }
 
+  /* Create /var/run/utmp */
+  char *utmp = concat (root_dir, "/var/run/utmp", 0);
+  FILE *ufp = fopen (utmp, "wb");
+  if (ufp)
+    fclose (ufp);
+  free (utmp);
+
   dismiss_url_status_dialog ();
 
   init_dialog ();
@@ -198,69 +396,41 @@ do_install (HINSTANCE h)
   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)
-    {
-      do_desktop (h);
-      note (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);
@@ -285,24 +455,34 @@ do_install (HINSTANCE h)
       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)
@@ -317,19 +497,35 @@ do_install (HINSTANCE h)
   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");
+  remove_mount ("/usr/lib");
   remove_mount ("/var");
   remove_mount ("/lib");
   remove_mount ("/bin");
   remove_mount ("/etc");
 
   int istext = (root_text == IDC_ROOT_TEXT) ? 1 : 0;
+  int issystem = (root_scope == IDC_ROOT_SYSTEM) ? 1 : 0;
 
-  create_mount ("/", root_dir, istext);
-  create_mount ("/usr/bin", concat (root_dir, "/bin", 0), istext);
-  create_mount ("/usr/lib", concat (root_dir, "/lib", 0), istext);
-
-  do_desktop(h);
+  create_mount ("/", root_dir, istext, issystem);
+  create_mount ("/usr/bin", concat (root_dir, "/bin", 0), istext, issystem);
+  create_mount ("/usr/lib", concat (root_dir, "/lib", 0), istext, issystem);
 
-  note (IDS_INSTALL_COMPLETE);
+  if (errors)
+    exit_msg = IDS_INSTALL_INCOMPLETE;
+  else
+    exit_msg = IDS_INSTALL_COMPLETE;
 }
This page took 0.032372 seconds and 5 git commands to generate.