version.c revision 289166
1/* 2 * version.c: library version number and utilities 3 * 4 * ==================================================================== 5 * Licensed to the Apache Software Foundation (ASF) under one 6 * or more contributor license agreements. See the NOTICE file 7 * distributed with this work for additional information 8 * regarding copyright ownership. The ASF licenses this file 9 * to you under the Apache License, Version 2.0 (the 10 * "License"); you may not use this file except in compliance 11 * with the License. You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, 16 * software distributed under the License is distributed on an 17 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 18 * KIND, either express or implied. See the License for the 19 * specific language governing permissions and limitations 20 * under the License. 21 * ==================================================================== 22 */ 23 24 25 26#include "svn_error.h" 27#include "svn_version.h" 28 29#include "sysinfo.h" 30#include "svn_private_config.h" 31#include "private/svn_subr_private.h" 32 33const svn_version_t * 34svn_subr_version(void) 35{ 36 SVN_VERSION_BODY; 37} 38 39 40svn_boolean_t svn_ver_compatible(const svn_version_t *my_version, 41 const svn_version_t *lib_version) 42{ 43 /* With normal development builds the matching rules are strict, to 44 avoid inadvertantly using the wrong libraries. For backward 45 compatibility testing use --disable-full-version-match to 46 configure 1.7 and then the libraries that get built can be used 47 to replace those in 1.6 or earlier builds. */ 48 49#ifndef SVN_DISABLE_FULL_VERSION_MATCH 50 if (lib_version->tag[0] != '\0') 51 /* Development library; require exact match. */ 52 return svn_ver_equal(my_version, lib_version); 53 else if (my_version->tag[0] != '\0') 54 /* Development client; must be newer than the library 55 and have the same major and minor version. */ 56 return (my_version->major == lib_version->major 57 && my_version->minor == lib_version->minor 58 && my_version->patch > lib_version->patch); 59#endif 60 61 /* General compatibility rules for released versions. */ 62 return (my_version->major == lib_version->major 63 && my_version->minor <= lib_version->minor); 64} 65 66 67svn_boolean_t svn_ver_equal(const svn_version_t *my_version, 68 const svn_version_t *lib_version) 69{ 70 return (my_version->major == lib_version->major 71 && my_version->minor == lib_version->minor 72 && my_version->patch == lib_version->patch 73 && 0 == strcmp(my_version->tag, lib_version->tag)); 74} 75 76 77svn_error_t * 78svn_ver__check_list2(const svn_version_t *my_version, 79 const svn_version_checklist_t *checklist, 80 svn_boolean_t (*comparator)(const svn_version_t *, 81 const svn_version_t *)) 82{ 83 svn_error_t *err = SVN_NO_ERROR; 84 int i; 85 86 for (i = 0; checklist[i].label != NULL; ++i) 87 { 88 const svn_version_t *lib_version = checklist[i].version_query(); 89 if (!comparator(my_version, lib_version)) 90 err = svn_error_createf(SVN_ERR_VERSION_MISMATCH, err, 91 _("Version mismatch in '%s'%s:" 92 " found %d.%d.%d%s," 93 " expected %d.%d.%d%s"), 94 checklist[i].label, 95 comparator == svn_ver_equal 96 ? _(" (expecting equality)") 97 : comparator == svn_ver_compatible 98 ? _(" (expecting compatibility)") 99 : "", 100 lib_version->major, lib_version->minor, 101 lib_version->patch, lib_version->tag, 102 my_version->major, my_version->minor, 103 my_version->patch, my_version->tag); 104 } 105 106 return err; 107} 108 109 110struct svn_version_extended_t 111{ 112 const char *build_date; /* Compilation date */ 113 const char *build_time; /* Compilation time */ 114 const char *build_host; /* Build canonical host name */ 115 const char *copyright; /* Copyright notice (localized) */ 116 const char *runtime_host; /* Runtime canonical host name */ 117 const char *runtime_osname; /* Running OS release name */ 118 119 /* Array of svn_version_ext_linked_lib_t describing dependent 120 libraries. */ 121 const apr_array_header_t *linked_libs; 122 123 /* Array of svn_version_ext_loaded_lib_t describing loaded shared 124 libraries. */ 125 const apr_array_header_t *loaded_libs; 126}; 127 128 129const svn_version_extended_t * 130svn_version_extended(svn_boolean_t verbose, 131 apr_pool_t *pool) 132{ 133 svn_version_extended_t *info = apr_pcalloc(pool, sizeof(*info)); 134 135 info->build_date = NULL; 136 info->build_time = NULL; 137 info->build_host = SVN_BUILD_HOST; 138 info->copyright = apr_pstrdup 139 (pool, _("Copyright (C) 2015 The Apache Software Foundation.\n" 140 "This software consists of contributions made by many people;\n" 141 "see the NOTICE file for more information.\n" 142 "Subversion is open source software, see " 143 "http://subversion.apache.org/\n")); 144 145 if (verbose) 146 { 147 info->runtime_host = svn_sysinfo__canonical_host(pool); 148 info->runtime_osname = svn_sysinfo__release_name(pool); 149 info->linked_libs = svn_sysinfo__linked_libs(pool); 150 info->loaded_libs = svn_sysinfo__loaded_libs(pool); 151 } 152 153 return info; 154} 155 156 157const char * 158svn_version_ext_build_date(const svn_version_extended_t *ext_info) 159{ 160 return ext_info->build_date; 161} 162 163const char * 164svn_version_ext_build_time(const svn_version_extended_t *ext_info) 165{ 166 return ext_info->build_time; 167} 168 169const char * 170svn_version_ext_build_host(const svn_version_extended_t *ext_info) 171{ 172 return ext_info->build_host; 173} 174 175const char * 176svn_version_ext_copyright(const svn_version_extended_t *ext_info) 177{ 178 return ext_info->copyright; 179} 180 181const char * 182svn_version_ext_runtime_host(const svn_version_extended_t *ext_info) 183{ 184 return ext_info->runtime_host; 185} 186 187const char * 188svn_version_ext_runtime_osname(const svn_version_extended_t *ext_info) 189{ 190 return ext_info->runtime_osname; 191} 192 193const apr_array_header_t * 194svn_version_ext_linked_libs(const svn_version_extended_t *ext_info) 195{ 196 return ext_info->linked_libs; 197} 198 199const apr_array_header_t * 200svn_version_ext_loaded_libs(const svn_version_extended_t *ext_info) 201{ 202 return ext_info->loaded_libs; 203} 204 205svn_error_t * 206svn_version__parse_version_string(svn_version_t **version_p, 207 const char *version_string, 208 apr_pool_t *result_pool) 209{ 210 svn_error_t *err; 211 svn_version_t *version; 212 apr_array_header_t *pieces = 213 svn_cstring_split(version_string, ".", FALSE, result_pool); 214 215 if ((pieces->nelts < 2) || (pieces->nelts > 3)) 216 return svn_error_createf(SVN_ERR_MALFORMED_VERSION_STRING, NULL, 217 _("Failed to parse version number string '%s'"), 218 version_string); 219 220 version = apr_pcalloc(result_pool, sizeof(*version)); 221 version->tag = ""; 222 223 /* Parse the major and minor integers strictly. */ 224 err = svn_cstring_atoi(&(version->major), 225 APR_ARRAY_IDX(pieces, 0, const char *)); 226 if (err) 227 return svn_error_createf(SVN_ERR_MALFORMED_VERSION_STRING, err, 228 _("Failed to parse version number string '%s'"), 229 version_string); 230 err = svn_cstring_atoi(&(version->minor), 231 APR_ARRAY_IDX(pieces, 1, const char *)); 232 if (err) 233 return svn_error_createf(SVN_ERR_MALFORMED_VERSION_STRING, err, 234 _("Failed to parse version number string '%s'"), 235 version_string); 236 237 /* If there's a third component, we'll parse it, too. But we don't 238 require that it be present. */ 239 if (pieces->nelts == 3) 240 { 241 const char *piece = APR_ARRAY_IDX(pieces, 2, const char *); 242 char *hyphen = strchr(piece, '-'); 243 if (hyphen) 244 { 245 version->tag = apr_pstrdup(result_pool, hyphen + 1); 246 *hyphen = '\0'; 247 } 248 err = svn_cstring_atoi(&(version->patch), piece); 249 if (err) 250 return svn_error_createf(SVN_ERR_MALFORMED_VERSION_STRING, err, 251 _("Failed to parse version number string '%s'" 252 ), 253 version_string); 254 } 255 256 if (version->major < 0 || version->minor < 0 || version->patch < 0) 257 return svn_error_createf(SVN_ERR_MALFORMED_VERSION_STRING, err, 258 _("Failed to parse version number string '%s'"), 259 version_string); 260 261 *version_p = version; 262 return SVN_NO_ERROR; 263} 264 265 266svn_boolean_t 267svn_version__at_least(svn_version_t *version, 268 int major, 269 int minor, 270 int patch) 271{ 272 /* Compare major versions. */ 273 if (version->major < major) 274 return FALSE; 275 if (version->major > major) 276 return TRUE; 277 278 /* Major versions are the same. Compare minor versions. */ 279 if (version->minor < minor) 280 return FALSE; 281 if (version->minor > minor) 282 return TRUE; 283 284 /* Major and minor versions are the same. Compare patch 285 versions. */ 286 if (version->patch < patch) 287 return FALSE; 288 if (version->patch > patch) 289 return TRUE; 290 291 /* Major, minor, and patch versions are identical matches. But tags 292 in our schema are always used for versions not yet quite at the 293 given patch level. */ 294 if (version->tag && version->tag[0]) 295 return FALSE; 296 297 return TRUE; 298} 299