OSDN Git Service

* cygcheck.cc: Include cygprops.h.
authorcorinna <corinna>
Sat, 31 Oct 2009 22:26:37 +0000 (22:26 +0000)
committercorinna <corinna>
Sat, 31 Oct 2009 22:26:37 +0000 (22:26 +0000)
(del_orphaned_reg): New option variable.
(unique_object_name_opt): Ditto.
(handle_reg_installation): New function.
(print_reg_installations): Ditto.
(del_orphaned_reg_installations): Ditto.
(memmem): Ditto.
(handle_unique_object_name): Ditto.
(dump_sysinfo): Call print_reg_installations from here.
(usage): Add usage for new options --delete-orphaned-installation-keys,
--enable-unique-object-names, --disable-unique-object-names, and
--show-unique-object-names.
(longopts): Add new options --delete-orphaned-installation-keys,
--enable-unique-object-names, --disable-unique-object-names, and
--show-unique-object-names.
(main): Handle new options.
* utils.sgml (cygcheck): Change documentaion accordingly.

winsup/utils/ChangeLog
winsup/utils/cygcheck.cc
winsup/utils/utils.sgml

index 369f75e..5bdebcc 100644 (file)
@@ -1,3 +1,23 @@
+2009-10-31  Corinna Vinschen  <corinna@vinschen.de>
+
+       * cygcheck.cc: Include cygprops.h.
+       (del_orphaned_reg): New option variable.
+       (unique_object_name_opt): Ditto.
+       (handle_reg_installation): New function.
+       (print_reg_installations): Ditto.
+       (del_orphaned_reg_installations): Ditto.
+       (memmem): Ditto.
+       (handle_unique_object_name): Ditto.
+       (dump_sysinfo): Call print_reg_installations from here.
+       (usage): Add usage for new options --delete-orphaned-installation-keys,
+       --enable-unique-object-names, --disable-unique-object-names, and
+       --show-unique-object-names.
+       (longopts): Add new options --delete-orphaned-installation-keys,
+       --enable-unique-object-names, --disable-unique-object-names, and
+       --show-unique-object-names.
+       (main): Handle new options.
+       * utils.sgml (cygcheck): Change documentaion accordingly.
+
 2009-10-28  Corinna Vinschen  <corinna@vinschen.de>
 
        * cygcheck.cc (pretty_id): Drop arguments.  Don't change CYGWIN
index 1d7db59..5f079f0 100644 (file)
@@ -24,6 +24,7 @@
 #include <getopt.h>
 #include "cygwin/include/sys/cygwin.h"
 #include "cygwin/include/mntent.h"
+#include "cygwin/cygprops.h"
 #undef cygwin_internal
 
 #define alloca __builtin_alloca
@@ -38,6 +39,8 @@ int dump_only = 0;
 int find_package = 0;
 int list_package = 0;
 int grep_packages = 0;
+int del_orphaned_reg = 0;
+int unique_object_name_opt = 0;
 
 static char emptystr[] = "";
 
@@ -57,9 +60,10 @@ void package_find (int, char **);
 void package_list (int, char **);
 /* In bloda.cc  */
 void dump_dodgy_apps (int verbose);
+/* Forward declaration */
+static void usage (FILE *, int);
 
-
-static const char version[] = "$Revision: 1.120 $";
+static const char version[] = "$Revision: 1.121 $";
 
 static const char *known_env_vars[] = {
   "c_include_path",
@@ -120,6 +124,15 @@ static common_apps[] = {
   {0, 0}
 };
 
+/* Options without ASCII single char representation. */
+enum
+{
+  CO_DELETE_KEYS = 0x100,
+  CO_ENABLE_UON = 0x101,
+  CO_DISABLE_UON = 0x102,
+  CO_SHOW_UON = 0x103
+};
+
 static int num_paths, max_paths;
 struct pathlike
 {
@@ -1203,6 +1216,172 @@ dump_sysinfo_services ()
     puts ("No Cygwin services found.\n");
 }
 
+enum handle_reg_t
+{
+  PRINT_KEY,
+  DELETE_KEY
+};
+
+void
+handle_reg_installation (handle_reg_t what)
+{
+  HKEY key;
+
+  if (what == PRINT_KEY)
+    printf ("Cygwin installations found in the registry:\n");
+  for (int i = 0; i < 2; ++i)
+    if (RegOpenKeyEx (i ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE,
+                     "SOFTWARE\\Cygwin\\Installations", 0,
+                     what == DELETE_KEY ? KEY_READ | KEY_WRITE : KEY_READ,
+                     &key)
+       == ERROR_SUCCESS)
+      {
+       char name[32], data[PATH_MAX];
+       DWORD nsize, dsize, type;
+       LONG ret;
+
+       for (DWORD index = 0;
+            (ret = RegEnumValue (key, index, name, (nsize = 32, &nsize), 0,
+                                 &type, (PBYTE) data,
+                                 (dsize = PATH_MAX, &dsize)))
+            != ERROR_NO_MORE_ITEMS; ++index)
+         if (ret == ERROR_SUCCESS && dsize > 5)
+           {
+             char *path = data + 4;
+             if (path[1] != ':')
+               *(path += 2) = '\\';
+             if (what == PRINT_KEY)
+               printf ("  %s Key: %s Path: %s", i ? "User:  " : "System:",
+                       name, path);
+             strcat (path, "\\bin\\cygwin1.dll");
+             if (what == PRINT_KEY)
+               printf ("%s\n", access (path, F_OK) ? " (ORPHANED)" : "");
+             else if (access (path, F_OK))
+               {
+                 RegDeleteValue (key, name);
+                 /* Start over since index is not reliable anymore. */
+                 --i;
+                 break;
+               }
+           }
+       RegCloseKey (key);
+      }
+  if (what == PRINT_KEY)
+    printf ("\n");
+}
+
+void
+print_reg_installations ()
+{
+  handle_reg_installation (PRINT_KEY);
+}
+
+void
+del_orphaned_reg_installations ()
+{
+  handle_reg_installation (DELETE_KEY);
+}
+
+/* Unfortunately neither mingw nor Windows know this function. */
+char *
+memmem (char *haystack, size_t haystacklen,
+        const char *needle, size_t needlelen)
+{
+  if (needlelen == 0)
+    return haystack;
+  while (needlelen <= haystacklen)
+    {
+      if (!memcmp (haystack, needle, needlelen))
+        return haystack;
+      haystack++;
+      haystacklen--;
+    }
+  return NULL;
+}
+int
+handle_unique_object_name (int opt, char *path)
+{
+  HANDLE fh, fm;
+  void *haystack;
+
+  if (!path || !*path)
+    usage (stderr, 1);
+
+  DWORD access, share, protect, mapping;
+
+  if (opt == CO_SHOW_UON)
+    {
+      access = GENERIC_READ;
+      share = FILE_SHARE_VALID_FLAGS;
+      protect = PAGE_READONLY;
+      mapping = FILE_MAP_READ;
+    }
+  else
+    {
+      access = GENERIC_READ | GENERIC_WRITE;
+      share = 0;
+      protect = PAGE_READWRITE;
+      mapping = FILE_MAP_WRITE;
+    }
+
+  fh = CreateFile (path, access, share, NULL, OPEN_EXISTING,
+                  FILE_FLAG_BACKUP_SEMANTICS, NULL);
+  if (fh == INVALID_HANDLE_VALUE)
+    {
+      DWORD err = GetLastError ();
+      switch (err)
+       {
+       case ERROR_SHARING_VIOLATION:
+         display_error ("%s still used by other Cygwin processes.\n"
+                        "Please stop all of them and retry.", path);
+         break;
+       case ERROR_ACCESS_DENIED:
+         display_error (
+           "Your permissions are not sufficient to change the file \"%s\"",
+           path);
+         break;
+       case ERROR_FILE_NOT_FOUND:
+         display_error ("%s: No such file.", path);
+         break;
+       default:
+         display_error (path, true, false);
+         break;
+       }
+      return 1;
+    }
+  if (!(fm = CreateFileMapping (fh, NULL, protect, 0, 0, NULL)))
+    display_error ("CreateFileMapping");
+  else if (!(haystack = MapViewOfFile (fm, mapping, 0, 0, 0)))
+    display_error ("MapViewOfFile");
+  else
+    {
+      size_t haystacklen = GetFileSize (fh, NULL);
+      cygwin_props_t *cygwin_props = (cygwin_props_t *) 
+              memmem ((char *) haystack, haystacklen,
+                      CYGWIN_PROPS_MAGIC, sizeof (CYGWIN_PROPS_MAGIC));
+      if (!cygwin_props)
+       display_error ("Can't find Cygwin properties in %s", path);
+      else
+       {
+         if (opt != CO_SHOW_UON)
+           cygwin_props->disable_key = opt - CO_ENABLE_UON;
+         printf ("Unique object names are %s\n",
+                 cygwin_props->disable_key ? "disabled" : "enabled");
+         UnmapViewOfFile (haystack);
+         CloseHandle (fm);
+         CloseHandle (fh);
+         return 0;
+       }
+    }
+  if (haystack)
+    UnmapViewOfFile (haystack);
+  if (fm)
+    CloseHandle (fm);
+  CloseHandle (fh);
+  return 1;
+}
+
 static void
 dump_sysinfo ()
 {
@@ -1557,6 +1736,8 @@ dump_sysinfo ()
     }
   printf ("obcaseinsensitive set to %lu\n\n", obcaseinsensitive);
 
+  print_reg_installations ();
+
   if (givehelp)
     {
       printf ("Listing available drives...\n");
@@ -1987,6 +2168,10 @@ Usage: cygcheck [-v] [-h] PROGRAM\n\
        cygcheck -f FILE [FILE]...\n\
        cygcheck -l [PACKAGE]...\n\
        cygcheck -p REGEXP\n\
+       cygcheck --delete-orphaned-installation-keys\n\
+       cygcheck --enable-unique-object-names Cygwin-DLL\n\
+       cygcheck --disable-unique-object-names Cygwin-DLL\n\
+       cygcheck --show-unique-object-names Cygwin-DLL\n\
        cygcheck -h\n\n\
 List system information, check installed packages, or query package database.\n\
 \n\
@@ -2004,6 +2189,19 @@ At least one command option or a PROGRAM is required, as shown above.\n\
   -l, --list-package   list contents of PACKAGE (or all packages if none given)\n\
   -p, --package-query  search for REGEXP in the entire cygwin.com package\n\
                        repository (requires internet connectivity)\n\
+  --delete-orphaned-installation-keys\n\
+                       Delete installation keys of old, now unused\n\
+                       installations from the registry.  Requires the right\n\
+                       to change the registry.\n\
+  --enable-unique-object-names Cygwin-DLL\n\
+  --disable-unique-object-names Cygwin-DLL\n\
+  --show-unique-object-names Cygwin-DLL\n\
+                       Enable, disable, or show the setting of the\n\
+                       \"unique object names\" setting in the Cygwin DLL\n\
+                       given as argument to this option.  The DLL path must\n\
+                       be given as valid Windows(!) path.\n\
+                       See the users guide for more information.\n\
+                       If you don't know what this means, don't change it.\n\
   -v, --verbose        produce more verbose output\n\
   -h, --help           annotate output with explanatory comments when given\n\
                        with another command, otherwise print this help\n\
@@ -2026,6 +2224,10 @@ struct option longopts[] = {
   {"find-package", no_argument, NULL, 'f'},
   {"list-package", no_argument, NULL, 'l'},
   {"package-query", no_argument, NULL, 'p'},
+  {"delete-orphaned-installation-keys", no_argument, NULL, CO_DELETE_KEYS},
+  {"enable-unique-object-names", no_argument, NULL, CO_ENABLE_UON},
+  {"disable-unique-object-names", no_argument, NULL, CO_DISABLE_UON},
+  {"show-unique-object-names", no_argument, NULL, CO_SHOW_UON},
   {"help", no_argument, NULL, 'h'},
   {"version", no_argument, 0, 'V'},
   {0, no_argument, NULL, 0}
@@ -2127,7 +2329,7 @@ main (int argc, char **argv)
      user's original environment.  */
   char *posixly = getenv ("POSIXLY_CORRECT");
   if (posixly == NULL)
-    (void) putenv("POSIXLY_CORRECT=1");
+    (void) putenv ("POSIXLY_CORRECT=1");
   while ((i = getopt_long (argc, argv, opts, longopts, NULL)) != EOF)
     switch (i)
       {
@@ -2161,6 +2363,14 @@ main (int argc, char **argv)
       case 'h':
        givehelp = 1;
        break;
+      case CO_DELETE_KEYS:
+       del_orphaned_reg = 1;
+       break;
+      case CO_ENABLE_UON:
+      case CO_DISABLE_UON:
+      case CO_SHOW_UON:
+       unique_object_name_opt = i;
+       break;
       case 'V':
        print_version ();
        exit (0);
@@ -2172,7 +2382,8 @@ main (int argc, char **argv)
   if (posixly == NULL)
     putenv ("POSIXLY_CORRECT=");
 
-  if ((argc == 0) && !sysinfo && !keycheck && !check_setup && !list_package)
+  if ((argc == 0) && !sysinfo && !keycheck && !check_setup && !list_package
+      && !del_orphaned_reg)
     {
       if (givehelp)
        usage (stdout, 0);
@@ -2180,11 +2391,18 @@ main (int argc, char **argv)
        usage (stderr, 1);
     }
 
-  if ((check_setup || sysinfo || find_package || list_package || grep_packages)
+  if ((check_setup || sysinfo || find_package || list_package || grep_packages
+       || del_orphaned_reg || unique_object_name_opt)
       && keycheck)
     usage (stderr, 1);
 
-  if ((find_package || list_package || grep_packages) && check_setup)
+  if ((find_package || list_package || grep_packages)
+      && (check_setup || del_orphaned_reg))
+    usage (stderr, 1);
+
+  if ((check_setup || sysinfo || find_package || list_package || grep_packages
+       || del_orphaned_reg)
+      && unique_object_name_opt)
     usage (stderr, 1);
 
   if (dump_only && !check_setup)
@@ -2195,6 +2413,10 @@ main (int argc, char **argv)
 
   if (keycheck)
     return check_keys ();
+  if (unique_object_name_opt)
+    return handle_unique_object_name (unique_object_name_opt, *argv);
+  if (del_orphaned_reg)
+    del_orphaned_reg_installations ();
   if (grep_packages)
     return package_grep (*argv);
 
index 2e6e9c1..e255779 100644 (file)
@@ -13,13 +13,18 @@ command-line utilities support the <literal>--help</literal> and
 <sect2 id="cygcheck"><title>cygcheck</title>
 
 <screen>
-Usage: cygcheck PROGRAM [ -v ] [ -h ]
-       cygcheck -c [ PACKAGE ... ] [ -d ]
-       cygcheck -s [ -r ] [ -v ] [ -h ]
+Usage: cygcheck [-v] [-h] PROGRAM
+       cygcheck -c [-d] [PACKAGE]
+       cygcheck -s [-r] [-v] [-h]
        cygcheck -k
-       cygcheck -f FILE [ FILE ... ]
-       cygcheck -l [ PACKAGE ... ]
+       cygcheck -f FILE [FILE]...
+       cygcheck -l [PACKAGE]...
        cygcheck -p REGEXP
+       cygcheck --delete-orphaned-installation-keys
+       cygcheck --enable-unique-object-names Cygwin-DLL
+       cygcheck --disable-unique-object-names Cygwin-DLL
+       cygcheck --show-unique-object-names Cygwin-DLL
+       cygcheck -h
 List system information, check installed packages, or query package database.
 
 At least one command option or a PROGRAM is required, as shown above.
@@ -36,6 +41,19 @@ At least one command option or a PROGRAM is required, as shown above.
   -l, --list-package   list contents of PACKAGE (or all packages if none given)
   -p, --package-query  search for REGEXP in the entire cygwin.com package
                        repository (requires internet connectivity)
+  --delete-orphaned-installation-keys
+                       Delete installation keys of old, now unused
+                       installations from the registry.  Requires the right
+                       to change the registry.
+  --enable-unique-object-names Cygwin-DLL
+  --disable-unique-object-names Cygwin-DLL
+  --show-unique-object-names Cygwin-DLL
+                       Enable, disable, or show the setting of the
+                       \"unique object names\" setting in the Cygwin DLL
+                       given as argument to this option.  The DLL path must
+                       be given as valid Windows(!) path.
+                       See the users guide for more information.
+                       If you don't know what this means, don't change it.
   -v, --verbose        produce more verbose output
   -h, --help           annotate output with explanatory comments when given
                        with another command, otherwise print this help
@@ -184,6 +202,65 @@ for example:</para>
 <prompt>$</prompt> <userinput>cygcheck -s -v -r -h &gt; cygcheck_output.txt</userinput>
 </screen>
 
+<para>
+Each Cygwin DLL stores its path and installation key in the registry.
+This allows troubleshooting of problems which could be a result of having
+multiple concurrent Cygwin installations.  However, if you're experimenting
+a lot with different Cygwin installation paths, your registry could 
+accumulate a lot of old Cygwin installation entries for which the
+installation doesn't exist anymore.  To get rid of these orphaned registry
+entries, use the <command>cygcheck --delete-orphaned-installation-keys</command>
+command.</para>
+
+<para>
+Each Cygwin DLL generates a key value from its installation path.  This
+value is not only stored in the registry, it's also used to generate
+global object names used for interprocess communication.   This keeps
+different Cygwin installations separate.  Processes running under a
+Cygwin DLL installed in C:\cygwin don't see processes running under a
+Cygwin DLL installed in C:\Program Files\cygwin.  This allows
+running multiple versions of Cygwin DLLs without these versions to
+interfere with each other, or to run small third-party installations
+for a specific purpose independently from a Cygwin net distribution.
+</para>
+
+<para>
+For debugging purposes it could be desired that the various Cygwin DLLs
+use the same key, independently from their installation paths.  If the
+DLLs have different versions, trying to run processes under these DLLs
+concurrently will result in error messages like this one:</para>
+
+<screen>
+*** shared version mismatch detected - 0x8A88009C/0x75BE0074.
+This problem is probably due to using incompatible versions of the cygwin DLL.
+Search for cygwin1.dll using the Windows Start->Find/Search facility
+and delete all but the most recent version.  The most recent version *should*
+reside in x:\\cygwin\\bin, where 'x' is the drive on which you have
+installed the cygwin distribution.  Rebooting is also suggested if you
+are unable to find another cygwin DLL.
+</screen>
+
+<para>
+To disable the usage of a unique key value of a certain Cygwin DLL, use
+the <command>cygcheck --disable-unique-object-names Cygwin-DLL</command>
+command.  <literal>Cygwin-DLL</literal> is the Windows path (*not* a 
+Cygwin POSIX path) to the DLL for which you want to disable this feature.
+Note that you have to stop all Cygwin processes running under this DLL,
+before you're allowed to change this setting.  For instance, run
+<command>cygcheck</command> from a DOS command line for this purpose.</para>
+
+<para>To re-enable the usage of a unique key, use the
+<command>cygcheck --enable-unique-object-names Cygwin-DLL</command> command.
+This option has the same characteristics as the
+<literal>--disable-unique-object-names</literal> option</para>
+
+<para>Finally, you can use
+<command>cygcheck --show-unique-object-names Cygwin-DLL</command> to find out
+if the given Cygwin DLL use unique object names or not.  In contrast to the
+<literal>--disable-...</literal> and <literal>--enable-...</literal> options,
+the <literal>--show-unique-object-names</literal> option also works for
+Cygwin DLLs which are currently in use.</para>
+
 </sect2>
 
 <sect2 id="cygpath"><title>cygpath</title>