1251881Speter/* 2251881Speter * version.c: library version number and utilities 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#include "svn_error.h" 27251881Speter#include "svn_version.h" 28251881Speter 29251881Speter#include "sysinfo.h" 30251881Speter#include "svn_private_config.h" 31251881Speter#include "private/svn_subr_private.h" 32251881Speter 33251881Speterconst svn_version_t * 34251881Spetersvn_subr_version(void) 35251881Speter{ 36251881Speter SVN_VERSION_BODY; 37251881Speter} 38251881Speter 39251881Speter 40251881Spetersvn_boolean_t svn_ver_compatible(const svn_version_t *my_version, 41251881Speter const svn_version_t *lib_version) 42251881Speter{ 43251881Speter /* With normal development builds the matching rules are strict, to 44251881Speter avoid inadvertantly using the wrong libraries. For backward 45251881Speter compatibility testing use --disable-full-version-match to 46251881Speter configure 1.7 and then the libraries that get built can be used 47251881Speter to replace those in 1.6 or earlier builds. */ 48251881Speter 49251881Speter#ifndef SVN_DISABLE_FULL_VERSION_MATCH 50251881Speter if (lib_version->tag[0] != '\0') 51251881Speter /* Development library; require exact match. */ 52251881Speter return svn_ver_equal(my_version, lib_version); 53251881Speter else if (my_version->tag[0] != '\0') 54251881Speter /* Development client; must be newer than the library 55251881Speter and have the same major and minor version. */ 56251881Speter return (my_version->major == lib_version->major 57251881Speter && my_version->minor == lib_version->minor 58251881Speter && my_version->patch > lib_version->patch); 59251881Speter#endif 60251881Speter 61251881Speter /* General compatibility rules for released versions. */ 62251881Speter return (my_version->major == lib_version->major 63251881Speter && my_version->minor <= lib_version->minor); 64251881Speter} 65251881Speter 66251881Speter 67251881Spetersvn_boolean_t svn_ver_equal(const svn_version_t *my_version, 68251881Speter const svn_version_t *lib_version) 69251881Speter{ 70251881Speter return (my_version->major == lib_version->major 71251881Speter && my_version->minor == lib_version->minor 72251881Speter && my_version->patch == lib_version->patch 73251881Speter && 0 == strcmp(my_version->tag, lib_version->tag)); 74251881Speter} 75251881Speter 76251881Speter 77251881Spetersvn_error_t * 78262253Spetersvn_ver__check_list2(const svn_version_t *my_version, 79262253Speter const svn_version_checklist_t *checklist, 80262253Speter svn_boolean_t (*comparator)(const svn_version_t *, 81262253Speter const svn_version_t *)) 82251881Speter{ 83251881Speter svn_error_t *err = SVN_NO_ERROR; 84251881Speter int i; 85251881Speter 86251881Speter for (i = 0; checklist[i].label != NULL; ++i) 87251881Speter { 88251881Speter const svn_version_t *lib_version = checklist[i].version_query(); 89262253Speter if (!comparator(my_version, lib_version)) 90251881Speter err = svn_error_createf(SVN_ERR_VERSION_MISMATCH, err, 91262253Speter _("Version mismatch in '%s'%s:" 92251881Speter " found %d.%d.%d%s," 93251881Speter " expected %d.%d.%d%s"), 94251881Speter checklist[i].label, 95262253Speter comparator == svn_ver_equal 96262253Speter ? _(" (expecting equality)") 97262253Speter : comparator == svn_ver_compatible 98262253Speter ? _(" (expecting compatibility)") 99262253Speter : "", 100251881Speter lib_version->major, lib_version->minor, 101251881Speter lib_version->patch, lib_version->tag, 102251881Speter my_version->major, my_version->minor, 103251881Speter my_version->patch, my_version->tag); 104251881Speter } 105251881Speter 106251881Speter return err; 107251881Speter} 108251881Speter 109251881Speter 110251881Speterstruct svn_version_extended_t 111251881Speter{ 112251881Speter const char *build_date; /* Compilation date */ 113251881Speter const char *build_time; /* Compilation time */ 114251881Speter const char *build_host; /* Build canonical host name */ 115251881Speter const char *copyright; /* Copyright notice (localized) */ 116251881Speter const char *runtime_host; /* Runtime canonical host name */ 117251881Speter const char *runtime_osname; /* Running OS release name */ 118251881Speter 119251881Speter /* Array of svn_version_ext_linked_lib_t describing dependent 120251881Speter libraries. */ 121251881Speter const apr_array_header_t *linked_libs; 122251881Speter 123251881Speter /* Array of svn_version_ext_loaded_lib_t describing loaded shared 124251881Speter libraries. */ 125251881Speter const apr_array_header_t *loaded_libs; 126251881Speter}; 127251881Speter 128251881Speter 129251881Speterconst svn_version_extended_t * 130251881Spetersvn_version_extended(svn_boolean_t verbose, 131251881Speter apr_pool_t *pool) 132251881Speter{ 133251881Speter svn_version_extended_t *info = apr_pcalloc(pool, sizeof(*info)); 134251881Speter 135257286Scperciva info->build_date = NULL; 136257286Scperciva info->build_time = NULL; 137251881Speter info->build_host = SVN_BUILD_HOST; 138251881Speter info->copyright = apr_pstrdup 139269847Speter (pool, _("Copyright (C) 2014 The Apache Software Foundation.\n" 140251881Speter "This software consists of contributions made by many people;\n" 141251881Speter "see the NOTICE file for more information.\n" 142251881Speter "Subversion is open source software, see " 143251881Speter "http://subversion.apache.org/\n")); 144251881Speter 145251881Speter if (verbose) 146251881Speter { 147251881Speter info->runtime_host = svn_sysinfo__canonical_host(pool); 148251881Speter info->runtime_osname = svn_sysinfo__release_name(pool); 149251881Speter info->linked_libs = svn_sysinfo__linked_libs(pool); 150251881Speter info->loaded_libs = svn_sysinfo__loaded_libs(pool); 151251881Speter } 152251881Speter 153251881Speter return info; 154251881Speter} 155251881Speter 156251881Speter 157251881Speterconst char * 158251881Spetersvn_version_ext_build_date(const svn_version_extended_t *ext_info) 159251881Speter{ 160251881Speter return ext_info->build_date; 161251881Speter} 162251881Speter 163251881Speterconst char * 164251881Spetersvn_version_ext_build_time(const svn_version_extended_t *ext_info) 165251881Speter{ 166251881Speter return ext_info->build_time; 167251881Speter} 168251881Speter 169251881Speterconst char * 170251881Spetersvn_version_ext_build_host(const svn_version_extended_t *ext_info) 171251881Speter{ 172251881Speter return ext_info->build_host; 173251881Speter} 174251881Speter 175251881Speterconst char * 176251881Spetersvn_version_ext_copyright(const svn_version_extended_t *ext_info) 177251881Speter{ 178251881Speter return ext_info->copyright; 179251881Speter} 180251881Speter 181251881Speterconst char * 182251881Spetersvn_version_ext_runtime_host(const svn_version_extended_t *ext_info) 183251881Speter{ 184251881Speter return ext_info->runtime_host; 185251881Speter} 186251881Speter 187251881Speterconst char * 188251881Spetersvn_version_ext_runtime_osname(const svn_version_extended_t *ext_info) 189251881Speter{ 190251881Speter return ext_info->runtime_osname; 191251881Speter} 192251881Speter 193251881Speterconst apr_array_header_t * 194251881Spetersvn_version_ext_linked_libs(const svn_version_extended_t *ext_info) 195251881Speter{ 196251881Speter return ext_info->linked_libs; 197251881Speter} 198251881Speter 199251881Speterconst apr_array_header_t * 200251881Spetersvn_version_ext_loaded_libs(const svn_version_extended_t *ext_info) 201251881Speter{ 202251881Speter return ext_info->loaded_libs; 203251881Speter} 204251881Speter 205251881Spetersvn_error_t * 206251881Spetersvn_version__parse_version_string(svn_version_t **version_p, 207251881Speter const char *version_string, 208251881Speter apr_pool_t *result_pool) 209251881Speter{ 210251881Speter svn_error_t *err; 211251881Speter svn_version_t *version; 212251881Speter apr_array_header_t *pieces = 213251881Speter svn_cstring_split(version_string, ".", FALSE, result_pool); 214251881Speter 215251881Speter if ((pieces->nelts < 2) || (pieces->nelts > 3)) 216251881Speter return svn_error_createf(SVN_ERR_MALFORMED_VERSION_STRING, NULL, 217251881Speter _("Failed to parse version number string '%s'"), 218251881Speter version_string); 219251881Speter 220251881Speter version = apr_pcalloc(result_pool, sizeof(*version)); 221251881Speter version->tag = ""; 222251881Speter 223251881Speter /* Parse the major and minor integers strictly. */ 224251881Speter err = svn_cstring_atoi(&(version->major), 225251881Speter APR_ARRAY_IDX(pieces, 0, const char *)); 226251881Speter if (err) 227251881Speter return svn_error_createf(SVN_ERR_MALFORMED_VERSION_STRING, err, 228251881Speter _("Failed to parse version number string '%s'"), 229251881Speter version_string); 230251881Speter err = svn_cstring_atoi(&(version->minor), 231251881Speter APR_ARRAY_IDX(pieces, 1, const char *)); 232251881Speter if (err) 233251881Speter return svn_error_createf(SVN_ERR_MALFORMED_VERSION_STRING, err, 234251881Speter _("Failed to parse version number string '%s'"), 235251881Speter version_string); 236251881Speter 237251881Speter /* If there's a third component, we'll parse it, too. But we don't 238251881Speter require that it be present. */ 239251881Speter if (pieces->nelts == 3) 240251881Speter { 241251881Speter const char *piece = APR_ARRAY_IDX(pieces, 2, const char *); 242251881Speter char *hyphen = strchr(piece, '-'); 243251881Speter if (hyphen) 244251881Speter { 245251881Speter version->tag = apr_pstrdup(result_pool, hyphen + 1); 246251881Speter *hyphen = '\0'; 247251881Speter } 248251881Speter err = svn_cstring_atoi(&(version->patch), piece); 249251881Speter if (err) 250251881Speter return svn_error_createf(SVN_ERR_MALFORMED_VERSION_STRING, err, 251251881Speter _("Failed to parse version number string '%s'" 252251881Speter ), 253251881Speter version_string); 254251881Speter } 255251881Speter 256251881Speter if (version->major < 0 || version->minor < 0 || version->patch < 0) 257251881Speter return svn_error_createf(SVN_ERR_MALFORMED_VERSION_STRING, err, 258251881Speter _("Failed to parse version number string '%s'"), 259251881Speter version_string); 260251881Speter 261251881Speter *version_p = version; 262251881Speter return SVN_NO_ERROR; 263251881Speter} 264251881Speter 265251881Speter 266251881Spetersvn_boolean_t 267251881Spetersvn_version__at_least(svn_version_t *version, 268251881Speter int major, 269251881Speter int minor, 270251881Speter int patch) 271251881Speter{ 272251881Speter /* Compare major versions. */ 273251881Speter if (version->major < major) 274251881Speter return FALSE; 275251881Speter if (version->major > major) 276251881Speter return TRUE; 277251881Speter 278251881Speter /* Major versions are the same. Compare minor versions. */ 279251881Speter if (version->minor < minor) 280251881Speter return FALSE; 281251881Speter if (version->minor > minor) 282251881Speter return TRUE; 283251881Speter 284251881Speter /* Major and minor versions are the same. Compare patch 285251881Speter versions. */ 286251881Speter if (version->patch < patch) 287251881Speter return FALSE; 288251881Speter if (version->patch > patch) 289251881Speter return TRUE; 290251881Speter 291251881Speter /* Major, minor, and patch versions are identical matches. But tags 292251881Speter in our schema are always used for versions not yet quite at the 293251881Speter given patch level. */ 294251881Speter if (version->tag && version->tag[0]) 295251881Speter return FALSE; 296251881Speter 297251881Speter return TRUE; 298251881Speter} 299