OSDN Git Service

* fhandler_registry.cc (perf_data_files): New table.
authorcorinna <corinna>
Fri, 19 Dec 2008 14:31:40 +0000 (14:31 +0000)
committercorinna <corinna>
Fri, 19 Dec 2008 14:31:40 +0000 (14:31 +0000)
(PERF_DATA_FILE_COUNT): New constant.
(fhandler_registry::exists): Add check for HKEY_PERFORMANCE_DATA
value names.
(fhandler_registry::fstat): For HKEY_PERFORMANCE_DATA, return
default values only.
(fhandler_registry::readdir): For HKEY_PERFORMANCE_DATA, list
names from perf_data_files only.
(fhandler_registry::fill_filebuf): Use larger buffer to speed up
access to HKEY_PERFORMANCE_DATA values.  Remove check for possible
subkey.  Add RegCloseKey ().
(open_key): Replace goto by break, remove label.  Do not try to
open subkey of HKEY_PERFORMANCE_DATA.  Add missing RegCloseKey ()
after open subkey error.

winsup/cygwin/ChangeLog
winsup/cygwin/fhandler_registry.cc

index 2b18c7d..3ee453f 100644 (file)
@@ -1,3 +1,20 @@
+2008-12-19  Christian Franke  <franke@computer.org>
+
+       * fhandler_registry.cc (perf_data_files): New table.
+       (PERF_DATA_FILE_COUNT): New constant.
+       (fhandler_registry::exists): Add check for HKEY_PERFORMANCE_DATA
+       value names.
+       (fhandler_registry::fstat): For HKEY_PERFORMANCE_DATA, return
+       default values only.
+       (fhandler_registry::readdir): For HKEY_PERFORMANCE_DATA, list
+       names from perf_data_files only.
+       (fhandler_registry::fill_filebuf): Use larger buffer to speed up
+       access to HKEY_PERFORMANCE_DATA values.  Remove check for possible
+       subkey.  Add RegCloseKey ().
+       (open_key): Replace goto by break, remove label.  Do not try to
+       open subkey of HKEY_PERFORMANCE_DATA.  Add missing RegCloseKey ()
+       after open subkey error.
+
 2008-12-19  Corinna Vinschen  <corinna@vinschen.de>
 
        * path.cc (path_conv::check): Handle incoming DOS paths non-POSIXy,
index 9efb2d1..c3c2264 100644 (file)
@@ -75,6 +75,22 @@ static const char *special_dot_files[] =
 static const int SPECIAL_DOT_FILE_COUNT =
   (sizeof (special_dot_files) / sizeof (const char *)) - 1;
 
+/* Value names for HKEY_PERFORMANCE_DATA.
+ *
+ * CAUTION: Never call RegQueryValueEx (HKEY_PERFORMANCE_DATA, "Add", ...).
+ * It WRITES data and may destroy the perfc009.dat file.  Same applies to
+ * name prefixes "Ad" and "A".
+ */
+static const char * const perf_data_files[] =
+{
+  "@",
+  "Costly",
+  "Global"
+};
+
+static const int PERF_DATA_FILE_COUNT =
+  sizeof (perf_data_files) / sizeof (perf_data_files[0]);
+
 static HKEY open_key (const char *name, REGSAM access, DWORD wow64, bool isValue);
 
 /* Return true if char must be encoded.
@@ -273,6 +289,24 @@ fhandler_registry::exists ()
          if (hKey == (HKEY) INVALID_HANDLE_VALUE)
            return 0;
 
+         if (hKey == HKEY_PERFORMANCE_DATA)
+           {
+             /* RegEnumValue () returns garbage for this key.
+                RegQueryValueEx () returns a PERF_DATA_BLOCK even
+                if a value does not contain any counter objects.
+                So allow access to the generic names and to
+                (blank separated) lists of counter numbers.
+                Never allow access to "Add", see above comment.  */
+             for (int i = 0; i < PERF_DATA_FILE_COUNT && file_type == 0; i++)
+               {
+                 if (strcasematch (perf_data_files[i], file))
+                   file_type = -1;
+               }
+             if (file_type == 0 && !file[strspn (file, " 0123456789")])
+               file_type = -1;
+             goto out;
+           }
+
          if (!val_only && dec_file[0])
            {
              while (ERROR_SUCCESS ==
@@ -376,7 +410,11 @@ fhandler_registry::fstat (struct __stat64 *buf)
        open_key (path, STANDARD_RIGHTS_READ | KEY_QUERY_VALUE, wow64,
                  (file_type < 0) ? true : false);
 
-      if (hKey != (HKEY) INVALID_HANDLE_VALUE)
+      if (hKey == HKEY_PERFORMANCE_DATA)
+       /* RegQueryInfoKey () always returns write time 0,
+          RegQueryValueEx () does not return required buffer size.  */
+       ;
+      else if (hKey != (HKEY) INVALID_HANDLE_VALUE)
        {
          FILETIME ftLastWriteTime;
          DWORD subkey_count;
@@ -474,6 +512,18 @@ fhandler_registry::readdir (DIR *dir, dirent *de)
       res = 0;
       goto out;
     }
+  if ((HKEY) dir->__handle == HKEY_PERFORMANCE_DATA)
+    {
+      /* RegEnumValue () returns garbage for this key,
+         simulate only a minimal listing of the generic names.  */
+      if (dir->__d_position >= SPECIAL_DOT_FILE_COUNT + PERF_DATA_FILE_COUNT)
+       goto out;
+      strcpy (de->d_name, perf_data_files[dir->__d_position - SPECIAL_DOT_FILE_COUNT]);
+      dir->__d_position++;
+      res = 0;
+      goto out;
+    }
+
 retry:
   if (dir->__d_position & REG_ENUM_VALUES_MASK)
     /* For the moment, the type of key is ignored here. when write access is added,
@@ -782,23 +832,21 @@ fhandler_registry::fill_filebuf ()
       bufalloc = 0;
       do
        {
-         bufalloc += 1000;
+         bufalloc += 16 * 1024;
          filebuf = (char *) crealloc_abort (filebuf, bufalloc);
          size = bufalloc;
          error = RegQueryValueEx (handle, value_name, NULL, &type,
                                   (BYTE *) filebuf, &size);
          if (error != ERROR_SUCCESS && error != ERROR_MORE_DATA)
            {
-             if (error != ERROR_FILE_NOT_FOUND)
-               {
-                 seterrno_from_win_error (__FILE__, __LINE__, error);
-                 return true;
-               }
-             goto value_not_found;
+             seterrno_from_win_error (__FILE__, __LINE__, error);
+             return false;
            }
        }
       while (error == ERROR_MORE_DATA);
       filesize = size;
+      /* RegQueryValueEx () opens HKEY_PERFORMANCE_DATA.  */
+      RegCloseKey (handle);
     }
   return true;
 value_not_found:
@@ -851,9 +899,9 @@ open_key (const char *name, REGSAM access, DWORD wow64, bool isValue)
       if (*name)
        name++;
       if (*name == 0 && isValue == true)
-       goto out;
+       break;
 
-      if (val_only || !component[0])
+      if (val_only || !component[0] || hKey == HKEY_PERFORMANCE_DATA)
        {
          set_errno (ENOENT);
          if (parentOpened)
@@ -874,14 +922,14 @@ open_key (const char *name, REGSAM access, DWORD wow64, bool isValue)
                                    REG_OPTION_BACKUP_RESTORE,
                                    effective_access | wow64, NULL,
                                    &hKey, NULL);
+         if (parentOpened)
+           RegCloseKey (hParentKey);
          if (error != ERROR_SUCCESS)
            {
              hKey = (HKEY) INVALID_HANDLE_VALUE;
              seterrno_from_win_error (__FILE__, __LINE__, error);
              return hKey;
            }
-         if (parentOpened)
-           RegCloseKey (hParentKey);
          hParentKey = hKey;
          parentOpened = true;
        }
@@ -895,7 +943,6 @@ open_key (const char *name, REGSAM access, DWORD wow64, bool isValue)
          hParentKey = hKey;
        }
     }
-out:
   return hKey;
 }