sysinfo.c revision 262250
1251881Speter/* 2251881Speter * sysinfo.c : information about the running system 3251881Speter * 4251881Speter * ==================================================================== 5251881Speter * Licensed to the Apache Software Foundation (ASF) under one 6251881Speter * or more contributor license agreements. See the NOTICE file 7251881Speter * distributed with this work for additional information 8251881Speter * regarding copyright ownership. The ASF licenses this file 9251881Speter * to you under the Apache License, Version 2.0 (the 10251881Speter * "License"); you may not use this file except in compliance 11251881Speter * with the License. You may obtain a copy of the License at 12251881Speter * 13251881Speter * http://www.apache.org/licenses/LICENSE-2.0 14251881Speter * 15251881Speter * Unless required by applicable law or agreed to in writing, 16251881Speter * software distributed under the License is distributed on an 17251881Speter * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 18251881Speter * KIND, either express or implied. See the License for the 19251881Speter * specific language governing permissions and limitations 20251881Speter * under the License. 21251881Speter * ==================================================================== 22251881Speter */ 23251881Speter 24251881Speter 25251881Speter 26251881Speter#ifdef WIN32 27251881Speter#define WIN32_LEAN_AND_MEAN 28251881Speter#define PSAPI_VERSION 1 29251881Speter#include <windows.h> 30251881Speter#include <psapi.h> 31251881Speter#include <Ws2tcpip.h> 32251881Speter#endif 33251881Speter 34251881Speter#define APR_WANT_STRFUNC 35251881Speter#include <apr_want.h> 36251881Speter 37251881Speter#include <apr_lib.h> 38251881Speter#include <apr_pools.h> 39251881Speter#include <apr_file_info.h> 40251881Speter#include <apr_signal.h> 41251881Speter#include <apr_strings.h> 42251881Speter#include <apr_thread_proc.h> 43251881Speter#include <apr_version.h> 44251881Speter#include <apu_version.h> 45251881Speter 46251881Speter#include "svn_pools.h" 47251881Speter#include "svn_ctype.h" 48251881Speter#include "svn_dirent_uri.h" 49251881Speter#include "svn_error.h" 50251881Speter#include "svn_io.h" 51251881Speter#include "svn_string.h" 52251881Speter#include "svn_utf.h" 53251881Speter#include "svn_version.h" 54251881Speter 55251881Speter#include "private/svn_sqlite.h" 56251881Speter 57251881Speter#include "sysinfo.h" 58251881Speter#include "svn_private_config.h" 59251881Speter 60251881Speter#if HAVE_SYS_UTSNAME_H 61251881Speter#include <sys/utsname.h> 62251881Speter#endif 63251881Speter 64251881Speter#ifdef SVN_HAVE_MACOS_PLIST 65251881Speter#include <CoreFoundation/CoreFoundation.h> 66251881Speter#endif 67251881Speter 68251881Speter#ifdef SVN_HAVE_MACHO_ITERATE 69251881Speter#include <mach-o/dyld.h> 70251881Speter#include <mach-o/loader.h> 71251881Speter#endif 72251881Speter 73251881Speter#if HAVE_UNAME 74251881Speterstatic const char *canonical_host_from_uname(apr_pool_t *pool); 75251881Speter# ifndef SVN_HAVE_MACOS_PLIST 76251881Speterstatic const char *release_name_from_uname(apr_pool_t *pool); 77251881Speter# endif 78251881Speter#endif 79251881Speter 80251881Speter#ifdef WIN32 81251881Speterstatic const char *win32_canonical_host(apr_pool_t *pool); 82251881Speterstatic const char *win32_release_name(apr_pool_t *pool); 83251881Speterstatic const apr_array_header_t *win32_shared_libs(apr_pool_t *pool); 84251881Speter#endif /* WIN32 */ 85251881Speter 86251881Speter#ifdef SVN_HAVE_MACOS_PLIST 87251881Speterstatic const char *macos_release_name(apr_pool_t *pool); 88251881Speter#endif 89251881Speter 90251881Speter#ifdef SVN_HAVE_MACHO_ITERATE 91251881Speterstatic const apr_array_header_t *macos_shared_libs(apr_pool_t *pool); 92251881Speter#endif 93251881Speter 94251881Speter 95251881Speter#if __linux__ 96251881Speterstatic const char *linux_release_name(apr_pool_t *pool); 97251881Speter#endif 98251881Speter 99251881Speterconst char * 100251881Spetersvn_sysinfo__canonical_host(apr_pool_t *pool) 101251881Speter{ 102251881Speter#ifdef WIN32 103251881Speter return win32_canonical_host(pool); 104251881Speter#elif HAVE_UNAME 105251881Speter return canonical_host_from_uname(pool); 106251881Speter#else 107251881Speter return "unknown-unknown-unknown"; 108251881Speter#endif 109251881Speter} 110251881Speter 111251881Speter 112251881Speterconst char * 113251881Spetersvn_sysinfo__release_name(apr_pool_t *pool) 114251881Speter{ 115251881Speter#ifdef WIN32 116251881Speter return win32_release_name(pool); 117251881Speter#elif defined(SVN_HAVE_MACOS_PLIST) 118251881Speter return macos_release_name(pool); 119251881Speter#elif __linux__ 120251881Speter return linux_release_name(pool); 121251881Speter#elif HAVE_UNAME 122251881Speter return release_name_from_uname(pool); 123251881Speter#else 124251881Speter return NULL; 125251881Speter#endif 126251881Speter} 127251881Speter 128251881Speterconst apr_array_header_t * 129251881Spetersvn_sysinfo__linked_libs(apr_pool_t *pool) 130251881Speter{ 131251881Speter svn_version_ext_linked_lib_t *lib; 132251881Speter apr_array_header_t *array = apr_array_make(pool, 3, sizeof(*lib)); 133251881Speter 134251881Speter lib = &APR_ARRAY_PUSH(array, svn_version_ext_linked_lib_t); 135251881Speter lib->name = "APR"; 136251881Speter lib->compiled_version = APR_VERSION_STRING; 137251881Speter lib->runtime_version = apr_pstrdup(pool, apr_version_string()); 138251881Speter 139251881Speter/* Don't list APR-Util if it isn't linked in, which it may not be if 140251881Speter * we're using APR 2.x+ which combined APR-Util into APR. */ 141251881Speter#ifdef APU_VERSION_STRING 142251881Speter lib = &APR_ARRAY_PUSH(array, svn_version_ext_linked_lib_t); 143251881Speter lib->name = "APR-Util"; 144251881Speter lib->compiled_version = APU_VERSION_STRING; 145251881Speter lib->runtime_version = apr_pstrdup(pool, apu_version_string()); 146251881Speter#endif 147251881Speter 148251881Speter lib = &APR_ARRAY_PUSH(array, svn_version_ext_linked_lib_t); 149251881Speter lib->name = "SQLite"; 150251881Speter lib->compiled_version = apr_pstrdup(pool, svn_sqlite__compiled_version()); 151251881Speter#ifdef SVN_SQLITE_INLINE 152251881Speter lib->runtime_version = NULL; 153251881Speter#else 154251881Speter lib->runtime_version = apr_pstrdup(pool, svn_sqlite__runtime_version()); 155251881Speter#endif 156251881Speter 157251881Speter return array; 158251881Speter} 159251881Speter 160251881Speterconst apr_array_header_t * 161251881Spetersvn_sysinfo__loaded_libs(apr_pool_t *pool) 162251881Speter{ 163251881Speter#ifdef WIN32 164251881Speter return win32_shared_libs(pool); 165251881Speter#elif defined(SVN_HAVE_MACHO_ITERATE) 166251881Speter return macos_shared_libs(pool); 167251881Speter#else 168251881Speter return NULL; 169251881Speter#endif 170251881Speter} 171251881Speter 172251881Speter 173251881Speter#if HAVE_UNAME 174251881Speterstatic const char* 175251881Spetercanonical_host_from_uname(apr_pool_t *pool) 176251881Speter{ 177251881Speter const char *machine = "unknown"; 178251881Speter const char *vendor = "unknown"; 179251881Speter const char *sysname = "unknown"; 180251881Speter const char *sysver = ""; 181251881Speter struct utsname info; 182251881Speter 183251881Speter if (0 <= uname(&info)) 184251881Speter { 185251881Speter svn_error_t *err; 186251881Speter const char *tmp; 187251881Speter 188251881Speter err = svn_utf_cstring_to_utf8(&tmp, info.machine, pool); 189251881Speter if (err) 190251881Speter svn_error_clear(err); 191251881Speter else 192251881Speter machine = tmp; 193251881Speter 194251881Speter err = svn_utf_cstring_to_utf8(&tmp, info.sysname, pool); 195251881Speter if (err) 196251881Speter svn_error_clear(err); 197251881Speter else 198251881Speter { 199251881Speter char *lwr = apr_pstrdup(pool, tmp); 200251881Speter char *it = lwr; 201251881Speter while (*it) 202251881Speter { 203251881Speter if (svn_ctype_isupper(*it)) 204251881Speter *it = apr_tolower(*it); 205251881Speter ++it; 206251881Speter } 207251881Speter sysname = lwr; 208251881Speter } 209251881Speter 210251881Speter if (0 == strcmp(sysname, "darwin")) 211251881Speter vendor = "apple"; 212251881Speter if (0 == strcmp(sysname, "linux")) 213251881Speter sysver = "-gnu"; 214251881Speter else 215251881Speter { 216251881Speter err = svn_utf_cstring_to_utf8(&tmp, info.release, pool); 217251881Speter if (err) 218251881Speter svn_error_clear(err); 219251881Speter else 220251881Speter { 221251881Speter apr_size_t n = strspn(tmp, ".0123456789"); 222251881Speter if (n > 0) 223251881Speter { 224251881Speter char *ver = apr_pstrdup(pool, tmp); 225251881Speter ver[n] = 0; 226251881Speter sysver = ver; 227251881Speter } 228251881Speter else 229251881Speter sysver = tmp; 230251881Speter } 231251881Speter } 232251881Speter } 233251881Speter 234251881Speter return apr_psprintf(pool, "%s-%s-%s%s", machine, vendor, sysname, sysver); 235251881Speter} 236251881Speter 237251881Speter# ifndef SVN_HAVE_MACOS_PLIST 238251881Speter/* Generate a release name from the uname(3) info, effectively 239251881Speter returning "`uname -s` `uname -r`". */ 240251881Speterstatic const char * 241251881Speterrelease_name_from_uname(apr_pool_t *pool) 242251881Speter{ 243251881Speter struct utsname info; 244251881Speter if (0 <= uname(&info)) 245251881Speter { 246251881Speter svn_error_t *err; 247251881Speter const char *sysname; 248251881Speter const char *sysver; 249251881Speter 250251881Speter err = svn_utf_cstring_to_utf8(&sysname, info.sysname, pool); 251251881Speter if (err) 252251881Speter { 253251881Speter sysname = NULL; 254251881Speter svn_error_clear(err); 255251881Speter } 256251881Speter 257251881Speter 258251881Speter err = svn_utf_cstring_to_utf8(&sysver, info.release, pool); 259251881Speter if (err) 260251881Speter { 261251881Speter sysver = NULL; 262251881Speter svn_error_clear(err); 263251881Speter } 264251881Speter 265251881Speter if (sysname || sysver) 266251881Speter { 267251881Speter return apr_psprintf(pool, "%s%s%s", 268251881Speter (sysname ? sysname : ""), 269251881Speter (sysver ? (sysname ? " " : "") : ""), 270251881Speter (sysver ? sysver : "")); 271251881Speter } 272251881Speter } 273251881Speter return NULL; 274251881Speter} 275251881Speter# endif /* !SVN_HAVE_MACOS_PLIST */ 276251881Speter#endif /* HAVE_UNAME */ 277251881Speter 278251881Speter 279251881Speter#if __linux__ 280251881Speter/* Split a stringbuf into a key/value pair. 281251881Speter Return the key, leaving the striped value in the stringbuf. */ 282251881Speterstatic const char * 283251881Speterstringbuf_split_key(svn_stringbuf_t *buffer, char delim) 284251881Speter{ 285251881Speter char *key; 286251881Speter char *end; 287251881Speter 288251881Speter end = strchr(buffer->data, delim); 289251881Speter if (!end) 290251881Speter return NULL; 291251881Speter 292251881Speter svn_stringbuf_strip_whitespace(buffer); 293262250Speter 294262250Speter /* Now we split the currently allocated buffer in two parts: 295262250Speter - a const char * HEAD 296262250Speter - the remaining stringbuf_t. */ 297262250Speter 298262250Speter /* Create HEAD as '\0' terminated const char * */ 299251881Speter key = buffer->data; 300251881Speter end = strchr(key, delim); 301251881Speter *end = '\0'; 302262250Speter 303262250Speter /* And update the TAIL to be a smaller, but still valid stringbuf */ 304251881Speter buffer->data = end + 1; 305262250Speter buffer->len -= 1 + end - key; 306262250Speter buffer->blocksize -= 1 + end - key; 307262250Speter 308251881Speter svn_stringbuf_strip_whitespace(buffer); 309251881Speter 310251881Speter return key; 311251881Speter} 312251881Speter 313251881Speter/* Parse `/usr/bin/lsb_rlease --all` */ 314251881Speterstatic const char * 315251881Speterlsb_release(apr_pool_t *pool) 316251881Speter{ 317251881Speter static const char *const args[3] = 318251881Speter { 319251881Speter "/usr/bin/lsb_release", 320251881Speter "--all", 321251881Speter NULL 322251881Speter }; 323251881Speter 324251881Speter const char *distributor = NULL; 325251881Speter const char *description = NULL; 326251881Speter const char *release = NULL; 327251881Speter const char *codename = NULL; 328251881Speter 329251881Speter apr_proc_t lsbproc; 330251881Speter svn_stream_t *lsbinfo; 331251881Speter svn_error_t *err; 332251881Speter 333251881Speter /* Run /usr/bin/lsb_release --all < /dev/null 2>/dev/null */ 334251881Speter { 335251881Speter apr_file_t *stdin_handle; 336251881Speter apr_file_t *stdout_handle; 337251881Speter 338251881Speter err = svn_io_file_open(&stdin_handle, SVN_NULL_DEVICE_NAME, 339251881Speter APR_READ, APR_OS_DEFAULT, pool); 340251881Speter if (!err) 341251881Speter err = svn_io_file_open(&stdout_handle, SVN_NULL_DEVICE_NAME, 342251881Speter APR_WRITE, APR_OS_DEFAULT, pool); 343251881Speter if (!err) 344251881Speter err = svn_io_start_cmd3(&lsbproc, NULL, args[0], args, NULL, FALSE, 345251881Speter FALSE, stdin_handle, 346251881Speter TRUE, NULL, 347251881Speter FALSE, stdout_handle, 348251881Speter pool); 349251881Speter if (err) 350251881Speter { 351251881Speter svn_error_clear(err); 352251881Speter return NULL; 353251881Speter } 354251881Speter } 355251881Speter 356251881Speter /* Parse the output and try to populate the */ 357251881Speter lsbinfo = svn_stream_from_aprfile2(lsbproc.out, TRUE, pool); 358251881Speter if (lsbinfo) 359251881Speter { 360251881Speter for (;;) 361251881Speter { 362251881Speter svn_boolean_t eof = FALSE; 363251881Speter svn_stringbuf_t *line; 364251881Speter const char *key; 365251881Speter 366251881Speter err = svn_stream_readline(lsbinfo, &line, "\n", &eof, pool); 367251881Speter if (err || eof) 368251881Speter break; 369251881Speter 370251881Speter key = stringbuf_split_key(line, ':'); 371251881Speter if (!key) 372251881Speter continue; 373251881Speter 374251881Speter if (0 == svn_cstring_casecmp(key, "Distributor ID")) 375251881Speter distributor = line->data; 376251881Speter else if (0 == svn_cstring_casecmp(key, "Description")) 377251881Speter description = line->data; 378251881Speter else if (0 == svn_cstring_casecmp(key, "Release")) 379251881Speter release = line->data; 380251881Speter else if (0 == svn_cstring_casecmp(key, "Codename")) 381251881Speter codename = line->data; 382251881Speter } 383251881Speter err = svn_error_compose_create(err, 384251881Speter svn_stream_close(lsbinfo)); 385251881Speter if (err) 386251881Speter { 387251881Speter svn_error_clear(err); 388251881Speter apr_proc_kill(&lsbproc, SIGKILL); 389251881Speter return NULL; 390251881Speter } 391251881Speter } 392251881Speter 393251881Speter /* Reap the child process */ 394251881Speter err = svn_io_wait_for_cmd(&lsbproc, "", NULL, NULL, pool); 395251881Speter if (err) 396251881Speter { 397251881Speter svn_error_clear(err); 398251881Speter return NULL; 399251881Speter } 400251881Speter 401251881Speter if (description) 402251881Speter return apr_psprintf(pool, "%s%s%s%s", description, 403251881Speter (codename ? " (" : ""), 404251881Speter (codename ? codename : ""), 405251881Speter (codename ? ")" : "")); 406251881Speter if (distributor) 407251881Speter return apr_psprintf(pool, "%s%s%s%s%s%s", distributor, 408251881Speter (release ? " " : ""), 409251881Speter (release ? release : ""), 410251881Speter (codename ? " (" : ""), 411251881Speter (codename ? codename : ""), 412251881Speter (codename ? ")" : "")); 413251881Speter 414251881Speter return NULL; 415251881Speter} 416251881Speter 417251881Speter/* Read the whole contents of a file. */ 418251881Speterstatic svn_stringbuf_t * 419251881Speterread_file_contents(const char *filename, apr_pool_t *pool) 420251881Speter{ 421251881Speter svn_error_t *err; 422251881Speter svn_stringbuf_t *buffer; 423251881Speter 424251881Speter err = svn_stringbuf_from_file2(&buffer, filename, pool); 425251881Speter if (err) 426251881Speter { 427251881Speter svn_error_clear(err); 428251881Speter return NULL; 429251881Speter } 430251881Speter 431251881Speter return buffer; 432251881Speter} 433251881Speter 434251881Speter/* Strip everything but the first line from a stringbuf. */ 435251881Speterstatic void 436251881Speterstringbuf_first_line_only(svn_stringbuf_t *buffer) 437251881Speter{ 438251881Speter char *eol = strchr(buffer->data, '\n'); 439251881Speter if (eol) 440251881Speter { 441251881Speter *eol = '\0'; 442251881Speter buffer->len = 1 + eol - buffer->data; 443251881Speter } 444251881Speter svn_stringbuf_strip_whitespace(buffer); 445251881Speter} 446251881Speter 447251881Speter/* Look at /etc/redhat_release to detect RHEL/Fedora/CentOS. */ 448251881Speterstatic const char * 449251881Speterredhat_release(apr_pool_t *pool) 450251881Speter{ 451251881Speter svn_stringbuf_t *buffer = read_file_contents("/etc/redhat-release", pool); 452251881Speter if (buffer) 453251881Speter { 454251881Speter stringbuf_first_line_only(buffer); 455251881Speter return buffer->data; 456251881Speter } 457251881Speter return NULL; 458251881Speter} 459251881Speter 460251881Speter/* Look at /etc/SuSE-release to detect non-LSB SuSE. */ 461251881Speterstatic const char * 462251881Spetersuse_release(apr_pool_t *pool) 463251881Speter{ 464251881Speter const char *release = NULL; 465251881Speter const char *codename = NULL; 466251881Speter 467251881Speter svn_stringbuf_t *buffer = read_file_contents("/etc/SuSE-release", pool); 468251881Speter svn_stringbuf_t *line; 469251881Speter svn_stream_t *stream; 470251881Speter svn_boolean_t eof; 471251881Speter svn_error_t *err; 472251881Speter if (!buffer) 473251881Speter return NULL; 474251881Speter 475251881Speter stream = svn_stream_from_stringbuf(buffer, pool); 476251881Speter err = svn_stream_readline(stream, &line, "\n", &eof, pool); 477251881Speter if (err || eof) 478251881Speter { 479251881Speter svn_error_clear(err); 480251881Speter return NULL; 481251881Speter } 482251881Speter 483251881Speter svn_stringbuf_strip_whitespace(line); 484251881Speter release = line->data; 485251881Speter 486251881Speter for (;;) 487251881Speter { 488251881Speter const char *key; 489251881Speter 490251881Speter err = svn_stream_readline(stream, &line, "\n", &eof, pool); 491251881Speter if (err || eof) 492251881Speter { 493251881Speter svn_error_clear(err); 494251881Speter break; 495251881Speter } 496251881Speter 497251881Speter key = stringbuf_split_key(line, '='); 498251881Speter if (!key) 499251881Speter continue; 500251881Speter 501251881Speter if (0 == strncmp(key, "CODENAME", 8)) 502251881Speter codename = line->data; 503251881Speter } 504251881Speter 505251881Speter return apr_psprintf(pool, "%s%s%s%s", 506251881Speter release, 507251881Speter (codename ? " (" : ""), 508251881Speter (codename ? codename : ""), 509251881Speter (codename ? ")" : "")); 510251881Speter} 511251881Speter 512251881Speter/* Look at /etc/debian_version to detect non-LSB Debian. */ 513251881Speterstatic const char * 514251881Speterdebian_release(apr_pool_t *pool) 515251881Speter{ 516251881Speter svn_stringbuf_t *buffer = read_file_contents("/etc/debian_version", pool); 517251881Speter if (!buffer) 518251881Speter return NULL; 519251881Speter 520251881Speter stringbuf_first_line_only(buffer); 521251881Speter return apr_pstrcat(pool, "Debian ", buffer->data, NULL); 522251881Speter} 523251881Speter 524251881Speter/* Try to find the Linux distribution name, or return info from uname. */ 525251881Speterstatic const char * 526251881Speterlinux_release_name(apr_pool_t *pool) 527251881Speter{ 528251881Speter const char *uname_release = release_name_from_uname(pool); 529251881Speter 530251881Speter /* Try anything that has /usr/bin/lsb_release. 531251881Speter Covers, for example, Debian, Ubuntu and SuSE. */ 532251881Speter const char *release_name = lsb_release(pool); 533251881Speter 534251881Speter /* Try RHEL/Fedora/CentOS */ 535251881Speter if (!release_name) 536251881Speter release_name = redhat_release(pool); 537251881Speter 538251881Speter /* Try Non-LSB SuSE */ 539251881Speter if (!release_name) 540251881Speter release_name = suse_release(pool); 541251881Speter 542251881Speter /* Try non-LSB Debian */ 543251881Speter if (!release_name) 544251881Speter release_name = debian_release(pool); 545251881Speter 546251881Speter if (!release_name) 547251881Speter return uname_release; 548251881Speter 549251881Speter if (!uname_release) 550251881Speter return release_name; 551251881Speter 552251881Speter return apr_psprintf(pool, "%s [%s]", release_name, uname_release); 553251881Speter} 554251881Speter#endif /* __linux__ */ 555251881Speter 556251881Speter 557251881Speter#ifdef WIN32 558251881Spetertypedef DWORD (WINAPI *FNGETNATIVESYSTEMINFO)(LPSYSTEM_INFO); 559257936Spetertypedef BOOL (WINAPI *FNENUMPROCESSMODULES) (HANDLE, HMODULE*, DWORD, LPDWORD); 560251881Speter 561251881Speter/* Get system and version info, and try to tell the difference 562251881Speter between the native system type and the runtime environment of the 563251881Speter current process. Populate results in SYSINFO, LOCAL_SYSINFO 564251881Speter (optional) and OSINFO. */ 565251881Speterstatic BOOL 566251881Spetersystem_info(SYSTEM_INFO *sysinfo, 567251881Speter SYSTEM_INFO *local_sysinfo, 568251881Speter OSVERSIONINFOEXW *osinfo) 569251881Speter{ 570251881Speter FNGETNATIVESYSTEMINFO GetNativeSystemInfo_ = (FNGETNATIVESYSTEMINFO) 571251881Speter GetProcAddress(GetModuleHandleA("kernel32.dll"), "GetNativeSystemInfo"); 572251881Speter 573251881Speter ZeroMemory(sysinfo, sizeof *sysinfo); 574251881Speter if (local_sysinfo) 575251881Speter { 576251881Speter ZeroMemory(local_sysinfo, sizeof *local_sysinfo); 577251881Speter GetSystemInfo(local_sysinfo); 578251881Speter if (GetNativeSystemInfo_) 579251881Speter GetNativeSystemInfo_(sysinfo); 580251881Speter else 581251881Speter memcpy(sysinfo, local_sysinfo, sizeof *sysinfo); 582251881Speter } 583251881Speter else 584251881Speter GetSystemInfo(sysinfo); 585251881Speter 586251881Speter ZeroMemory(osinfo, sizeof *osinfo); 587251881Speter osinfo->dwOSVersionInfoSize = sizeof *osinfo; 588251881Speter if (!GetVersionExW((LPVOID)osinfo)) 589251881Speter return FALSE; 590251881Speter 591251881Speter return TRUE; 592251881Speter} 593251881Speter 594251881Speter/* Map the proccessor type from SYSINFO to a string. */ 595251881Speterstatic const char * 596251881Speterprocessor_name(SYSTEM_INFO *sysinfo) 597251881Speter{ 598251881Speter switch (sysinfo->wProcessorArchitecture) 599251881Speter { 600251881Speter case PROCESSOR_ARCHITECTURE_AMD64: return "x86_64"; 601251881Speter case PROCESSOR_ARCHITECTURE_IA64: return "ia64"; 602251881Speter case PROCESSOR_ARCHITECTURE_INTEL: return "x86"; 603251881Speter case PROCESSOR_ARCHITECTURE_MIPS: return "mips"; 604251881Speter case PROCESSOR_ARCHITECTURE_ALPHA: return "alpha32"; 605251881Speter case PROCESSOR_ARCHITECTURE_PPC: return "powerpc"; 606251881Speter case PROCESSOR_ARCHITECTURE_SHX: return "shx"; 607251881Speter case PROCESSOR_ARCHITECTURE_ARM: return "arm"; 608251881Speter case PROCESSOR_ARCHITECTURE_ALPHA64: return "alpha"; 609251881Speter case PROCESSOR_ARCHITECTURE_MSIL: return "msil"; 610251881Speter case PROCESSOR_ARCHITECTURE_IA32_ON_WIN64: return "x86_wow64"; 611251881Speter default: return "unknown"; 612251881Speter } 613251881Speter} 614251881Speter 615251881Speter/* Return the Windows-specific canonical host name. */ 616251881Speterstatic const char * 617251881Speterwin32_canonical_host(apr_pool_t *pool) 618251881Speter{ 619251881Speter SYSTEM_INFO sysinfo; 620251881Speter SYSTEM_INFO local_sysinfo; 621251881Speter OSVERSIONINFOEXW osinfo; 622251881Speter 623251881Speter if (system_info(&sysinfo, &local_sysinfo, &osinfo)) 624251881Speter { 625251881Speter const char *arch = processor_name(&local_sysinfo); 626251881Speter const char *machine = processor_name(&sysinfo); 627251881Speter const char *vendor = "microsoft"; 628251881Speter const char *sysname = "windows"; 629251881Speter const char *sysver = apr_psprintf(pool, "%u.%u.%u", 630251881Speter (unsigned int)osinfo.dwMajorVersion, 631251881Speter (unsigned int)osinfo.dwMinorVersion, 632251881Speter (unsigned int)osinfo.dwBuildNumber); 633251881Speter 634251881Speter if (sysinfo.wProcessorArchitecture 635251881Speter == local_sysinfo.wProcessorArchitecture) 636251881Speter return apr_psprintf(pool, "%s-%s-%s%s", 637251881Speter machine, vendor, sysname, sysver); 638251881Speter return apr_psprintf(pool, "%s/%s-%s-%s%s", 639251881Speter arch, machine, vendor, sysname, sysver); 640251881Speter } 641251881Speter 642251881Speter return "unknown-microsoft-windows"; 643251881Speter} 644251881Speter 645251881Speter/* Convert a Unicode string to UTF-8. */ 646251881Speterstatic char * 647251881Speterwcs_to_utf8(const wchar_t *wcs, apr_pool_t *pool) 648251881Speter{ 649251881Speter const int bufsize = WideCharToMultiByte(CP_UTF8, 0, wcs, -1, 650251881Speter NULL, 0, NULL, NULL); 651251881Speter if (bufsize > 0) 652251881Speter { 653251881Speter char *const utf8 = apr_palloc(pool, bufsize + 1); 654251881Speter WideCharToMultiByte(CP_UTF8, 0, wcs, -1, utf8, bufsize, NULL, NULL); 655251881Speter return utf8; 656251881Speter } 657251881Speter return NULL; 658251881Speter} 659251881Speter 660251881Speter/* Query the value called NAME of the registry key HKEY. */ 661251881Speterstatic char * 662251881Speterregistry_value(HKEY hkey, wchar_t *name, apr_pool_t *pool) 663251881Speter{ 664251881Speter DWORD size; 665251881Speter wchar_t *value; 666251881Speter 667251881Speter if (RegQueryValueExW(hkey, name, NULL, NULL, NULL, &size)) 668251881Speter return NULL; 669251881Speter 670251881Speter value = apr_palloc(pool, size + sizeof *value); 671251881Speter if (RegQueryValueExW(hkey, name, NULL, NULL, (void*)value, &size)) 672251881Speter return NULL; 673251881Speter value[size / sizeof *value] = 0; 674251881Speter return wcs_to_utf8(value, pool); 675251881Speter} 676251881Speter 677251881Speter/* Try to glean the Windows release name and associated info from the 678251881Speter registry. Failing that, construct a release name from the version 679251881Speter info. */ 680251881Speterstatic const char * 681251881Speterwin32_release_name(apr_pool_t *pool) 682251881Speter{ 683251881Speter SYSTEM_INFO sysinfo; 684251881Speter OSVERSIONINFOEXW osinfo; 685251881Speter HKEY hkcv; 686251881Speter 687251881Speter if (!system_info(&sysinfo, NULL, &osinfo)) 688251881Speter return NULL; 689251881Speter 690251881Speter if (!RegOpenKeyExW(HKEY_LOCAL_MACHINE, 691251881Speter L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 692251881Speter 0, KEY_QUERY_VALUE, &hkcv)) 693251881Speter { 694251881Speter const char *release = registry_value(hkcv, L"ProductName", pool); 695251881Speter const char *spack = registry_value(hkcv, L"CSDVersion", pool); 696251881Speter const char *curver = registry_value(hkcv, L"CurrentVersion", pool); 697251881Speter const char *curtype = registry_value(hkcv, L"CurrentType", pool); 698251881Speter const char *install = registry_value(hkcv, L"InstallationType", pool); 699251881Speter const char *curbuild = registry_value(hkcv, L"CurrentBuildNumber", pool); 700251881Speter 701251881Speter if (!spack && *osinfo.szCSDVersion) 702251881Speter spack = wcs_to_utf8(osinfo.szCSDVersion, pool); 703251881Speter 704251881Speter if (!curbuild) 705251881Speter curbuild = registry_value(hkcv, L"CurrentBuild", pool); 706251881Speter 707251881Speter if (release || spack || curver || curtype || curbuild) 708251881Speter { 709251881Speter const char *bootinfo = ""; 710251881Speter if (curver || install || curtype) 711251881Speter { 712251881Speter bootinfo = apr_psprintf(pool, "[%s%s%s%s%s]", 713251881Speter (curver ? curver : ""), 714251881Speter (install ? (curver ? " " : "") : ""), 715251881Speter (install ? install : ""), 716251881Speter (curtype 717251881Speter ? (curver||install ? " " : "") 718251881Speter : ""), 719251881Speter (curtype ? curtype : "")); 720251881Speter } 721251881Speter 722251881Speter return apr_psprintf(pool, "%s%s%s%s%s%s%s", 723251881Speter (release ? release : ""), 724251881Speter (spack ? (release ? ", " : "") : ""), 725251881Speter (spack ? spack : ""), 726251881Speter (curbuild 727251881Speter ? (release||spack ? ", build " : "build ") 728251881Speter : ""), 729251881Speter (curbuild ? curbuild : ""), 730251881Speter (bootinfo 731251881Speter ? (release||spack||curbuild ? " " : "") 732251881Speter : ""), 733251881Speter (bootinfo ? bootinfo : "")); 734251881Speter } 735251881Speter } 736251881Speter 737251881Speter if (*osinfo.szCSDVersion) 738251881Speter { 739251881Speter const char *servicepack = wcs_to_utf8(osinfo.szCSDVersion, pool); 740251881Speter 741251881Speter if (servicepack) 742251881Speter return apr_psprintf(pool, "Windows NT %u.%u, %s, build %u", 743251881Speter (unsigned int)osinfo.dwMajorVersion, 744251881Speter (unsigned int)osinfo.dwMinorVersion, 745251881Speter servicepack, 746251881Speter (unsigned int)osinfo.dwBuildNumber); 747251881Speter 748251881Speter /* Assume wServicePackMajor > 0 if szCSDVersion is not empty */ 749251881Speter if (osinfo.wServicePackMinor) 750251881Speter return apr_psprintf(pool, "Windows NT %u.%u SP%u.%u, build %u", 751251881Speter (unsigned int)osinfo.dwMajorVersion, 752251881Speter (unsigned int)osinfo.dwMinorVersion, 753251881Speter (unsigned int)osinfo.wServicePackMajor, 754251881Speter (unsigned int)osinfo.wServicePackMinor, 755251881Speter (unsigned int)osinfo.dwBuildNumber); 756251881Speter 757251881Speter return apr_psprintf(pool, "Windows NT %u.%u SP%u, build %u", 758251881Speter (unsigned int)osinfo.dwMajorVersion, 759251881Speter (unsigned int)osinfo.dwMinorVersion, 760251881Speter (unsigned int)osinfo.wServicePackMajor, 761251881Speter (unsigned int)osinfo.dwBuildNumber); 762251881Speter } 763251881Speter 764251881Speter return apr_psprintf(pool, "Windows NT %u.%u, build %u", 765251881Speter (unsigned int)osinfo.dwMajorVersion, 766251881Speter (unsigned int)osinfo.dwMinorVersion, 767251881Speter (unsigned int)osinfo.dwBuildNumber); 768251881Speter} 769251881Speter 770251881Speter 771251881Speter/* Get a list of handles of shared libs loaded by the current 772251881Speter process. Returns a NULL-terminated array alocated from POOL. */ 773251881Speterstatic HMODULE * 774251881Speterenum_loaded_modules(apr_pool_t *pool) 775251881Speter{ 776257936Speter HMODULE psapi_dll = 0; 777251881Speter HANDLE current = GetCurrentProcess(); 778251881Speter HMODULE dummy[1]; 779251881Speter HMODULE *handles; 780251881Speter DWORD size; 781257936Speter FNENUMPROCESSMODULES EnumProcessModules_; 782251881Speter 783257936Speter psapi_dll = GetModuleHandleA("psapi.dll"); 784257936Speter 785257936Speter if (!psapi_dll) 786257936Speter { 787257936Speter /* Load and never unload, just like static linking */ 788257936Speter psapi_dll = LoadLibraryA("psapi.dll"); 789257936Speter } 790257936Speter 791257936Speter if (!psapi_dll) 792257936Speter return NULL; 793257936Speter 794257936Speter EnumProcessModules_ = (FNENUMPROCESSMODULES) 795257936Speter GetProcAddress(psapi_dll, "EnumProcessModules"); 796257936Speter 797257936Speter /* Before Windows XP psapi was an optional module */ 798257936Speter if (! EnumProcessModules_) 799251881Speter return NULL; 800251881Speter 801257936Speter if (!EnumProcessModules_(current, dummy, sizeof(dummy), &size)) 802257936Speter return NULL; 803257936Speter 804251881Speter handles = apr_palloc(pool, size + sizeof *handles); 805257936Speter if (! EnumProcessModules_(current, handles, size, &size)) 806251881Speter return NULL; 807251881Speter handles[size / sizeof *handles] = NULL; 808251881Speter return handles; 809251881Speter} 810251881Speter 811251881Speter/* Find the version number, if any, embedded in FILENAME. */ 812251881Speterstatic const char * 813251881Speterfile_version_number(const wchar_t *filename, apr_pool_t *pool) 814251881Speter{ 815251881Speter VS_FIXEDFILEINFO info; 816251881Speter unsigned int major, minor, micro, nano; 817251881Speter void *data; 818251881Speter DWORD data_size = GetFileVersionInfoSizeW(filename, NULL); 819251881Speter void *vinfo; 820251881Speter UINT vinfo_size; 821251881Speter 822251881Speter if (!data_size) 823251881Speter return NULL; 824251881Speter 825251881Speter data = apr_palloc(pool, data_size); 826251881Speter if (!GetFileVersionInfoW(filename, 0, data_size, data)) 827251881Speter return NULL; 828251881Speter 829251881Speter if (!VerQueryValueW(data, L"\\", &vinfo, &vinfo_size)) 830251881Speter return NULL; 831251881Speter 832251881Speter if (vinfo_size != sizeof info) 833251881Speter return NULL; 834251881Speter 835251881Speter memcpy(&info, vinfo, sizeof info); 836251881Speter major = (info.dwFileVersionMS >> 16) & 0xFFFF; 837251881Speter minor = info.dwFileVersionMS & 0xFFFF; 838251881Speter micro = (info.dwFileVersionLS >> 16) & 0xFFFF; 839251881Speter nano = info.dwFileVersionLS & 0xFFFF; 840251881Speter 841251881Speter if (!nano) 842251881Speter { 843251881Speter if (!micro) 844251881Speter return apr_psprintf(pool, "%u.%u", major, minor); 845251881Speter else 846251881Speter return apr_psprintf(pool, "%u.%u.%u", major, minor, micro); 847251881Speter } 848251881Speter return apr_psprintf(pool, "%u.%u.%u.%u", major, minor, micro, nano); 849251881Speter} 850251881Speter 851251881Speter/* List the shared libraries loaded by the current process. */ 852251881Speterstatic const apr_array_header_t * 853251881Speterwin32_shared_libs(apr_pool_t *pool) 854251881Speter{ 855251881Speter apr_array_header_t *array = NULL; 856251881Speter wchar_t buffer[MAX_PATH + 1]; 857251881Speter HMODULE *handles = enum_loaded_modules(pool); 858251881Speter HMODULE *module; 859251881Speter 860251881Speter for (module = handles; module && *module; ++module) 861251881Speter { 862251881Speter const char *filename; 863251881Speter const char *version; 864251881Speter if (GetModuleFileNameW(*module, buffer, MAX_PATH)) 865251881Speter { 866251881Speter buffer[MAX_PATH] = 0; 867251881Speter 868251881Speter version = file_version_number(buffer, pool); 869251881Speter filename = wcs_to_utf8(buffer, pool); 870251881Speter if (filename) 871251881Speter { 872251881Speter svn_version_ext_loaded_lib_t *lib; 873251881Speter 874251881Speter if (!array) 875251881Speter { 876251881Speter array = apr_array_make(pool, 32, sizeof(*lib)); 877251881Speter } 878251881Speter lib = &APR_ARRAY_PUSH(array, svn_version_ext_loaded_lib_t); 879251881Speter lib->name = svn_dirent_local_style(filename, pool); 880251881Speter lib->version = version; 881251881Speter } 882251881Speter } 883251881Speter } 884251881Speter 885251881Speter return array; 886251881Speter} 887251881Speter#endif /* WIN32 */ 888251881Speter 889251881Speter 890251881Speter#ifdef SVN_HAVE_MACOS_PLIST 891251881Speter/* Load the SystemVersion.plist or ServerVersion.plist file into a 892251881Speter property list. Set SERVER to TRUE if the file read was 893251881Speter ServerVersion.plist. */ 894251881Speterstatic CFDictionaryRef 895251881Spetersystem_version_plist(svn_boolean_t *server, apr_pool_t *pool) 896251881Speter{ 897251881Speter static const UInt8 server_version[] = 898251881Speter "/System/Library/CoreServices/ServerVersion.plist"; 899251881Speter static const UInt8 system_version[] = 900251881Speter "/System/Library/CoreServices/SystemVersion.plist"; 901251881Speter 902251881Speter CFPropertyListRef plist = NULL; 903251881Speter CFDataRef resource = NULL; 904251881Speter CFStringRef errstr = NULL; 905251881Speter CFURLRef url = NULL; 906251881Speter SInt32 errcode; 907251881Speter 908251881Speter url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, 909251881Speter server_version, 910251881Speter sizeof(server_version) - 1, 911251881Speter FALSE); 912251881Speter if (!url) 913251881Speter return NULL; 914251881Speter 915251881Speter if (!CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault, 916251881Speter url, &resource, 917251881Speter NULL, NULL, &errcode)) 918251881Speter { 919251881Speter CFRelease(url); 920251881Speter url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, 921251881Speter system_version, 922251881Speter sizeof(system_version) - 1, 923251881Speter FALSE); 924251881Speter if (!url) 925251881Speter return NULL; 926251881Speter 927251881Speter if (!CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault, 928251881Speter url, &resource, 929251881Speter NULL, NULL, &errcode)) 930251881Speter { 931251881Speter CFRelease(url); 932251881Speter return NULL; 933251881Speter } 934251881Speter else 935251881Speter { 936251881Speter CFRelease(url); 937251881Speter *server = FALSE; 938251881Speter } 939251881Speter } 940251881Speter else 941251881Speter { 942251881Speter CFRelease(url); 943251881Speter *server = TRUE; 944251881Speter } 945251881Speter 946251881Speter /* ### CFPropertyListCreateFromXMLData is obsolete, but its 947251881Speter replacement CFPropertyListCreateWithData is only available 948251881Speter from Mac OS 1.6 onward. */ 949251881Speter plist = CFPropertyListCreateFromXMLData(kCFAllocatorDefault, resource, 950251881Speter kCFPropertyListImmutable, 951251881Speter &errstr); 952251881Speter if (resource) 953251881Speter CFRelease(resource); 954251881Speter if (errstr) 955251881Speter CFRelease(errstr); 956251881Speter 957251881Speter if (CFDictionaryGetTypeID() != CFGetTypeID(plist)) 958251881Speter { 959251881Speter /* Oops ... this really should be a dict. */ 960251881Speter CFRelease(plist); 961251881Speter return NULL; 962251881Speter } 963251881Speter 964251881Speter return plist; 965251881Speter} 966251881Speter 967251881Speter/* Return the value for KEY from PLIST, or NULL if not available. */ 968251881Speterstatic const char * 969251881Spetervalue_from_dict(CFDictionaryRef plist, CFStringRef key, apr_pool_t *pool) 970251881Speter{ 971251881Speter CFStringRef valref; 972251881Speter CFIndex bufsize; 973251881Speter const void *valptr; 974251881Speter const char *value; 975251881Speter 976251881Speter if (!CFDictionaryGetValueIfPresent(plist, key, &valptr)) 977251881Speter return NULL; 978251881Speter 979251881Speter valref = valptr; 980251881Speter if (CFStringGetTypeID() != CFGetTypeID(valref)) 981251881Speter return NULL; 982251881Speter 983251881Speter value = CFStringGetCStringPtr(valref, kCFStringEncodingUTF8); 984251881Speter if (value) 985251881Speter return apr_pstrdup(pool, value); 986251881Speter 987251881Speter bufsize = 5 * CFStringGetLength(valref) + 1; 988251881Speter value = apr_palloc(pool, bufsize); 989251881Speter if (!CFStringGetCString(valref, (char*)value, bufsize, 990251881Speter kCFStringEncodingUTF8)) 991251881Speter value = NULL; 992251881Speter 993251881Speter return value; 994251881Speter} 995251881Speter 996251881Speter/* Return the commercial name of the OS, given the version number in 997251881Speter a format that matches the regular expression /^10\.\d+(\..*)?$/ */ 998251881Speterstatic const char * 999251881Speterrelease_name_from_version(const char *osver) 1000251881Speter{ 1001251881Speter char *end = NULL; 1002251881Speter unsigned long num = strtoul(osver, &end, 10); 1003251881Speter 1004251881Speter if (!end || *end != '.' || num != 10) 1005251881Speter return NULL; 1006251881Speter 1007251881Speter osver = end + 1; 1008251881Speter end = NULL; 1009251881Speter num = strtoul(osver, &end, 10); 1010251881Speter if (!end || (*end && *end != '.')) 1011251881Speter return NULL; 1012251881Speter 1013251881Speter /* See http://en.wikipedia.org/wiki/History_of_OS_X#Release_timeline */ 1014251881Speter switch(num) 1015251881Speter { 1016251881Speter case 0: return "Cheetah"; 1017251881Speter case 1: return "Puma"; 1018251881Speter case 2: return "Jaguar"; 1019251881Speter case 3: return "Panther"; 1020251881Speter case 4: return "Tiger"; 1021251881Speter case 5: return "Leopard"; 1022251881Speter case 6: return "Snow Leopard"; 1023251881Speter case 7: return "Lion"; 1024251881Speter case 8: return "Mountain Lion"; 1025251881Speter } 1026251881Speter 1027251881Speter return NULL; 1028251881Speter} 1029251881Speter 1030251881Speter/* Construct the release name from information stored in the Mac OS X 1031251881Speter "SystemVersion.plist" file (or ServerVersion.plist, for Mac Os 1032251881Speter Server. */ 1033251881Speterstatic const char * 1034251881Spetermacos_release_name(apr_pool_t *pool) 1035251881Speter{ 1036251881Speter svn_boolean_t server; 1037251881Speter CFDictionaryRef plist = system_version_plist(&server, pool); 1038251881Speter 1039251881Speter if (plist) 1040251881Speter { 1041251881Speter const char *osname = value_from_dict(plist, CFSTR("ProductName"), pool); 1042251881Speter const char *osver = value_from_dict(plist, 1043251881Speter CFSTR("ProductUserVisibleVersion"), 1044251881Speter pool); 1045251881Speter const char *build = value_from_dict(plist, 1046251881Speter CFSTR("ProductBuildVersion"), 1047251881Speter pool); 1048251881Speter const char *release; 1049251881Speter 1050251881Speter if (!osver) 1051251881Speter osver = value_from_dict(plist, CFSTR("ProductVersion"), pool); 1052251881Speter release = release_name_from_version(osver); 1053251881Speter 1054251881Speter CFRelease(plist); 1055251881Speter return apr_psprintf(pool, "%s%s%s%s%s%s%s%s", 1056251881Speter (osname ? osname : ""), 1057251881Speter (osver ? (osname ? " " : "") : ""), 1058251881Speter (osver ? osver : ""), 1059251881Speter (release ? (osname||osver ? " " : "") : ""), 1060251881Speter (release ? release : ""), 1061251881Speter (build 1062251881Speter ? (osname||osver||release ? ", " : "") 1063251881Speter : ""), 1064251881Speter (build 1065251881Speter ? (server ? "server build " : "build ") 1066251881Speter : ""), 1067251881Speter (build ? build : "")); 1068251881Speter } 1069251881Speter 1070251881Speter return NULL; 1071251881Speter} 1072251881Speter#endif /* SVN_HAVE_MACOS_PLIST */ 1073251881Speter 1074251881Speter#ifdef SVN_HAVE_MACHO_ITERATE 1075251881Speter/* List the shared libraries loaded by the current process. 1076251881Speter Ignore frameworks and system libraries, they're just clutter. */ 1077251881Speterstatic const apr_array_header_t * 1078251881Spetermacos_shared_libs(apr_pool_t *pool) 1079251881Speter{ 1080251881Speter static const char slb_prefix[] = "/usr/lib/system/"; 1081251881Speter static const char fwk_prefix[] = "/System/Library/Frameworks/"; 1082251881Speter static const char pfk_prefix[] = "/System/Library/PrivateFrameworks/"; 1083251881Speter 1084251881Speter const size_t slb_prefix_len = strlen(slb_prefix); 1085251881Speter const size_t fwk_prefix_len = strlen(fwk_prefix); 1086251881Speter const size_t pfk_prefix_len = strlen(pfk_prefix); 1087251881Speter 1088251881Speter apr_array_header_t *result = NULL; 1089251881Speter apr_array_header_t *dylibs = NULL; 1090251881Speter 1091251881Speter uint32_t i; 1092251881Speter for (i = 0;; ++i) 1093251881Speter { 1094251881Speter const struct mach_header *header = _dyld_get_image_header(i); 1095251881Speter const char *filename = _dyld_get_image_name(i); 1096251881Speter const char *version; 1097251881Speter char *truename; 1098251881Speter svn_version_ext_loaded_lib_t *lib; 1099251881Speter 1100251881Speter if (!(header && filename)) 1101251881Speter break; 1102251881Speter 1103251881Speter switch (header->cputype) 1104251881Speter { 1105251881Speter case CPU_TYPE_I386: version = _("Intel"); break; 1106251881Speter case CPU_TYPE_X86_64: version = _("Intel 64-bit"); break; 1107251881Speter case CPU_TYPE_POWERPC: version = _("PowerPC"); break; 1108251881Speter case CPU_TYPE_POWERPC64: version = _("PowerPC 64-bit"); break; 1109251881Speter default: 1110251881Speter version = NULL; 1111251881Speter } 1112251881Speter 1113251881Speter if (0 == apr_filepath_merge(&truename, "", filename, 1114251881Speter APR_FILEPATH_NATIVE 1115251881Speter | APR_FILEPATH_TRUENAME, 1116251881Speter pool)) 1117251881Speter filename = truename; 1118251881Speter else 1119251881Speter filename = apr_pstrdup(pool, filename); 1120251881Speter 1121251881Speter if (0 == strncmp(filename, slb_prefix, slb_prefix_len) 1122251881Speter || 0 == strncmp(filename, fwk_prefix, fwk_prefix_len) 1123251881Speter || 0 == strncmp(filename, pfk_prefix, pfk_prefix_len)) 1124251881Speter { 1125251881Speter /* Ignore frameworks and system libraries. */ 1126251881Speter continue; 1127251881Speter } 1128251881Speter 1129251881Speter if (header->filetype == MH_EXECUTE) 1130251881Speter { 1131251881Speter /* Make sure the program filename is first in the list */ 1132251881Speter if (!result) 1133251881Speter { 1134251881Speter result = apr_array_make(pool, 32, sizeof(*lib)); 1135251881Speter } 1136251881Speter lib = &APR_ARRAY_PUSH(result, svn_version_ext_loaded_lib_t); 1137251881Speter } 1138251881Speter else 1139251881Speter { 1140251881Speter if (!dylibs) 1141251881Speter { 1142251881Speter dylibs = apr_array_make(pool, 32, sizeof(*lib)); 1143251881Speter } 1144251881Speter lib = &APR_ARRAY_PUSH(dylibs, svn_version_ext_loaded_lib_t); 1145251881Speter } 1146251881Speter 1147251881Speter lib->name = filename; 1148251881Speter lib->version = version; 1149251881Speter } 1150251881Speter 1151251881Speter /* Gather results into one array. */ 1152251881Speter if (dylibs) 1153251881Speter { 1154251881Speter if (result) 1155251881Speter apr_array_cat(result, dylibs); 1156251881Speter else 1157251881Speter result = dylibs; 1158251881Speter } 1159251881Speter 1160251881Speter return result; 1161251881Speter} 1162251881Speter#endif /* SVN_HAVE_MACHO_ITERATE */ 1163