14Srgrimes/* 24Srgrimes * version.c: library version number and utilities 34Srgrimes * 44Srgrimes * ==================================================================== 54Srgrimes * Licensed to the Apache Software Foundation (ASF) under one 64Srgrimes * or more contributor license agreements. See the NOTICE file 74Srgrimes * distributed with this work for additional information 84Srgrimes * regarding copyright ownership. The ASF licenses this file 94Srgrimes * to you under the Apache License, Version 2.0 (the 104Srgrimes * "License"); you may not use this file except in compliance 114Srgrimes * with the License. You may obtain a copy of the License at 124Srgrimes * 134Srgrimes * http://www.apache.org/licenses/LICENSE-2.0 144Srgrimes * 154Srgrimes * Unless required by applicable law or agreed to in writing, 164Srgrimes * software distributed under the License is distributed on an 174Srgrimes * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 184Srgrimes * KIND, either express or implied. See the License for the 194Srgrimes * specific language governing permissions and limitations 204Srgrimes * under the License. 214Srgrimes * ==================================================================== 224Srgrimes */ 234Srgrimes 244Srgrimes 254Srgrimes 264Srgrimes#include "svn_error.h" 274Srgrimes#include "svn_version.h" 284Srgrimes 294Srgrimes#include "sysinfo.h" 304Srgrimes#include "svn_private_config.h" 314Srgrimes#include "private/svn_subr_private.h" 32551Srgrimes 3350477Speterconst svn_version_t * 344Srgrimessvn_subr_version(void) 354Srgrimes{ 36196994Sphk SVN_VERSION_BODY; 37196994Sphk} 38196994Sphk 39196994Sphk 40249722Stijlsvn_boolean_t svn_ver_compatible(const svn_version_t *my_version, 41249722Stijl const svn_version_t *lib_version) 424Srgrimes{ 434Srgrimes /* With normal development builds the matching rules are strict, to 444Srgrimes avoid inadvertantly using the wrong libraries. For backward 4568498Sasmodai compatibility testing use --disable-full-version-match to 4668498Sasmodai configure 1.7 and then the libraries that get built can be used 47154128Simp to replace those in 1.6 or earlier builds. */ 48223440Sjhb 49154128Simp#ifndef SVN_DISABLE_FULL_VERSION_MATCH 50154128Simp if (lib_version->tag[0] != '\0') 5144364Simp /* Development library; require exact match. */ 52551Srgrimes return svn_ver_equal(my_version, lib_version); 5344364Simp else if (my_version->tag[0] != '\0') 5444364Simp /* Development client; must be newer than the library 5538673Skato and have the same major and minor version. */ 5644364Simp return (my_version->major == lib_version->major 5736977Sbde && my_version->minor == lib_version->minor 5836977Sbde && my_version->patch > lib_version->patch); 59177661Sjb#endif 60224207Sattilio 61183525Sjhb /* General compatibility rules for released versions. */ 62224207Sattilio return (my_version->major == lib_version->major 6328354Sfsmp && my_version->minor <= lib_version->minor); 6466296Sps} 65177661Sjb 664Srgrimes 67250338Sattiliosvn_boolean_t svn_ver_equal(const svn_version_t *my_version, 68250338Sattilio const svn_version_t *lib_version) 69250338Sattilio{ 70250338Sattilio return (my_version->major == lib_version->major 7168498Sasmodai && my_version->minor == lib_version->minor 7268498Sasmodai && my_version->patch == lib_version->patch 73195376Ssam && 0 == strcmp(my_version->tag, lib_version->tag)); 74195376Ssam} 75195376Ssam 76195376Ssam 77195376Ssamsvn_error_t * 78195376Ssamsvn_ver__check_list2(const svn_version_t *my_version, 79195376Ssam const svn_version_checklist_t *checklist, 804Srgrimes svn_boolean_t (*comparator)(const svn_version_t *, 81191278Srwatson const svn_version_t *)) 82191278Srwatson{ 83191278Srwatson svn_error_t *err = SVN_NO_ERROR; 84191278Srwatson int i; 85192331Sjhb 86191276Srwatson for (i = 0; checklist[i].label != NULL; ++i) 87191276Srwatson { 8815543Sphk const svn_version_t *lib_version = checklist[i].version_query(); 8915565Sphk if (!comparator(my_version, lib_version)) 901045Sdg err = svn_error_createf(SVN_ERR_VERSION_MISMATCH, err, 9115543Sphk _("Version mismatch in '%s'%s:" 9215565Sphk " found %d.%d.%d%s," 93282065Skib " expected %d.%d.%d%s"), 94112841Sjake checklist[i].label, 95112841Sjake comparator == svn_ver_equal 96183343Skmacy ? _(" (expecting equality)") 97112841Sjake : comparator == svn_ver_compatible 98111363Sjake ? _(" (expecting compatibility)") 99111363Sjake : "", 100183343Skmacy lib_version->major, lib_version->minor, 101112841Sjake lib_version->patch, lib_version->tag, 102111363Sjake my_version->major, my_version->minor, 103111363Sjake my_version->patch, my_version->tag); 104111363Sjake } 10515543Sphk 10615565Sphk return err; 10727950Sdyson} 1084Srgrimes 109197316Salc 110197316Salcstruct svn_version_extended_t 11127993Sdyson{ 11282309Speter const char *build_date; /* Compilation date */ 11383366Sjulian const char *build_time; /* Compilation time */ 11483366Sjulian const char *build_host; /* Build canonical host name */ 11582309Speter const char *copyright; /* Copyright notice (localized) */ 116116355Salc const char *runtime_host; /* Runtime canonical host name */ 117286878Skib const char *runtime_osname; /* Running OS release name */ 118286878Skib 119286878Skib /* Array of svn_version_ext_linked_lib_t describing dependent 120286878Skib libraries. */ 121286878Skib const apr_array_header_t *linked_libs; 1224Srgrimes 1234Srgrimes /* Array of svn_version_ext_loaded_lib_t describing loaded shared 124239730Sdes libraries. */ 125239730Sdes const apr_array_header_t *loaded_libs; 126239730Sdes}; 127239730Sdes 128239730Sdes 129239730Sdesconst svn_version_extended_t * 130239730Sdessvn_version_extended(svn_boolean_t verbose, 131239730Sdes apr_pool_t *pool) 132239730Sdes{ 133239730Sdes svn_version_extended_t *info = apr_pcalloc(pool, sizeof(*info)); 134239730Sdes 135239730Sdes info->build_date = NULL; 136239730Sdes info->build_time = NULL; 137239730Sdes info->build_host = SVN_BUILD_HOST; 13881933Sdillon info->copyright = apr_pstrdup 139102738Sdillon (pool, _("Copyright (C) 2015 The Apache Software Foundation.\n" 140102738Sdillon "This software consists of contributions made by many people;\n" 141248789Skib "see the NOTICE file for more information.\n" 142248789Skib "Subversion is open source software, see " 143248789Skib "http://subversion.apache.org/\n")); 14481933Sdillon 14581933Sdillon if (verbose) 146248789Skib { 14781933Sdillon info->runtime_host = svn_sysinfo__canonical_host(pool); 14881933Sdillon info->runtime_osname = svn_sysinfo__release_name(pool); 14981933Sdillon info->linked_libs = svn_sysinfo__linked_libs(pool); 1504Srgrimes info->loaded_libs = svn_sysinfo__loaded_libs(pool); 1514Srgrimes } 15240286Sdg 15340286Sdg return info; 154112569Sjake} 155112569Sjake 1561549Srgrimes 157112569Sjakeconst char * 158112569Sjakesvn_version_ext_build_date(const svn_version_extended_t *ext_info) 1591045Sdg{ 160112569Sjake return ext_info->build_date; 161112569Sjake} 162584Srgrimes 16344157Sluoqiconst char * 16444157Sluoqisvn_version_ext_build_time(const svn_version_extended_t *ext_info) 165286305Skib{ 166286305Skib return ext_info->build_time; 167286305Skib} 168196994Sphk 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