You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by as...@apache.org on 2012/11/24 21:29:48 UTC

svn commit: r1413258 [16/33] - in /subversion/branches/compressed-pristines: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ contrib/client-side/emacs/ contrib/server-side/fsfsfixer/ notes/ notes/directory-index/ subversion/ subv...

Modified: subversion/branches/compressed-pristines/subversion/libsvn_subr/sysinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_subr/sysinfo.c?rev=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_subr/sysinfo.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_subr/sysinfo.c Sat Nov 24 20:29:11 2012
@@ -1,655 +1,1131 @@
-/*
- * sysinfo.c :  information about the running system
- *
- * ====================================================================
- *    Licensed to the Apache Software Foundation (ASF) under one
- *    or more contributor license agreements.  See the NOTICE file
- *    distributed with this work for additional information
- *    regarding copyright ownership.  The ASF licenses this file
- *    to you under the Apache License, Version 2.0 (the
- *    "License"); you may not use this file except in compliance
- *    with the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *    Unless required by applicable law or agreed to in writing,
- *    software distributed under the License is distributed on an
- *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *    KIND, either express or implied.  See the License for the
- *    specific language governing permissions and limitations
- *    under the License.
- * ====================================================================
- */
-
-
-
-#ifdef WIN32
-#define WIN32_LEAN_AND_MEAN
-#define PSAPI_VERSION 1
-#include <windows.h>
-#include <psapi.h>
-#endif
-
-#define APR_WANT_STRFUNC
-#include <apr_want.h>
-
-#include <apr_lib.h>
-#include <apr_pools.h>
-#include <apr_file_info.h>
-#include <apr_strings.h>
-
-#include "svn_ctype.h"
-#include "svn_error.h"
-#include "svn_utf.h"
-
-#include "sysinfo.h"
-#include "svn_private_config.h"
-
-#if HAVE_SYS_UTSNAME_H
-#include <sys/utsname.h>
-#endif
-
-#ifdef SVN_HAVE_MACOS_PLIST
-#include <CoreFoundation/CoreFoundation.h>
-#endif
-
-#if HAVE_UNAME
-static const char* canonical_host_from_uname(apr_pool_t *pool);
-#endif
-
-#ifdef WIN32
-static const char * win32_canonical_host(apr_pool_t *pool);
-static const char * win32_release_name(apr_pool_t *pool);
-static const char * win32_shared_libs(apr_pool_t *pool);
-#endif /* WIN32 */
-
-#ifdef SVN_HAVE_MACOS_PLIST
-static const char *macos_release_name(apr_pool_t *pool);
-#endif  /* SVN_HAVE_MACOS_PLIST */
-
-
-const char *
-svn_sysinfo__canonical_host(apr_pool_t *pool)
-{
-#if HAVE_UNAME
-  return canonical_host_from_uname(pool);
-#elif defined(WIN32)
-  return win32_canonical_host(pool);
-#else
-  return "unknown-unknown-unknown";
-#endif
-}
-
-
-const char *
-svn_sysinfo__release_name(apr_pool_t *pool)
-{
-#ifdef WIN32
-  return win32_release_name(pool);
-#elif defined(SVN_HAVE_MACOS_PLIST)
-  return macos_release_name(pool);
-#else
-  return NULL;
-#endif
-}
-
-
-const char *
-svn_sysinfo__loaded_libs(apr_pool_t *pool)
-{
-#ifdef WIN32
-  return win32_shared_libs(pool);
-#else
-  return NULL;
-#endif
-}
-
-
-#if HAVE_UNAME
-static const char*
-canonical_host_from_uname(apr_pool_t *pool)
-{
-  const char *machine = "unknown";
-  const char *vendor = "unknown";
-  const char *sysname = "unknown";
-  const char *sysver = "";
-  struct utsname info;
-
-  if (0 <= uname(&info))
-    {
-      svn_error_t *err;
-      const char *tmp;
-
-      err = svn_utf_cstring_to_utf8(&tmp, info.machine, pool);
-      if (err)
-        svn_error_clear(err);
-      else
-        machine = tmp;
-
-      err = svn_utf_cstring_to_utf8(&tmp, info.sysname, pool);
-      if (err)
-        svn_error_clear(err);
-      else
-        {
-          char *lwr = apr_pstrdup(pool, tmp);
-          char *it = lwr;
-          while (*it)
-            {
-              if (svn_ctype_isupper(*it))
-                *it = apr_tolower(*it);
-              ++it;
-            }
-          sysname = lwr;
-        }
-
-      if (0 == strcmp(sysname, "darwin"))
-        vendor = "apple";
-
-      err = svn_utf_cstring_to_utf8(&tmp, info.release, pool);
-      if (err)
-        svn_error_clear(err);
-      else
-        sysver = tmp;
-    }
-
-  return apr_psprintf(pool, "%s-%s-%s%s", machine, vendor, sysname, sysver);
-}
-#endif  /* HAVE_UNAME */
-
-
-#ifdef WIN32
-typedef DWORD (WINAPI *FNGETNATIVESYSTEMINFO)(LPSYSTEM_INFO);
-typedef BOOL (WINAPI *FNENUMPROCESSMODULES) (HANDLE, HMODULE, DWORD, LPDWORD);
-
-/* Get system and version info, and try to tell the difference
-   between the native system type and the runtime environment of the
-   current process. Populate results in SYSINFO, LOCAL_SYSINFO
-   (optional) and OSINFO. */
-static BOOL
-system_info(SYSTEM_INFO *sysinfo,
-            SYSTEM_INFO *local_sysinfo,
-            OSVERSIONINFOEXW *osinfo)
-{
-  FNGETNATIVESYSTEMINFO GetNativeSystemInfo_ = (FNGETNATIVESYSTEMINFO)
-    GetProcAddress(GetModuleHandleA("kernel32.dll"), "GetNativeSystemInfo");
-
-  ZeroMemory(sysinfo, sizeof *sysinfo);
-  if (local_sysinfo)
-    {
-      ZeroMemory(local_sysinfo, sizeof *local_sysinfo);
-      GetSystemInfo(local_sysinfo);
-      if (GetNativeSystemInfo_)
-        GetNativeSystemInfo_(sysinfo);
-      else
-        memcpy(sysinfo, local_sysinfo, sizeof *sysinfo);
-    }
-  else
-    GetSystemInfo(sysinfo);
-
-  ZeroMemory(osinfo, sizeof *osinfo);
-  osinfo->dwOSVersionInfoSize = sizeof *osinfo;
-  if (!GetVersionExW((LPVOID)osinfo))
-    return FALSE;
-
-  return TRUE;
-}
-
-/* Map the proccessor type from SYSINFO to a string. */
-static const char *
-processor_name(SYSTEM_INFO *sysinfo)
-{
-  switch (sysinfo->wProcessorArchitecture)
-    {
-    case PROCESSOR_ARCHITECTURE_AMD64:         return "x86_64";
-    case PROCESSOR_ARCHITECTURE_IA64:          return "ia64";
-    case PROCESSOR_ARCHITECTURE_INTEL:         return "x86";
-    case PROCESSOR_ARCHITECTURE_MIPS:          return "mips";
-    case PROCESSOR_ARCHITECTURE_ALPHA:         return "alpha32";
-    case PROCESSOR_ARCHITECTURE_PPC:           return "powerpc";
-    case PROCESSOR_ARCHITECTURE_SHX:           return "shx";
-    case PROCESSOR_ARCHITECTURE_ARM:           return "arm";
-    case PROCESSOR_ARCHITECTURE_ALPHA64:       return "alpha";
-    case PROCESSOR_ARCHITECTURE_MSIL:          return "msil";
-    case PROCESSOR_ARCHITECTURE_IA32_ON_WIN64: return "x86_wow64";
-    default: return "unknown";
-    }
-}
-
-/* Return the Windows-specific canonical host name. */
-static const char *
-win32_canonical_host(apr_pool_t *pool)
-{
-  SYSTEM_INFO sysinfo;
-  SYSTEM_INFO local_sysinfo;
-  OSVERSIONINFOEXW osinfo;
-
-  if (system_info(&sysinfo, &local_sysinfo, &osinfo))
-    {
-      const char *arch = processor_name(&local_sysinfo);
-      const char *machine = processor_name(&sysinfo);
-      const char *vendor = "microsoft";
-      const char *sysname = "windows";
-      const char *sysver = apr_psprintf(pool, "%u.%u.%u",
-                                        (unsigned int)osinfo.dwMajorVersion,
-                                        (unsigned int)osinfo.dwMinorVersion,
-                                        (unsigned int)osinfo.dwBuildNumber);
-
-      if (sysinfo.wProcessorArchitecture
-          == local_sysinfo.wProcessorArchitecture)
-        return apr_psprintf(pool, "%s-%s-%s%s",
-                            machine, vendor, sysname, sysver);
-      return apr_psprintf(pool, "%s/%s-%s-%s%s",
-                          arch, machine, vendor, sysname, sysver);
-    }
-
-  return "unknown-microsoft-windows";
-}
-
-/* Convert a Unicode string to UTF-8. */
-static char *
-wcs_to_utf8(const wchar_t *wcs, apr_pool_t *pool)
-{
-  const int bufsize = WideCharToMultiByte(CP_UTF8, 0, wcs, -1,
-                                          NULL, 0, NULL, NULL);
-  if (bufsize > 0)
-    {
-      char *const utf8 = apr_palloc(pool, bufsize + 1);
-      WideCharToMultiByte(CP_UTF8, 0, wcs, -1, utf8, bufsize, NULL, NULL);
-      return utf8;
-    }
-  return NULL;
-}
-
-/* Query the value called NAME of the registry key HKEY. */
-static char *
-registry_value(HKEY hkey, wchar_t *name, apr_pool_t *pool)
-{
-  DWORD size;
-  wchar_t *value;
-
-  if (RegQueryValueExW(hkey, name, NULL, NULL, NULL, &size))
-    return NULL;
-
-  value = apr_palloc(pool, size + sizeof *value);
-  if (RegQueryValueExW(hkey, name, NULL, NULL, (void*)value, &size))
-    return NULL;
-  value[size / sizeof *value] = 0;
-  return wcs_to_utf8(value, pool);
-}
-
-/* Try to glean the Windows release name and associated info from the
-   registry. Failing that, construct a release name from the version
-   info. */
-static const char *
-win32_release_name(apr_pool_t *pool)
-{
-  SYSTEM_INFO sysinfo;
-  OSVERSIONINFOEXW osinfo;
-  HKEY hkcv;
-
-  if (!system_info(&sysinfo, NULL, &osinfo))
-    return NULL;
-
-  if (!RegOpenKeyExW(HKEY_LOCAL_MACHINE,
-                     L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
-                     0, KEY_QUERY_VALUE, &hkcv))
-    {
-      const char *release = registry_value(hkcv, L"ProductName", pool);
-      const char *spack = registry_value(hkcv, L"CSDVersion", pool);
-      const char *curver = registry_value(hkcv, L"CurrentVersion", pool);
-      const char *curtype = registry_value(hkcv, L"CurrentType", pool);
-      const char *install = registry_value(hkcv, L"InstallationType", pool);
-      const char *curbuild = registry_value(hkcv, L"CurrentBuildNumber", pool);
-
-      if (!spack && *osinfo.szCSDVersion)
-        spack = wcs_to_utf8(osinfo.szCSDVersion, pool);
-
-      if (!curbuild)
-        curbuild = registry_value(hkcv, L"CurrentBuild", pool);
-
-      if (release || spack || curver || curtype || curbuild)
-        {
-          const char *bootinfo = "";
-          if (curver || install || curtype)
-            {
-              bootinfo = apr_psprintf(pool, "[%s%s%s%s%s]",
-                                      (curver ? curver : ""),
-                                      (install ? (curver ? " " : "") : ""),
-                                      (install ? install : ""),
-                                      (curtype
-                                       ? (curver||install ? " " : "")
-                                       : ""),
-                                      (curtype ? curtype : ""));
-            }
-
-          return apr_psprintf(pool, "%s%s%s%s%s%s%s",
-                              (release ? release : ""),
-                              (spack ? (release ? ", " : "") : ""),
-                              (spack ? spack : ""),
-                              (curbuild
-                               ? (release||spack ? ", build " : "build ")
-                               : ""),
-                              (curbuild ? curbuild : ""),
-                              (bootinfo
-                               ? (release||spack||curbuild ? " " : "")
-                               : ""),
-                              (bootinfo ? bootinfo : ""));
-        }
-    }
-
-  if (*osinfo.szCSDVersion)
-    {
-      const char *servicepack = wcs_to_utf8(osinfo.szCSDVersion, pool);
-
-      if (servicepack)
-        return apr_psprintf(pool, "Windows NT %u.%u, %s, build %u",
-                            (unsigned int)osinfo.dwMajorVersion,
-                            (unsigned int)osinfo.dwMinorVersion,
-                            servicepack,
-                            (unsigned int)osinfo.dwBuildNumber);
-
-      /* Assume wServicePackMajor > 0 if szCSDVersion is not empty */
-      if (osinfo.wServicePackMinor)
-        return apr_psprintf(pool, "Windows NT %u.%u SP%u.%u, build %u",
-                            (unsigned int)osinfo.dwMajorVersion,
-                            (unsigned int)osinfo.dwMinorVersion,
-                            (unsigned int)osinfo.wServicePackMajor,
-                            (unsigned int)osinfo.wServicePackMinor,
-                            (unsigned int)osinfo.dwBuildNumber);
-
-      return apr_psprintf(pool, "Windows NT %u.%u SP%u, build %u",
-                          (unsigned int)osinfo.dwMajorVersion,
-                          (unsigned int)osinfo.dwMinorVersion,
-                          (unsigned int)osinfo.wServicePackMajor,
-                          (unsigned int)osinfo.dwBuildNumber);
-    }
-
-  return apr_psprintf(pool, "Windows NT %u.%u, build %u",
-                      (unsigned int)osinfo.dwMajorVersion,
-                      (unsigned int)osinfo.dwMinorVersion,
-                      (unsigned int)osinfo.dwBuildNumber);
-}
-
-
-/* Get a list of handles of shared libs loaded by the current
-   process. Returns a NULL-terminated array alocated from POOL. */
-static HMODULE *
-enum_loaded_modules(apr_pool_t *pool)
-{
-  HANDLE current = GetCurrentProcess();
-  HMODULE dummy[1];
-  HMODULE *handles;
-  DWORD size;
-
-  if (!EnumProcessModules(current, dummy, sizeof(dummy), &size))
-    return NULL;
-
-  handles = apr_palloc(pool, size + sizeof *handles);
-  if (!EnumProcessModules(current, handles, size, &size))
-    return NULL;
-  handles[size / sizeof *handles] = NULL;
-  return handles;
-}
-
-/* Find the version number, if any, embedded in FILENAME. */
-static const char *
-file_version_number(const wchar_t *filename, apr_pool_t *pool)
-{
-  VS_FIXEDFILEINFO info;
-  unsigned int major, minor, micro, nano;
-  void *data;
-  DWORD data_size = GetFileVersionInfoSizeW(filename, NULL);
-  void *vinfo;
-  UINT vinfo_size;
-
-  if (!data_size)
-    return NULL;
-
-  data = apr_palloc(pool, data_size);
-  if (!GetFileVersionInfoW(filename, 0, data_size, data))
-    return NULL;
-
-  if (!VerQueryValueW(data, L"\\", &vinfo, &vinfo_size))
-    return NULL;
-
-  if (vinfo_size != sizeof info)
-    return NULL;
-
-  memcpy(&info, vinfo, sizeof info);
-  major = (info.dwFileVersionMS >> 16) & 0xFFFF;
-  minor = info.dwFileVersionMS & 0xFFFF;
-  micro = (info.dwFileVersionLS >> 16) & 0xFFFF;
-  nano = info.dwFileVersionLS & 0xFFFF;
-
-  if (!nano)
-    {
-      if (!micro)
-        return apr_psprintf(pool, "%u.%u", major, minor);
-      else
-        return apr_psprintf(pool, "%u.%u.%u", major, minor, micro);
-    }
-  return apr_psprintf(pool, "%u.%u.%u.%u", major, minor, micro, nano);
-}
-
-/* List the shared libraries loaded by the current process. */
-static const char *
-win32_shared_libs(apr_pool_t *pool)
-{
-  wchar_t buffer[MAX_PATH + 1];
-  HMODULE *handles = enum_loaded_modules(pool);
-  char *libinfo = "";
-  HMODULE *module;
-
-  for (module = handles; module && *module; ++module)
-    {
-      const char *filename;
-      const char *version;
-      if (GetModuleFileNameW(*module, buffer, MAX_PATH))
-        {
-          buffer[MAX_PATH] = 0;
-          version = file_version_number(buffer, pool);
-          filename = wcs_to_utf8(buffer, pool);
-          if (filename)
-            {
-              char *truename;
-              if (0 == apr_filepath_merge(&truename, "", filename,
-                                          APR_FILEPATH_NATIVE
-                                          | APR_FILEPATH_TRUENAME,
-                                          pool))
-                filename = truename;
-              if (version)
-                libinfo = apr_pstrcat(pool, libinfo, "  - ", filename,
-                                      "   (", version, ")\n", NULL);
-              else
-                libinfo = apr_pstrcat(pool, libinfo, "  - ", filename,
-                                      "\n", NULL);
-            }
-        }
-    }
-
-  if (*libinfo)
-    return libinfo;
-  return NULL;
-}
-#endif /* WIN32 */
-
-#ifdef SVN_HAVE_MACOS_PLIST
-/* Load the SystemVersion.plist or ServerVersion.plist file into a
-   property list. Set SERVER to TRUE if the file read was
-   ServerVersion.plist. */
-static CFDictionaryRef
-system_version_plist(svn_boolean_t *server, apr_pool_t *pool)
-{
-  static const UInt8 server_version[] =
-    "/System/Library/CoreServices/ServerVersion.plist";
-  static const UInt8 system_version[] =
-    "/System/Library/CoreServices/SystemVersion.plist";
-
-  CFPropertyListRef plist = NULL;
-  CFDataRef resource = NULL;
-  CFStringRef errstr = NULL;
-  CFURLRef url = NULL;
-  SInt32 errcode;
-
-  url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault,
-                                                server_version,
-                                                sizeof(server_version) - 1,
-                                                FALSE);
-  if (!url)
-    return NULL;
-
-  if (!CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault,
-                                                url, &resource,
-                                                NULL, NULL, &errcode))
-    {
-      CFRelease(url);
-      url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault,
-                                                    system_version,
-                                                    sizeof(system_version) - 1,
-                                                    FALSE);
-      if (!url)
-        return NULL;
-
-      if (!CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault,
-                                                    url, &resource,
-                                                    NULL, NULL, &errcode))
-        {
-          CFRelease(url);
-          return NULL;
-        }
-      else
-        {
-          CFRelease(url);
-          *server = FALSE;
-        }
-    }
-  else
-    {
-      CFRelease(url);
-      *server = TRUE;
-    }
-
-  /* ### CFPropertyListCreateFromXMLData is obsolete, but its
-         replacement CFPropertyListCreateWithData is only available
-         from Mac OS 1.6 onward. */
-  plist = CFPropertyListCreateFromXMLData(kCFAllocatorDefault, resource,
-                                          kCFPropertyListImmutable,
-                                          &errstr);
-  if (resource)
-    CFRelease(resource);
-  if (errstr)
-    CFRelease(errstr);
-
-  if (CFDictionaryGetTypeID() != CFGetTypeID(plist))
-    {
-      /* Oops ... this really should be a dict. */
-      CFRelease(plist);
-      return NULL;
-    }
-
-  return plist;
-}
-
-/* Return the value for KEY from PLIST, or NULL if not available. */
-static const char *
-value_from_dict(CFDictionaryRef plist, CFStringRef key, apr_pool_t *pool)
-{
-  CFStringRef valref;
-  CFIndex bufsize;
-  const void *valptr;
-  const char *value;
-
-  if (!CFDictionaryGetValueIfPresent(plist, key, &valptr))
-    return NULL;
-
-  valref = valptr;
-  if (CFStringGetTypeID() != CFGetTypeID(valref))
-    return NULL;
-
-  value = CFStringGetCStringPtr(valref, kCFStringEncodingUTF8);
-  if (value)
-    return apr_pstrdup(pool, value);
-
-  bufsize =  5 * CFStringGetLength(valref) + 1;
-  value = apr_palloc(pool, bufsize);
-  if (!CFStringGetCString(valref, (char*)value, bufsize,
-                          kCFStringEncodingUTF8))
-    value = NULL;
-
-  return value;
-}
-
-/* Return the commercial name of the OS, given the version number in
-   a format that matches the regular expression /^10\.\d+(\..*)?$/ */
-static const char *
-release_name_from_version(const char *osver)
-{
-  char *end = NULL;
-  unsigned long num = strtoul(osver, &end, 10);
-
-  if (!end || *end != '.' || num != 10)
-    return NULL;
-
-  osver = end + 1;
-  end = NULL;
-  num = strtoul(osver, &end, 10);
-  if (!end || (*end && *end != '.'))
-    return NULL;
-
-  /* See http://en.wikipedia.org/wiki/History_of_OS_X#Release_timeline */
-  switch(num)
-    {
-    case 0: return "Cheetah";
-    case 1: return "Puma";
-    case 2: return "Jaguar";
-    case 3: return "Panther";
-    case 4: return "Tiger";
-    case 5: return "Leopard";
-    case 6: return "Snow Leopard";
-    case 7: return "Lion";
-    case 8: return "Mountain Lion";
-    }
-
-  return NULL;
-}
-
-static const char *
-macos_release_name(apr_pool_t *pool)
-{
-  svn_boolean_t server;
-  CFDictionaryRef plist = system_version_plist(&server, pool);
-
-  if (plist)
-    {
-      const char *osname = value_from_dict(plist, CFSTR("ProductName"), pool);
-      const char *osver = value_from_dict(plist,
-                                          CFSTR("ProductUserVisibleVersion"),
-                                          pool);
-      const char *build = value_from_dict(plist,
-                                          CFSTR("ProductBuildVersion"),
-                                          pool);
-      const char *release;
-
-      if (!osver)
-        osver = value_from_dict(plist, CFSTR("ProductVersion"), pool);
-      release = release_name_from_version(osver);
-
-      CFRelease(plist);
-      return apr_psprintf(pool, "%s%s%s%s%s%s%s%s",
-                          (osname ? osname : ""),
-                          (osver ? (osname ? " " : "") : ""),
-                          (osver ? osver : ""),
-                          (release ? (osname||osver ? " " : "") : ""),
-                          (release ? release : ""),
-                          (build
-                           ? (osname||osver||release ? ", " : "")
-                           : ""),
-                          (build
-                           ? (server ? "server build " : "build ")
-                           : ""),
-                          (build ? build : ""));
-    }
-
-  return NULL;
-}
-#endif  /* SVN_HAVE_MACOS_PLIST */
+/*
+ * sysinfo.c :  information about the running system
+ *
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you under the Apache License, Version 2.0 (the
+ *    "License"); you may not use this file except in compliance
+ *    with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ * ====================================================================
+ */
+
+
+
+#ifdef WIN32
+#define WIN32_LEAN_AND_MEAN
+#define PSAPI_VERSION 1
+#include <windows.h>
+#include <psapi.h>
+#endif
+
+#define APR_WANT_STRFUNC
+#include <apr_want.h>
+
+#include <apr_lib.h>
+#include <apr_pools.h>
+#include <apr_file_info.h>
+#include <apr_signal.h>
+#include <apr_strings.h>
+#include <apr_thread_proc.h>
+#include <apr_version.h>
+#include <apu_version.h>
+
+#include "svn_ctype.h"
+#include "svn_error.h"
+#include "svn_io.h"
+#include "svn_string.h"
+#include "svn_utf.h"
+#include "svn_version.h"
+
+#include "private/svn_sqlite.h"
+
+#include "sysinfo.h"
+#include "svn_private_config.h"
+
+#if HAVE_SYS_UTSNAME_H
+#include <sys/utsname.h>
+#endif
+
+#ifdef SVN_HAVE_MACOS_PLIST
+#include <CoreFoundation/CoreFoundation.h>
+#endif
+
+#ifdef SVN_HAVE_MACHO_ITERATE
+#include <mach-o/dyld.h>
+#include <mach-o/loader.h>
+#endif
+
+#if HAVE_UNAME
+static const char *canonical_host_from_uname(apr_pool_t *pool);
+# ifndef SVN_HAVE_MACOS_PLIST
+static const char *release_name_from_uname(apr_pool_t *pool);
+# endif
+#endif
+
+#ifdef WIN32
+static const char *win32_canonical_host(apr_pool_t *pool);
+static const char *win32_release_name(apr_pool_t *pool);
+static const apr_array_header_t *win32_shared_libs(apr_pool_t *pool);
+#endif /* WIN32 */
+
+#ifdef SVN_HAVE_MACOS_PLIST
+static const char *macos_release_name(apr_pool_t *pool);
+#endif
+
+#ifdef SVN_HAVE_MACHO_ITERATE
+static const apr_array_header_t *macos_shared_libs(apr_pool_t *pool);
+#endif
+
+
+#if __linux__
+static const char *linux_release_name(apr_pool_t *pool);
+#endif
+
+const char *
+svn_sysinfo__canonical_host(apr_pool_t *pool)
+{
+#ifdef WIN32
+  return win32_canonical_host(pool);
+#elif HAVE_UNAME
+  return canonical_host_from_uname(pool);
+#else
+  return "unknown-unknown-unknown";
+#endif
+}
+
+
+const char *
+svn_sysinfo__release_name(apr_pool_t *pool)
+{
+#ifdef WIN32
+  return win32_release_name(pool);
+#elif defined(SVN_HAVE_MACOS_PLIST)
+  return macos_release_name(pool);
+#elif __linux__
+  return linux_release_name(pool);
+#elif HAVE_UNAME
+  return release_name_from_uname(pool);
+#else
+  return NULL;
+#endif
+}
+
+const apr_array_header_t *
+svn_sysinfo__linked_libs(apr_pool_t *pool)
+{
+  svn_version_ext_linked_lib_t *lib;
+  apr_array_header_t *array = apr_array_make(pool, 3, sizeof(*lib));
+
+  lib = &APR_ARRAY_PUSH(array, svn_version_ext_linked_lib_t);
+  lib->name = "APR";
+  lib->compiled_version = APR_VERSION_STRING;
+  lib->runtime_version = apr_pstrdup(pool, apr_version_string());
+
+  lib = &APR_ARRAY_PUSH(array, svn_version_ext_linked_lib_t);
+  lib->name = "APR-Util";
+  lib->compiled_version = APU_VERSION_STRING;
+  lib->runtime_version = apr_pstrdup(pool, apu_version_string());
+
+  lib = &APR_ARRAY_PUSH(array, svn_version_ext_linked_lib_t);
+  lib->name = "SQLite";
+  lib->compiled_version = apr_pstrdup(pool, svn_sqlite__compiled_version());
+#ifdef SVN_SQLITE_INLINE
+  lib->runtime_version = NULL;
+#else
+  lib->runtime_version = apr_pstrdup(pool, svn_sqlite__runtime_version());
+#endif
+
+  return array;
+}
+
+const apr_array_header_t *
+svn_sysinfo__loaded_libs(apr_pool_t *pool)
+{
+#ifdef WIN32
+  return win32_shared_libs(pool);
+#elif defined(SVN_HAVE_MACHO_ITERATE)
+  return macos_shared_libs(pool);
+#else
+  return NULL;
+#endif
+}
+
+
+#if HAVE_UNAME
+static const char*
+canonical_host_from_uname(apr_pool_t *pool)
+{
+  const char *machine = "unknown";
+  const char *vendor = "unknown";
+  const char *sysname = "unknown";
+  const char *sysver = "";
+  struct utsname info;
+
+  if (0 <= uname(&info))
+    {
+      svn_error_t *err;
+      const char *tmp;
+
+      err = svn_utf_cstring_to_utf8(&tmp, info.machine, pool);
+      if (err)
+        svn_error_clear(err);
+      else
+        machine = tmp;
+
+      err = svn_utf_cstring_to_utf8(&tmp, info.sysname, pool);
+      if (err)
+        svn_error_clear(err);
+      else
+        {
+          char *lwr = apr_pstrdup(pool, tmp);
+          char *it = lwr;
+          while (*it)
+            {
+              if (svn_ctype_isupper(*it))
+                *it = apr_tolower(*it);
+              ++it;
+            }
+          sysname = lwr;
+        }
+
+      if (0 == strcmp(sysname, "darwin"))
+        vendor = "apple";
+      if (0 == strcmp(sysname, "linux"))
+        sysver = "-gnu";
+      else
+        {
+          err = svn_utf_cstring_to_utf8(&tmp, info.release, pool);
+          if (err)
+            svn_error_clear(err);
+          else
+            {
+              apr_size_t n = strspn(tmp, ".0123456789");
+              if (n > 0)
+                {
+                  char *ver = apr_pstrdup(pool, tmp);
+                  ver[n] = 0;
+                  sysver = ver;
+                }
+              else
+                sysver = tmp;
+            }
+        }
+    }
+
+  return apr_psprintf(pool, "%s-%s-%s%s", machine, vendor, sysname, sysver);
+}
+
+# ifndef SVN_HAVE_MACOS_PLIST
+/* Generate a release name from the uname(3) info, effectively
+   returning "`uname -s` `uname -r`". */
+static const char *
+release_name_from_uname(apr_pool_t *pool)
+{
+  struct utsname info;
+  if (0 <= uname(&info))
+    {
+      svn_error_t *err;
+      const char *sysname;
+      const char *sysver;
+
+      err = svn_utf_cstring_to_utf8(&sysname, info.sysname, pool);
+      if (err)
+        {
+          sysname = NULL;
+          svn_error_clear(err);
+        }
+
+
+      err = svn_utf_cstring_to_utf8(&sysver, info.release, pool);
+      if (err)
+        {
+          sysver = NULL;
+          svn_error_clear(err);
+        }
+
+      if (sysname || sysver)
+        {
+          return apr_psprintf(pool, "%s%s%s",
+                              (sysname ? sysname : ""),
+                              (sysver ? (sysname ? " " : "") : ""),
+                              (sysver ? sysver : ""));
+        }
+    }
+  return NULL;
+}
+# endif  /* !SVN_HAVE_MACOS_PLIST */
+#endif  /* HAVE_UNAME */
+
+
+#if __linux__
+/* Split a stringbuf into a key/value pair.
+   Return the key, leaving the striped value in the stringbuf. */
+static const char *
+stringbuf_split_key(svn_stringbuf_t *buffer, char delim)
+{
+  char *key;
+  char *end;
+
+  end = strchr(buffer->data, delim);
+  if (!end)
+    return NULL;
+
+  svn_stringbuf_strip_whitespace(buffer);
+  key = buffer->data;
+  end = strchr(key, delim);
+  *end = '\0';
+  buffer->len = 1 + end - key;
+  buffer->data = end + 1;
+  svn_stringbuf_strip_whitespace(buffer);
+
+  return key;
+}
+
+/* Parse `/usr/bin/lsb_rlease --all` */
+static const char *
+lsb_release(apr_pool_t *pool)
+{
+  static const char *const args[3] =
+    {
+      "/usr/bin/lsb_release",
+      "--all",
+      NULL
+    };
+
+  const char *distributor = NULL;
+  const char *description = NULL;
+  const char *release = NULL;
+  const char *codename = NULL;
+
+  apr_proc_t lsbproc;
+  svn_stream_t *lsbinfo;
+  svn_error_t *err;
+
+  /* Run /usr/bin/lsb_release --all < /dev/null 2>/dev/null */
+  {
+    apr_file_t *stdin_handle;
+    apr_file_t *stdout_handle;
+
+    err = svn_io_file_open(&stdin_handle, SVN_NULL_DEVICE_NAME,
+                           APR_READ, APR_OS_DEFAULT, pool);
+    if (!err)
+      err = svn_io_file_open(&stdout_handle, SVN_NULL_DEVICE_NAME,
+                             APR_WRITE, APR_OS_DEFAULT, pool);
+    if (!err)
+      err = svn_io_start_cmd3(&lsbproc, NULL, args[0], args, NULL, FALSE,
+                              FALSE, stdin_handle,
+                              TRUE, NULL,
+                              FALSE, stdout_handle,
+                              pool);
+    if (err)
+      {
+        svn_error_clear(err);
+        return NULL;
+      }
+  }
+
+  /* Parse the output and try to populate the  */
+  lsbinfo = svn_stream_from_aprfile2(lsbproc.out, TRUE, pool);
+  if (lsbinfo)
+    {
+      for (;;)
+        {
+          svn_boolean_t eof = FALSE;
+          svn_stringbuf_t *line;
+          const char *key;
+
+          err = svn_stream_readline(lsbinfo, &line, "\n", &eof, pool);
+          if (err || eof)
+            break;
+
+          key = stringbuf_split_key(line, ':');
+          if (!key)
+            continue;
+
+          if (0 == svn_cstring_casecmp(key, "Distributor ID"))
+            distributor = line->data;
+          else if (0 == svn_cstring_casecmp(key, "Description"))
+            description = line->data;
+          else if (0 == svn_cstring_casecmp(key, "Release"))
+            release = line->data;
+          else if (0 == svn_cstring_casecmp(key, "Codename"))
+            codename = line->data;
+        }
+      err = svn_error_compose_create(err,
+                                     svn_stream_close(lsbinfo));
+      if (err)
+        {
+          svn_error_clear(err);
+          apr_proc_kill(&lsbproc, SIGKILL);
+          return NULL;
+        }
+    }
+
+  /* Reap the child process */
+  err = svn_io_wait_for_cmd(&lsbproc, "", NULL, NULL, pool);
+  if (err)
+    {
+      svn_error_clear(err);
+      return NULL;
+    }
+
+  if (description)
+    return apr_psprintf(pool, "%s%s%s%s", description,
+                        (codename ? " (" : ""),
+                        (codename ? codename : ""),
+                        (codename ? ")" : ""));
+  if (distributor)
+    return apr_psprintf(pool, "%s%s%s%s%s%s", distributor,
+                        (release ? " " : ""),
+                        (release ? release : ""),
+                        (codename ? " (" : ""),
+                        (codename ? codename : ""),
+                        (codename ? ")" : ""));
+
+  return NULL;
+}
+
+/* Read the whole contents of a file. */
+static svn_stringbuf_t *
+read_file_contents(const char *filename, apr_pool_t *pool)
+{
+  svn_error_t *err;
+  svn_stringbuf_t *buffer;
+
+  err = svn_stringbuf_from_file2(&buffer, filename, pool);
+  if (err)
+    {
+      svn_error_clear(err);
+      return NULL;
+    }
+
+  return buffer;
+}
+
+/* Strip everything but the first line from a stringbuf. */
+static void
+stringbuf_first_line_only(svn_stringbuf_t *buffer)
+{
+  char *eol = strchr(buffer->data, '\n');
+  if (eol)
+    {
+      *eol = '\0';
+      buffer->len = 1 + eol - buffer->data;
+    }
+  svn_stringbuf_strip_whitespace(buffer);
+}
+
+/* Look at /etc/redhat_release to detect RHEL/Fedora/CentOS. */
+static const char *
+redhat_release(apr_pool_t *pool)
+{
+  svn_stringbuf_t *buffer = read_file_contents("/etc/redhat-release", pool);
+  if (buffer)
+    {
+      stringbuf_first_line_only(buffer);
+      return buffer->data;
+    }
+  return NULL;
+}
+
+/* Look at /etc/SuSE-release to detect non-LSB SuSE. */
+static const char *
+suse_release(apr_pool_t *pool)
+{
+  const char *release = NULL;
+  const char *codename = NULL;
+
+  svn_stringbuf_t *buffer = read_file_contents("/etc/SuSE-release", pool);
+  svn_stringbuf_t *line;
+  svn_stream_t *stream;
+  svn_boolean_t eof;
+  svn_error_t *err;
+  if (!buffer)
+      return NULL;
+
+  stream = svn_stream_from_stringbuf(buffer, pool);
+  err = svn_stream_readline(stream, &line, "\n", &eof, pool);
+  if (err || eof)
+    {
+      svn_error_clear(err);
+      return NULL;
+    }
+
+  svn_stringbuf_strip_whitespace(line);
+  release = line->data;
+
+  for (;;)
+    {
+      const char *key;
+
+      err = svn_stream_readline(stream, &line, "\n", &eof, pool);
+      if (err || eof)
+        {
+          svn_error_clear(err);
+          break;
+        }
+
+      key = stringbuf_split_key(line, '=');
+      if (!key)
+        continue;
+
+      if (0 == strncmp(key, "CODENAME", 8))
+        codename = line->data;
+    }
+
+  return apr_psprintf(pool, "%s%s%s%s",
+                      release,
+                      (codename ? " (" : ""),
+                      (codename ? codename : ""),
+                      (codename ? ")" : ""));
+}
+
+/* Look at /etc/debian_version to detect non-LSB Debian. */
+static const char *
+debian_release(apr_pool_t *pool)
+{
+  svn_stringbuf_t *buffer = read_file_contents("/etc/debian_version", pool);
+  if (!buffer)
+      return NULL;
+
+  stringbuf_first_line_only(buffer);
+  return apr_pstrcat(pool, "Debian ", buffer->data, NULL);
+}
+
+/* Try to find the Linux distribution name, or return info from uname. */
+static const char *
+linux_release_name(apr_pool_t *pool)
+{
+  const char *uname_release = release_name_from_uname(pool);
+
+  /* Try anything that has /usr/bin/lsb_release.
+     Covers, for example, Debian, Ubuntu and SuSE.  */
+  const char *release_name = lsb_release(pool);
+
+  /* Try RHEL/Fedora/CentOS */
+  if (!release_name)
+    release_name = redhat_release(pool);
+
+  /* Try Non-LSB SuSE */
+  if (!release_name)
+    release_name = suse_release(pool);
+
+  /* Try non-LSB Debian */
+  if (!release_name)
+    release_name = debian_release(pool);
+
+  if (!release_name)
+    return uname_release;
+
+  if (!uname_release)
+    return release_name;
+
+  return apr_psprintf(pool, "%s [%s]", release_name, uname_release);
+}
+#endif /* __linux__ */
+
+
+#ifdef WIN32
+typedef DWORD (WINAPI *FNGETNATIVESYSTEMINFO)(LPSYSTEM_INFO);
+typedef BOOL (WINAPI *FNENUMPROCESSMODULES) (HANDLE, HMODULE, DWORD, LPDWORD);
+
+/* Get system and version info, and try to tell the difference
+   between the native system type and the runtime environment of the
+   current process. Populate results in SYSINFO, LOCAL_SYSINFO
+   (optional) and OSINFO. */
+static BOOL
+system_info(SYSTEM_INFO *sysinfo,
+            SYSTEM_INFO *local_sysinfo,
+            OSVERSIONINFOEXW *osinfo)
+{
+  FNGETNATIVESYSTEMINFO GetNativeSystemInfo_ = (FNGETNATIVESYSTEMINFO)
+    GetProcAddress(GetModuleHandleA("kernel32.dll"), "GetNativeSystemInfo");
+
+  ZeroMemory(sysinfo, sizeof *sysinfo);
+  if (local_sysinfo)
+    {
+      ZeroMemory(local_sysinfo, sizeof *local_sysinfo);
+      GetSystemInfo(local_sysinfo);
+      if (GetNativeSystemInfo_)
+        GetNativeSystemInfo_(sysinfo);
+      else
+        memcpy(sysinfo, local_sysinfo, sizeof *sysinfo);
+    }
+  else
+    GetSystemInfo(sysinfo);
+
+  ZeroMemory(osinfo, sizeof *osinfo);
+  osinfo->dwOSVersionInfoSize = sizeof *osinfo;
+  if (!GetVersionExW((LPVOID)osinfo))
+    return FALSE;
+
+  return TRUE;
+}
+
+/* Map the proccessor type from SYSINFO to a string. */
+static const char *
+processor_name(SYSTEM_INFO *sysinfo)
+{
+  switch (sysinfo->wProcessorArchitecture)
+    {
+    case PROCESSOR_ARCHITECTURE_AMD64:         return "x86_64";
+    case PROCESSOR_ARCHITECTURE_IA64:          return "ia64";
+    case PROCESSOR_ARCHITECTURE_INTEL:         return "x86";
+    case PROCESSOR_ARCHITECTURE_MIPS:          return "mips";
+    case PROCESSOR_ARCHITECTURE_ALPHA:         return "alpha32";
+    case PROCESSOR_ARCHITECTURE_PPC:           return "powerpc";
+    case PROCESSOR_ARCHITECTURE_SHX:           return "shx";
+    case PROCESSOR_ARCHITECTURE_ARM:           return "arm";
+    case PROCESSOR_ARCHITECTURE_ALPHA64:       return "alpha";
+    case PROCESSOR_ARCHITECTURE_MSIL:          return "msil";
+    case PROCESSOR_ARCHITECTURE_IA32_ON_WIN64: return "x86_wow64";
+    default: return "unknown";
+    }
+}
+
+/* Return the Windows-specific canonical host name. */
+static const char *
+win32_canonical_host(apr_pool_t *pool)
+{
+  SYSTEM_INFO sysinfo;
+  SYSTEM_INFO local_sysinfo;
+  OSVERSIONINFOEXW osinfo;
+
+  if (system_info(&sysinfo, &local_sysinfo, &osinfo))
+    {
+      const char *arch = processor_name(&local_sysinfo);
+      const char *machine = processor_name(&sysinfo);
+      const char *vendor = "microsoft";
+      const char *sysname = "windows";
+      const char *sysver = apr_psprintf(pool, "%u.%u.%u",
+                                        (unsigned int)osinfo.dwMajorVersion,
+                                        (unsigned int)osinfo.dwMinorVersion,
+                                        (unsigned int)osinfo.dwBuildNumber);
+
+      if (sysinfo.wProcessorArchitecture
+          == local_sysinfo.wProcessorArchitecture)
+        return apr_psprintf(pool, "%s-%s-%s%s",
+                            machine, vendor, sysname, sysver);
+      return apr_psprintf(pool, "%s/%s-%s-%s%s",
+                          arch, machine, vendor, sysname, sysver);
+    }
+
+  return "unknown-microsoft-windows";
+}
+
+/* Convert a Unicode string to UTF-8. */
+static char *
+wcs_to_utf8(const wchar_t *wcs, apr_pool_t *pool)
+{
+  const int bufsize = WideCharToMultiByte(CP_UTF8, 0, wcs, -1,
+                                          NULL, 0, NULL, NULL);
+  if (bufsize > 0)
+    {
+      char *const utf8 = apr_palloc(pool, bufsize + 1);
+      WideCharToMultiByte(CP_UTF8, 0, wcs, -1, utf8, bufsize, NULL, NULL);
+      return utf8;
+    }
+  return NULL;
+}
+
+/* Query the value called NAME of the registry key HKEY. */
+static char *
+registry_value(HKEY hkey, wchar_t *name, apr_pool_t *pool)
+{
+  DWORD size;
+  wchar_t *value;
+
+  if (RegQueryValueExW(hkey, name, NULL, NULL, NULL, &size))
+    return NULL;
+
+  value = apr_palloc(pool, size + sizeof *value);
+  if (RegQueryValueExW(hkey, name, NULL, NULL, (void*)value, &size))
+    return NULL;
+  value[size / sizeof *value] = 0;
+  return wcs_to_utf8(value, pool);
+}
+
+/* Try to glean the Windows release name and associated info from the
+   registry. Failing that, construct a release name from the version
+   info. */
+static const char *
+win32_release_name(apr_pool_t *pool)
+{
+  SYSTEM_INFO sysinfo;
+  OSVERSIONINFOEXW osinfo;
+  HKEY hkcv;
+
+  if (!system_info(&sysinfo, NULL, &osinfo))
+    return NULL;
+
+  if (!RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+                     L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
+                     0, KEY_QUERY_VALUE, &hkcv))
+    {
+      const char *release = registry_value(hkcv, L"ProductName", pool);
+      const char *spack = registry_value(hkcv, L"CSDVersion", pool);
+      const char *curver = registry_value(hkcv, L"CurrentVersion", pool);
+      const char *curtype = registry_value(hkcv, L"CurrentType", pool);
+      const char *install = registry_value(hkcv, L"InstallationType", pool);
+      const char *curbuild = registry_value(hkcv, L"CurrentBuildNumber", pool);
+
+      if (!spack && *osinfo.szCSDVersion)
+        spack = wcs_to_utf8(osinfo.szCSDVersion, pool);
+
+      if (!curbuild)
+        curbuild = registry_value(hkcv, L"CurrentBuild", pool);
+
+      if (release || spack || curver || curtype || curbuild)
+        {
+          const char *bootinfo = "";
+          if (curver || install || curtype)
+            {
+              bootinfo = apr_psprintf(pool, "[%s%s%s%s%s]",
+                                      (curver ? curver : ""),
+                                      (install ? (curver ? " " : "") : ""),
+                                      (install ? install : ""),
+                                      (curtype
+                                       ? (curver||install ? " " : "")
+                                       : ""),
+                                      (curtype ? curtype : ""));
+            }
+
+          return apr_psprintf(pool, "%s%s%s%s%s%s%s",
+                              (release ? release : ""),
+                              (spack ? (release ? ", " : "") : ""),
+                              (spack ? spack : ""),
+                              (curbuild
+                               ? (release||spack ? ", build " : "build ")
+                               : ""),
+                              (curbuild ? curbuild : ""),
+                              (bootinfo
+                               ? (release||spack||curbuild ? " " : "")
+                               : ""),
+                              (bootinfo ? bootinfo : ""));
+        }
+    }
+
+  if (*osinfo.szCSDVersion)
+    {
+      const char *servicepack = wcs_to_utf8(osinfo.szCSDVersion, pool);
+
+      if (servicepack)
+        return apr_psprintf(pool, "Windows NT %u.%u, %s, build %u",
+                            (unsigned int)osinfo.dwMajorVersion,
+                            (unsigned int)osinfo.dwMinorVersion,
+                            servicepack,
+                            (unsigned int)osinfo.dwBuildNumber);
+
+      /* Assume wServicePackMajor > 0 if szCSDVersion is not empty */
+      if (osinfo.wServicePackMinor)
+        return apr_psprintf(pool, "Windows NT %u.%u SP%u.%u, build %u",
+                            (unsigned int)osinfo.dwMajorVersion,
+                            (unsigned int)osinfo.dwMinorVersion,
+                            (unsigned int)osinfo.wServicePackMajor,
+                            (unsigned int)osinfo.wServicePackMinor,
+                            (unsigned int)osinfo.dwBuildNumber);
+
+      return apr_psprintf(pool, "Windows NT %u.%u SP%u, build %u",
+                          (unsigned int)osinfo.dwMajorVersion,
+                          (unsigned int)osinfo.dwMinorVersion,
+                          (unsigned int)osinfo.wServicePackMajor,
+                          (unsigned int)osinfo.dwBuildNumber);
+    }
+
+  return apr_psprintf(pool, "Windows NT %u.%u, build %u",
+                      (unsigned int)osinfo.dwMajorVersion,
+                      (unsigned int)osinfo.dwMinorVersion,
+                      (unsigned int)osinfo.dwBuildNumber);
+}
+
+
+/* Get a list of handles of shared libs loaded by the current
+   process. Returns a NULL-terminated array alocated from POOL. */
+static HMODULE *
+enum_loaded_modules(apr_pool_t *pool)
+{
+  HANDLE current = GetCurrentProcess();
+  HMODULE dummy[1];
+  HMODULE *handles;
+  DWORD size;
+
+  if (!EnumProcessModules(current, dummy, sizeof(dummy), &size))
+    return NULL;
+
+  handles = apr_palloc(pool, size + sizeof *handles);
+  if (!EnumProcessModules(current, handles, size, &size))
+    return NULL;
+  handles[size / sizeof *handles] = NULL;
+  return handles;
+}
+
+/* Find the version number, if any, embedded in FILENAME. */
+static const char *
+file_version_number(const wchar_t *filename, apr_pool_t *pool)
+{
+  VS_FIXEDFILEINFO info;
+  unsigned int major, minor, micro, nano;
+  void *data;
+  DWORD data_size = GetFileVersionInfoSizeW(filename, NULL);
+  void *vinfo;
+  UINT vinfo_size;
+
+  if (!data_size)
+    return NULL;
+
+  data = apr_palloc(pool, data_size);
+  if (!GetFileVersionInfoW(filename, 0, data_size, data))
+    return NULL;
+
+  if (!VerQueryValueW(data, L"\\", &vinfo, &vinfo_size))
+    return NULL;
+
+  if (vinfo_size != sizeof info)
+    return NULL;
+
+  memcpy(&info, vinfo, sizeof info);
+  major = (info.dwFileVersionMS >> 16) & 0xFFFF;
+  minor = info.dwFileVersionMS & 0xFFFF;
+  micro = (info.dwFileVersionLS >> 16) & 0xFFFF;
+  nano = info.dwFileVersionLS & 0xFFFF;
+
+  if (!nano)
+    {
+      if (!micro)
+        return apr_psprintf(pool, "%u.%u", major, minor);
+      else
+        return apr_psprintf(pool, "%u.%u.%u", major, minor, micro);
+    }
+  return apr_psprintf(pool, "%u.%u.%u.%u", major, minor, micro, nano);
+}
+
+/* List the shared libraries loaded by the current process. */
+static const apr_array_header_t *
+win32_shared_libs(apr_pool_t *pool)
+{
+  apr_array_header_t *array = NULL;
+  wchar_t buffer[MAX_PATH + 1];
+  HMODULE *handles = enum_loaded_modules(pool);
+  HMODULE *module;
+
+  for (module = handles; module && *module; ++module)
+    {
+      const char *filename;
+      const char *version;
+      if (GetModuleFileNameW(*module, buffer, MAX_PATH))
+        {
+          buffer[MAX_PATH] = 0;
+          version = file_version_number(buffer, pool);
+          filename = wcs_to_utf8(buffer, pool);
+          if (filename)
+            {
+              svn_version_ext_loaded_lib_t *lib;
+              char *truename;
+
+              if (0 == apr_filepath_merge(&truename, "", filename,
+                                          APR_FILEPATH_NATIVE
+                                          | APR_FILEPATH_TRUENAME,
+                                          pool))
+                filename = truename;
+
+              if (!array)
+                {
+                  array = apr_array_make(pool, 32, sizeof(*lib));
+                }
+              lib = &APR_ARRAY_PUSH(array, svn_version_ext_loaded_lib_t);
+              lib->name = filename;
+              lib->version = version;
+            }
+        }
+    }
+
+  return array;
+}
+#endif /* WIN32 */
+
+
+#ifdef SVN_HAVE_MACOS_PLIST
+/* Load the SystemVersion.plist or ServerVersion.plist file into a
+   property list. Set SERVER to TRUE if the file read was
+   ServerVersion.plist. */
+static CFDictionaryRef
+system_version_plist(svn_boolean_t *server, apr_pool_t *pool)
+{
+  static const UInt8 server_version[] =
+    "/System/Library/CoreServices/ServerVersion.plist";
+  static const UInt8 system_version[] =
+    "/System/Library/CoreServices/SystemVersion.plist";
+
+  CFPropertyListRef plist = NULL;
+  CFDataRef resource = NULL;
+  CFStringRef errstr = NULL;
+  CFURLRef url = NULL;
+  SInt32 errcode;
+
+  url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault,
+                                                server_version,
+                                                sizeof(server_version) - 1,
+                                                FALSE);
+  if (!url)
+    return NULL;
+
+  if (!CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault,
+                                                url, &resource,
+                                                NULL, NULL, &errcode))
+    {
+      CFRelease(url);
+      url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault,
+                                                    system_version,
+                                                    sizeof(system_version) - 1,
+                                                    FALSE);
+      if (!url)
+        return NULL;
+
+      if (!CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault,
+                                                    url, &resource,
+                                                    NULL, NULL, &errcode))
+        {
+          CFRelease(url);
+          return NULL;
+        }
+      else
+        {
+          CFRelease(url);
+          *server = FALSE;
+        }
+    }
+  else
+    {
+      CFRelease(url);
+      *server = TRUE;
+    }
+
+  /* ### CFPropertyListCreateFromXMLData is obsolete, but its
+         replacement CFPropertyListCreateWithData is only available
+         from Mac OS 1.6 onward. */
+  plist = CFPropertyListCreateFromXMLData(kCFAllocatorDefault, resource,
+                                          kCFPropertyListImmutable,
+                                          &errstr);
+  if (resource)
+    CFRelease(resource);
+  if (errstr)
+    CFRelease(errstr);
+
+  if (CFDictionaryGetTypeID() != CFGetTypeID(plist))
+    {
+      /* Oops ... this really should be a dict. */
+      CFRelease(plist);
+      return NULL;
+    }
+
+  return plist;
+}
+
+/* Return the value for KEY from PLIST, or NULL if not available. */
+static const char *
+value_from_dict(CFDictionaryRef plist, CFStringRef key, apr_pool_t *pool)
+{
+  CFStringRef valref;
+  CFIndex bufsize;
+  const void *valptr;
+  const char *value;
+
+  if (!CFDictionaryGetValueIfPresent(plist, key, &valptr))
+    return NULL;
+
+  valref = valptr;
+  if (CFStringGetTypeID() != CFGetTypeID(valref))
+    return NULL;
+
+  value = CFStringGetCStringPtr(valref, kCFStringEncodingUTF8);
+  if (value)
+    return apr_pstrdup(pool, value);
+
+  bufsize =  5 * CFStringGetLength(valref) + 1;
+  value = apr_palloc(pool, bufsize);
+  if (!CFStringGetCString(valref, (char*)value, bufsize,
+                          kCFStringEncodingUTF8))
+    value = NULL;
+
+  return value;
+}
+
+/* Return the commercial name of the OS, given the version number in
+   a format that matches the regular expression /^10\.\d+(\..*)?$/ */
+static const char *
+release_name_from_version(const char *osver)
+{
+  char *end = NULL;
+  unsigned long num = strtoul(osver, &end, 10);
+
+  if (!end || *end != '.' || num != 10)
+    return NULL;
+
+  osver = end + 1;
+  end = NULL;
+  num = strtoul(osver, &end, 10);
+  if (!end || (*end && *end != '.'))
+    return NULL;
+
+  /* See http://en.wikipedia.org/wiki/History_of_OS_X#Release_timeline */
+  switch(num)
+    {
+    case 0: return "Cheetah";
+    case 1: return "Puma";
+    case 2: return "Jaguar";
+    case 3: return "Panther";
+    case 4: return "Tiger";
+    case 5: return "Leopard";
+    case 6: return "Snow Leopard";
+    case 7: return "Lion";
+    case 8: return "Mountain Lion";
+    }
+
+  return NULL;
+}
+
+/* Construct the release name from information stored in the Mac OS X
+   "SystemVersion.plist" file (or ServerVersion.plist, for Mac Os
+   Server. */
+static const char *
+macos_release_name(apr_pool_t *pool)
+{
+  svn_boolean_t server;
+  CFDictionaryRef plist = system_version_plist(&server, pool);
+
+  if (plist)
+    {
+      const char *osname = value_from_dict(plist, CFSTR("ProductName"), pool);
+      const char *osver = value_from_dict(plist,
+                                          CFSTR("ProductUserVisibleVersion"),
+                                          pool);
+      const char *build = value_from_dict(plist,
+                                          CFSTR("ProductBuildVersion"),
+                                          pool);
+      const char *release;
+
+      if (!osver)
+        osver = value_from_dict(plist, CFSTR("ProductVersion"), pool);
+      release = release_name_from_version(osver);
+
+      CFRelease(plist);
+      return apr_psprintf(pool, "%s%s%s%s%s%s%s%s",
+                          (osname ? osname : ""),
+                          (osver ? (osname ? " " : "") : ""),
+                          (osver ? osver : ""),
+                          (release ? (osname||osver ? " " : "") : ""),
+                          (release ? release : ""),
+                          (build
+                           ? (osname||osver||release ? ", " : "")
+                           : ""),
+                          (build
+                           ? (server ? "server build " : "build ")
+                           : ""),
+                          (build ? build : ""));
+    }
+
+  return NULL;
+}
+#endif  /* SVN_HAVE_MACOS_PLIST */
+
+#ifdef SVN_HAVE_MACHO_ITERATE
+/* List the shared libraries loaded by the current process.
+   Ignore frameworks and system libraries, they're just clutter. */
+static const apr_array_header_t *
+macos_shared_libs(apr_pool_t *pool)
+{
+  static const char slb_prefix[] = "/usr/lib/system/";
+  static const char fwk_prefix[] = "/System/Library/Frameworks/";
+  static const char pfk_prefix[] = "/System/Library/PrivateFrameworks/";
+
+  const size_t slb_prefix_len = strlen(slb_prefix);
+  const size_t fwk_prefix_len = strlen(fwk_prefix);
+  const size_t pfk_prefix_len = strlen(pfk_prefix);
+
+  apr_array_header_t *result = NULL;
+  apr_array_header_t *dylibs = NULL;
+
+  uint32_t i;
+  for (i = 0;; ++i)
+    {
+      const struct mach_header *header = _dyld_get_image_header(i);
+      const char *filename = _dyld_get_image_name(i);
+      const char *version;
+      char *truename;
+      svn_version_ext_loaded_lib_t *lib;
+
+      if (!(header && filename))
+        break;
+
+      switch (header->cputype)
+        {
+        case CPU_TYPE_I386:      version = _("Intel"); break;
+        case CPU_TYPE_X86_64:    version = _("Intel 64-bit"); break;
+        case CPU_TYPE_POWERPC:   version = _("PowerPC"); break;
+        case CPU_TYPE_POWERPC64: version = _("PowerPC 64-bit"); break;
+        default:
+          version = NULL;
+        }
+
+      if (0 == apr_filepath_merge(&truename, "", filename,
+                                  APR_FILEPATH_NATIVE
+                                  | APR_FILEPATH_TRUENAME,
+                                  pool))
+        filename = truename;
+      else
+        filename = apr_pstrdup(pool, filename);
+
+      if (0 == strncmp(filename, slb_prefix, slb_prefix_len)
+          || 0 == strncmp(filename, fwk_prefix, fwk_prefix_len)
+          || 0 == strncmp(filename, pfk_prefix, pfk_prefix_len))
+        {
+          /* Ignore frameworks and system libraries. */
+          continue;
+        }
+
+      if (header->filetype == MH_EXECUTE)
+        {
+          /* Make sure the program filename is first in the list */
+          if (!result)
+            {
+              result = apr_array_make(pool, 32, sizeof(*lib));
+            }
+          lib = &APR_ARRAY_PUSH(result, svn_version_ext_loaded_lib_t);
+        }
+      else
+        {
+          if (!dylibs)
+            {
+              dylibs = apr_array_make(pool, 32, sizeof(*lib));
+            }
+          lib = &APR_ARRAY_PUSH(dylibs, svn_version_ext_loaded_lib_t);
+        }
+
+      lib->name = filename;
+      lib->version = version;
+    }
+
+  /* Gather results into one array. */
+  if (dylibs)
+    {
+      if (result)
+        apr_array_cat(result, dylibs);
+      else
+        result = dylibs;
+    }
+
+  return result;
+}
+#endif  /* SVN_HAVE_MACHO_ITERATE */

Modified: subversion/branches/compressed-pristines/subversion/libsvn_subr/sysinfo.h
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_subr/sysinfo.h?rev=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_subr/sysinfo.h (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_subr/sysinfo.h Sat Nov 24 20:29:11 2012
@@ -1,59 +1,69 @@
-/*
- * sysinfo.h:  share svn_sysinfo__* functions
- *
- * ====================================================================
- *    Licensed to the Apache Software Foundation (ASF) under one
- *    or more contributor license agreements.  See the NOTICE file
- *    distributed with this work for additional information
- *    regarding copyright ownership.  The ASF licenses this file
- *    to you under the Apache License, Version 2.0 (the
- *    "License"); you may not use this file except in compliance
- *    with the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- *    Unless required by applicable law or agreed to in writing,
- *    software distributed under the License is distributed on an
- *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *    KIND, either express or implied.  See the License for the
- *    specific language governing permissions and limitations
- *    under the License.
- * ====================================================================
- */
-
-#ifndef SVN_LIBSVN_SUBR_SYSINFO_H
-#define SVN_LIBSVN_SUBR_SYSINFO_H
-
-#include <apr_pools.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-/* Return a canonical name similar to the output of config.guess,
- * identifying the running system.
- *
- * All allocations are done in POOL.
- */
-const char *svn_sysinfo__canonical_host(apr_pool_t *pool);
-
-/* Return the release name (i.e., marketing name) of the running
- * system, or NULL if it's not available.
- *
- * All allocations are done in POOL.
- */
-const char *svn_sysinfo__release_name(apr_pool_t *pool);
-
-/* Return a string containing a list of shared libraries loaded by the
- * running process, including their versions where applicable, or NULL
- * if the information is not available.
- *
- * All allocations are done in POOL.
- */
-const char *svn_sysinfo__loaded_libs(apr_pool_t *pool);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* SVN_LIBSVN_SUBR_SYSINFO_H */
+/*
+ * sysinfo.h:  share svn_sysinfo__* functions
+ *
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you under the Apache License, Version 2.0 (the
+ *    "License"); you may not use this file except in compliance
+ *    with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ * ====================================================================
+ */
+
+#ifndef SVN_LIBSVN_SUBR_SYSINFO_H
+#define SVN_LIBSVN_SUBR_SYSINFO_H
+
+#include <apr_pools.h>
+#include <apr_tables.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* Return a canonical name similar to the output of config.guess,
+ * identifying the running system.
+ *
+ * All allocations are done in POOL.
+ */
+const char *svn_sysinfo__canonical_host(apr_pool_t *pool);
+
+/* Return the release name (i.e., marketing name) of the running
+ * system, or NULL if it's not available.
+ *
+ * All allocations are done in POOL.
+ */
+const char *svn_sysinfo__release_name(apr_pool_t *pool);
+
+/* Return an array of svn_version_linked_lib_t of descriptions of the
+ * link-time and run-time versions of dependent libraries, or NULL of
+ * the info is not available.
+ *
+ * All allocations are done in POOL.
+ */
+const apr_array_header_t *svn_sysinfo__linked_libs(apr_pool_t *pool);
+
+/* Return an array of svn_version_loaded_lib_t of descriptions of
+ * shared libraries loaded by the running process, including their
+ * versions where applicable, or NULL if the information is not
+ * available.
+ *
+ * All allocations are done in POOL.
+ */
+const apr_array_header_t *svn_sysinfo__loaded_libs(apr_pool_t *pool);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* SVN_LIBSVN_SUBR_SYSINFO_H */

Modified: subversion/branches/compressed-pristines/subversion/libsvn_subr/temp_serializer.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_subr/temp_serializer.c?rev=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_subr/temp_serializer.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_subr/temp_serializer.c Sat Nov 24 20:29:11 2012
@@ -51,7 +51,9 @@ typedef struct source_stack_t
   /* offset within the target buffer to where the structure got copied */
   apr_size_t target_offset;
 
-  /* parent stack entry. Will be NULL for the root entry. */
+  /* parent stack entry. Will be NULL for the root entry.
+   * Items in the svn_temp_serializer__context_t recycler will use this
+   * to link to the next unused item. */
   struct source_stack_t *upper;
 } source_stack_t;
 
@@ -70,6 +72,9 @@ struct svn_temp_serializer__context_t
    * process has been finished. However, it is not necessarily NULL when
    * the application end serialization. */
   source_stack_t *source;
+
+  /* unused stack elements will be put here for later reuse. */
+  source_stack_t *recycler;
 };
 
 /* Make sure the serialized data len is a multiple of the default alignment,
@@ -110,6 +115,7 @@ svn_temp_serializer__init(const void *so
   svn_temp_serializer__context_t *context = apr_palloc(pool, sizeof(*context));
   context->pool = pool;
   context->buffer = svn_stringbuf_create_ensure(init_size, pool);
+  context->recycler = NULL;
 
   /* If a source struct has been given, make it the root struct. */
   if (source_struct)
@@ -168,6 +174,9 @@ svn_temp_serializer__init_append(void *b
   context->source->target_offset = (char *)source_struct - (char *)buffer;
   context->source->upper = NULL;
 
+  /* initialize the RECYCLER */
+  context->recycler = NULL;
+
   /* done */
   return context;
 }
@@ -219,9 +228,16 @@ svn_temp_serializer__push(svn_temp_seria
                           apr_size_t struct_size)
 {
   const void *source = *source_struct;
+  source_stack_t *new;
 
-  /* create a new entry for the structure stack */
-  source_stack_t *new = apr_palloc(context->pool, sizeof(*new));
+  /* recycle an old entry or create a new one for the structure stack */
+  if (context->recycler)
+    {
+      new = context->recycler;
+      context->recycler = new->upper;
+    }
+  else
+    new = apr_palloc(context->pool, sizeof(*new));
 
   /* the serialized structure must be properly aligned */
   if (source)
@@ -250,11 +266,17 @@ svn_temp_serializer__push(svn_temp_seria
 void
 svn_temp_serializer__pop(svn_temp_serializer__context_t *context)
 {
+  source_stack_t *old = context->source;
+  
   /* we may pop the original struct but not further */
   assert(context->source);
 
   /* one level up the structure stack */
   context->source = context->source->upper;
+
+  /* put the old stack element into the recycler for later reuse */
+  old->upper = context->recycler;
+  context->recycler = old;
 }
 
 /* Serialize a string referenced from the current structure within the
@@ -311,7 +333,7 @@ svn_temp_serializer__get_length(svn_temp
   return context->buffer->len;
 }
 
-/* Return the data buffer that receives the serialialized data from
+/* Return the data buffer that receives the serialized data from
  * the given serialization CONTEXT.
  */
 svn_stringbuf_t *

Modified: subversion/branches/compressed-pristines/subversion/libsvn_subr/utf.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_subr/utf.c?rev=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_subr/utf.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_subr/utf.c Sat Nov 24 20:29:11 2012
@@ -892,7 +892,9 @@ svn_utf_stringbuf_from_utf8(svn_stringbu
         *dest = svn_stringbuf_dup(src, pool);
     }
 
-  put_xlate_handle_node(node, SVN_UTF_UTON_XLATE_HANDLE, pool);
+  err = svn_error_compose_create(
+          err,
+          put_xlate_handle_node(node, SVN_UTF_UTON_XLATE_HANDLE, pool));
 
   return err;
 }
@@ -925,7 +927,9 @@ svn_utf_string_from_utf8(const svn_strin
         *dest = svn_string_dup(src, pool);
     }
 
-  put_xlate_handle_node(node, SVN_UTF_UTON_XLATE_HANDLE, pool);
+  err = svn_error_compose_create(
+          err,
+          put_xlate_handle_node(node, SVN_UTF_UTON_XLATE_HANDLE, pool));
 
   return err;
 }
@@ -939,11 +943,13 @@ svn_utf_cstring_from_utf8(const char **d
   xlate_handle_node_t *node;
   svn_error_t *err;
 
-  SVN_ERR(check_utf8(src, strlen(src), pool));
+  SVN_ERR(check_cstring_utf8(src, pool));
 
   SVN_ERR(get_uton_xlate_handle_node(&node, pool));
   err = convert_cstring(dest, src, node, pool);
-  put_xlate_handle_node(node, SVN_UTF_UTON_XLATE_HANDLE, pool);
+  err = svn_error_compose_create(
+          err, 
+          put_xlate_handle_node(node, SVN_UTF_UTON_XLATE_HANDLE, pool));
 
   return err;
 }
@@ -960,12 +966,14 @@ svn_utf_cstring_from_utf8_ex2(const char
   const char *convset_key = get_xlate_key(topage, SVN_APR_UTF8_CHARSET,
                                           pool);
 
-  SVN_ERR(check_utf8(src, strlen(src), pool));
+  SVN_ERR(check_cstring_utf8(src, pool));
 
   SVN_ERR(get_xlate_handle_node(&node, topage, SVN_APR_UTF8_CHARSET,
                                 convset_key, pool));
   err = convert_cstring(dest, src, node, pool);
-  put_xlate_handle_node(node, convset_key, pool);
+  err = svn_error_compose_create(
+          err,
+          put_xlate_handle_node(node, convset_key, pool));
 
   return err;
 }
@@ -1062,7 +1070,9 @@ svn_utf_cstring_from_utf8_string(const c
         *dest = apr_pstrmemdup(pool, src->data, src->len);
     }
 
-  put_xlate_handle_node(node, SVN_UTF_UTON_XLATE_HANDLE, pool);
+  err = svn_error_compose_create(
+          err,
+          put_xlate_handle_node(node, SVN_UTF_UTON_XLATE_HANDLE, pool));
 
   return err;
 }

Modified: subversion/branches/compressed-pristines/subversion/libsvn_subr/utf_validate.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_subr/utf_validate.c?rev=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_subr/utf_validate.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_subr/utf_validate.c Sat Nov 24 20:29:11 2012
@@ -57,6 +57,8 @@
  */
 
 #include "private/svn_utf_private.h"
+#include "private/svn_eol_private.h"
+#include "private/svn_dep_compat.h"
 
 /* Lookup table to categorise each octet in the string. */
 static const char octet_category[256] = {
@@ -249,12 +251,92 @@ static const char machine [9][14] = {
    FSM_ERROR},        /* 0xf5-0xff */
 };
 
+/* Scan MAX_LEN bytes in *DATA for chars that are not in the octet
+ * category 0 (FSM_START).  Return the position of the first such char
+ * or DATA + MAX_LEN if all were cat 0.
+ */
+static const char *
+first_non_fsm_start_char(const char *data, apr_size_t max_len)
+{
+#if !SVN_UNALIGNED_ACCESS_IS_OK
+
+  /* On some systems, we need to make sure that buf is properly aligned
+   * for chunky data access.
+   */
+  if ((apr_uintptr_t)data & (sizeof(apr_uintptr_t)-1))
+    {
+      apr_size_t len = (~(apr_uintptr_t)data) & (sizeof(apr_uintptr_t)-1);
+      if (len > max_len)
+        len = max_len;
+      max_len -= len;
+
+      for (; len > 0; ++data, --len)
+        if (*data < 0 || *data >= 0x80)
+          return data;
+    }
+    
+#endif
+    
+  /* Scan the input one machine word at a time. */
+  for (; max_len > sizeof(apr_uintptr_t)
+       ; data += sizeof(apr_uintptr_t), max_len -= sizeof(apr_uintptr_t))
+    if (*(const apr_uintptr_t *)data & SVN__BIT_7_SET)
+      break;
+
+  /* The remaining odd bytes will be examined the naive way: */
+  for (; max_len > 0; ++data, --max_len)
+    if (*data < 0 || *data >= 0x80)
+      break;
+
+  return data;
+}
+
+/* Scan the C string in *DATA for chars that are not in the octet
+ * category 0 (FSM_START).  Return the position of either the such
+ * char or of the terminating NUL.
+ */
+static const char *
+first_non_fsm_start_char_cstring(const char *data)
+{
+  /* We need to make sure that BUF is properly aligned for chunky data
+   * access because we don't know the string's length. Unaligned chunk
+   * read access beyond the NUL terminator could therefore result in a
+   * segfault.
+   */
+  for (; (apr_uintptr_t)data & (sizeof(apr_uintptr_t)-1); ++data)
+    if (*data <= 0 || *data >= 0x80)
+      return data;
+
+  /* Scan the input one machine word at a time. */
+  for (; ; data += sizeof(apr_uintptr_t))
+    {
+      /* Check for non-ASCII chars: */
+      apr_uintptr_t chunk = *(const apr_uintptr_t *)data;
+      if (chunk & SVN__BIT_7_SET)
+        break;
+
+      /* This is the well-known strlen test: */
+      chunk |= (chunk & SVN__LOWER_7BITS_SET) + SVN__LOWER_7BITS_SET;
+      if ((chunk & SVN__BIT_7_SET) != SVN__BIT_7_SET)
+        break;
+    }
+
+  /* The remaining odd bytes will be examined the naive way: */
+  for (; ; ++data)
+    if (*data <= 0 || *data >= 0x80)
+      break;
+
+  return data;
+}
 
 const char *
 svn_utf__last_valid(const char *data, apr_size_t len)
 {
-  const char *start = data, *end = data + len;
+  const char *start = first_non_fsm_start_char(data, len);
+  const char *end = data + len;
   int state = FSM_START;
+
+  data = start;
   while (data < end)
     {
       unsigned char octet = *data++;
@@ -270,6 +352,8 @@ svn_boolean_t
 svn_utf__cstring_is_valid(const char *data)
 {
   int state = FSM_START;
+  data = first_non_fsm_start_char_cstring(data);
+
   while (*data)
     {
       unsigned char octet = *data++;
@@ -284,6 +368,8 @@ svn_utf__is_valid(const char *data, apr_
 {
   const char *end = data + len;
   int state = FSM_START;
+  data = first_non_fsm_start_char(data, len);
+
   while (data < end)
     {
       unsigned char octet = *data++;
@@ -296,8 +382,11 @@ svn_utf__is_valid(const char *data, apr_
 const char *
 svn_utf__last_valid2(const char *data, apr_size_t len)
 {
-  const char *start = data, *end = data + len;
+  const char *start = first_non_fsm_start_char(data, len);
+  const char *end = data + len;
   int state = FSM_START;
+
+  data = start;
   while (data < end)
     {
       unsigned char octet = *data++;

Modified: subversion/branches/compressed-pristines/subversion/libsvn_subr/version.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_subr/version.c?rev=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_subr/version.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_subr/version.c Sat Nov 24 20:29:11 2012
@@ -26,7 +26,9 @@
 #include "svn_error.h"
 #include "svn_version.h"
 
+#include "sysinfo.h"
 #include "svn_private_config.h"
+#include "private/svn_subr_private.h"
 
 const svn_version_t *
 svn_subr_version(void)
@@ -96,3 +98,181 @@ svn_ver_check_list(const svn_version_t *
 
   return err;
 }
+
+
+struct svn_version_extended_t
+{
+  const char *build_date;       /* Compilation date */
+  const char *build_time;       /* Compilation time */
+  const char *build_host;       /* Build canonical host name */
+  const char *copyright;        /* Copyright notice (localized) */
+  const char *runtime_host;     /* Runtime canonical host name */
+  const char *runtime_osname;   /* Running OS release name */
+
+  /* Array of svn_version_ext_linked_lib_t describing dependent
+     libraries. */
+  const apr_array_header_t *linked_libs;
+
+  /* Array of svn_version_ext_loaded_lib_t describing loaded shared
+     libraries. */
+  const apr_array_header_t *loaded_libs;
+};
+
+
+const svn_version_extended_t *
+svn_version_extended(svn_boolean_t verbose,
+                     apr_pool_t *pool)
+{
+  svn_version_extended_t *info = apr_pcalloc(pool, sizeof(*info));
+
+  info->build_date = __DATE__;
+  info->build_time = __TIME__;
+  info->build_host = SVN_BUILD_HOST;
+  info->copyright = apr_pstrdup
+    (pool, _("Copyright (C) 2012 The Apache Software Foundation.\n"
+             "This software consists of contributions made by many people;\n"
+             "see the NOTICE file for more information.\n"
+             "Subversion is open source software, see "
+             "http://subversion.apache.org/\n"));
+
+  if (verbose)
+    {
+      info->runtime_host = svn_sysinfo__canonical_host(pool);
+      info->runtime_osname = svn_sysinfo__release_name(pool);
+      info->linked_libs = svn_sysinfo__linked_libs(pool);
+      info->loaded_libs = svn_sysinfo__loaded_libs(pool);
+    }
+
+  return info;
+}
+
+
+const char *
+svn_version_ext_build_date(const svn_version_extended_t *ext_info)
+{
+  return ext_info->build_date;
+}
+
+const char *
+svn_version_ext_build_time(const svn_version_extended_t *ext_info)
+{
+  return ext_info->build_time;
+}
+
+const char *
+svn_version_ext_build_host(const svn_version_extended_t *ext_info)
+{
+  return ext_info->build_host;
+}
+
+const char *
+svn_version_ext_copyright(const svn_version_extended_t *ext_info)
+{
+  return ext_info->copyright;
+}
+
+const char *
+svn_version_ext_runtime_host(const svn_version_extended_t *ext_info)
+{
+  return ext_info->runtime_host;
+}
+
+const char *
+svn_version_ext_runtime_osname(const svn_version_extended_t *ext_info)
+{
+  return ext_info->runtime_osname;
+}
+
+const apr_array_header_t *
+svn_version_ext_linked_libs(const svn_version_extended_t *ext_info)
+{
+  return ext_info->linked_libs;
+}
+
+const apr_array_header_t *
+svn_version_ext_loaded_libs(const svn_version_extended_t *ext_info)
+{
+  return ext_info->loaded_libs;
+}
+
+svn_error_t *
+svn_version__parse_version_string(svn_version_t **version_p,
+                                  const char *version_string,
+                                  apr_pool_t *result_pool)
+{
+  svn_error_t *err;
+  svn_version_t *version;
+  apr_array_header_t *pieces = 
+    svn_cstring_split(version_string, ".", FALSE, result_pool);
+
+  if ((pieces->nelts < 2) || (pieces->nelts > 3))
+    return svn_error_create(SVN_ERR_MALFORMED_VERSION_STRING, NULL, NULL);
+
+  version = apr_pcalloc(result_pool, sizeof(*version));
+  version->tag = "";
+
+  /* Parse the major and minor integers strictly. */
+  err = svn_cstring_atoi(&(version->major),
+                         APR_ARRAY_IDX(pieces, 0, const char *));
+  if (err)
+    return svn_error_create(SVN_ERR_MALFORMED_VERSION_STRING, err, NULL);
+  err = svn_cstring_atoi(&(version->minor),
+                         APR_ARRAY_IDX(pieces, 1, const char *));
+  if (err)
+    return svn_error_create(SVN_ERR_MALFORMED_VERSION_STRING, err, NULL);
+
+  /* If there's a third component, we'll parse it, too.  But we don't
+     require that it be present. */
+  if (pieces->nelts == 3)
+    {
+      const char *piece = APR_ARRAY_IDX(pieces, 2, const char *);
+      char *hyphen = strchr(piece, '-');
+      if (hyphen)
+        {
+          version->tag = apr_pstrdup(result_pool, hyphen + 1);
+          *hyphen = '\0';
+        }
+      err = svn_cstring_atoi(&(version->patch), piece);
+      if (err)
+        return svn_error_create(SVN_ERR_MALFORMED_VERSION_STRING,
+                                err, NULL);
+    }
+
+  *version_p = version;
+  return SVN_NO_ERROR;
+}
+
+
+svn_boolean_t
+svn_version__at_least(svn_version_t *version,
+                      int major,
+                      int minor,
+                      int patch)
+{
+  /* Compare major versions. */
+  if (version->major < major)
+    return FALSE;
+  if (version->major > major)
+    return TRUE;
+
+  /* Major versions are the same.  Compare minor versions. */
+  if (version->minor < minor)
+    return FALSE;
+  if (version->minor > minor)
+    return TRUE;
+
+  /* Major and minor versions are the same.  Compare patch
+     versions. */
+  if (version->patch < patch)
+    return FALSE;
+  if (version->patch > patch)
+    return TRUE;
+
+  /* Major, minor, and patch versions are identical matches.  But tags
+     in our schema are always used for versions not yet quite at the
+     given patch level. */
+  if (version->tag && version->tag[0])
+    return FALSE;
+
+  return TRUE;
+}

Modified: subversion/branches/compressed-pristines/subversion/libsvn_subr/win32_crypto.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_subr/win32_crypto.c?rev=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_subr/win32_crypto.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_subr/win32_crypto.c Sat Nov 24 20:29:11 2012
@@ -145,7 +145,7 @@ windows_password_decrypter(svn_boolean_t
 
   SVN_ERR(svn_auth__simple_password_get(done, &in, creds, realmstring, username,
                                         parameters, non_interactive, pool));
-  if (!done)
+  if (!*done)
     return SVN_NO_ERROR;
 
   orig = svn_base64_decode_string(svn_string_create(in, pool), pool);
@@ -270,7 +270,7 @@ windows_ssl_client_cert_pw_decrypter(svn
   SVN_ERR(svn_auth__ssl_client_cert_pw_get(done, &in, creds, realmstring,
                                            username, parameters,
                                            non_interactive, pool));
-  if (!done)
+  if (!*done)
     return SVN_NO_ERROR;
 
   orig = svn_base64_decode_string(svn_string_create(in, pool), pool);

Modified: subversion/branches/compressed-pristines/subversion/libsvn_wc/adm_files.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_wc/adm_files.c?rev=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_wc/adm_files.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_wc/adm_files.c Sat Nov 24 20:29:11 2012
@@ -592,7 +592,7 @@ svn_wc_create_tmp_file2(apr_file_t **fp,
 
   SVN_ERR(svn_wc__db_open(&db,
                           NULL /* config */,
-                          TRUE /* auto_upgrade */,
+                          FALSE /* auto_upgrade */,
                           TRUE /* enforce_empty_wq */,
                           pool, pool));
 

Modified: subversion/branches/compressed-pristines/subversion/libsvn_wc/adm_ops.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_wc/adm_ops.c?rev=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_wc/adm_ops.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_wc/adm_ops.c Sat Nov 24 20:29:11 2012
@@ -1019,6 +1019,7 @@ check_can_add_node(svn_node_kind_t *kind
   const char *base_name = svn_dirent_basename(local_abspath, scratch_pool);
   svn_boolean_t is_wc_root;
   svn_node_kind_t kind;
+  svn_boolean_t is_special;
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
   SVN_ERR_ASSERT(!copyfrom_url || (svn_uri_is_canonical(copyfrom_url,
@@ -1035,7 +1036,8 @@ check_can_add_node(svn_node_kind_t *kind
   SVN_ERR(svn_path_check_valid(local_abspath, scratch_pool));
 
   /* Make sure something's there; set KIND and *KIND_P. */
-  SVN_ERR(svn_io_check_path(local_abspath, &kind, scratch_pool));
+  SVN_ERR(svn_io_check_special_path(local_abspath, &kind, &is_special,
+                                    scratch_pool));
   if (kind == svn_node_none)
     return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
                              _("'%s' not found"),
@@ -1097,14 +1099,20 @@ check_can_add_node(svn_node_kind_t *kind
               SVN_ERR_ASSERT(!is_wc_root);
               break;
             case svn_wc__db_status_normal:
-              if (copyfrom_url)
-                {
-                  SVN_ERR(svn_wc__check_wc_root(&is_wc_root, NULL, NULL,
-                                                db, local_abspath,
-                                                scratch_pool));
+              SVN_ERR(svn_wc__db_is_wcroot(&is_wc_root, db, local_abspath,
+                                           scratch_pool));
 
-                  if (is_wc_root)
-                    break;
+              if (is_wc_root && copyfrom_url)
+                {
+                  /* Integrate a sub working copy in a parent working copy
+                     (legacy behavior) */
+                  break;
+                }
+              else if (is_wc_root && is_special)
+                {
+                  /* Adding a symlink to a working copy root.
+                     (special_tests.py 23: externals as symlink targets) */
+                  break;
                 }
               /* else: Fall through in default error */
 
@@ -2203,7 +2211,7 @@ svn_wc_get_pristine_copy_path(const char
 
   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
 
-  SVN_ERR(svn_wc__db_open(&db, NULL, TRUE, TRUE, pool, pool));
+  SVN_ERR(svn_wc__db_open(&db, NULL, FALSE, TRUE, pool, pool));
   /* DB is now open. This is seemingly a "light" function that a caller
      may use repeatedly despite error return values. The rest of this
      function should aggressively close DB, even in the error case.  */

Modified: subversion/branches/compressed-pristines/subversion/libsvn_wc/cleanup.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_wc/cleanup.c?rev=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_wc/cleanup.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_wc/cleanup.c Sat Nov 24 20:29:11 2012
@@ -206,7 +206,7 @@ svn_wc_cleanup3(svn_wc_context_t *wc_ctx
   /* We need a DB that allows a non-empty work queue (though it *will*
      auto-upgrade). We'll handle everything manually.  */
   SVN_ERR(svn_wc__db_open(&db,
-                          NULL /* ### config */, TRUE, FALSE,
+                          NULL /* ### config */, FALSE, FALSE,
                           scratch_pool, scratch_pool));
 
   SVN_ERR(cleanup_internal(db, local_abspath, cancel_func, cancel_baton,