diff options
Diffstat (limited to 'lib/libalpm')
| -rw-r--r-- | lib/libalpm/Makefile.am | 3 | ||||
| -rw-r--r-- | lib/libalpm/package.c | 171 | ||||
| -rw-r--r-- | lib/libalpm/version.c | 198 | 
3 files changed, 200 insertions, 172 deletions
| diff --git a/lib/libalpm/Makefile.am b/lib/libalpm/Makefile.am index 871855ef..3473a73a 100644 --- a/lib/libalpm/Makefile.am +++ b/lib/libalpm/Makefile.am @@ -43,7 +43,8 @@ libalpm_la_SOURCES = \  	remove.h remove.c \  	sync.h sync.c \  	trans.h trans.c \ -	util.h util.c +	util.h util.c \ +	version.c  libalpm_la_LDFLAGS = -no-undefined -version-info $(LIB_VERSION_INFO)  libalpm_la_LIBADD = $(LTLIBINTL) diff --git a/lib/libalpm/package.c b/lib/libalpm/package.c index ed6d71d0..becbc60f 100644 --- a/lib/libalpm/package.c +++ b/lib/libalpm/package.c @@ -604,177 +604,6 @@ alpm_list_t SYMEXPORT *alpm_pkg_compute_requiredby(pmpkg_t *pkg)  	return(reqs);  } -/** Compare two version strings and determine which one is 'newer'. - * Returns a value comparable to the way strcmp works. Returns 1 - * if a is newer than b, 0 if a and b are the same version, or -1 - * if b is newer than a. - * - * This function has been adopted from the rpmvercmp function located - * at lib/rpmvercmp.c, and was most recently updated against rpm - * version 4.4.2.3. Small modifications have been made to make it more - * consistent with the libalpm coding style. - * - * Keep in mind that the pkgrel is only compared if it is available - * on both versions handed to this function. For example, comparing - * 1.5-1 and 1.5 will yield 0; comparing 1.5-1 and 1.5-2 will yield - * -1 as expected. This is mainly for supporting versioned dependencies - * that do not include the pkgrel. - */ -int SYMEXPORT alpm_pkg_vercmp(const char *a, const char *b) -{ -	char oldch1, oldch2; -	char *str1, *str2; -	char *ptr1, *ptr2; -	char *one, *two; -	int rc; -	int isnum; -	int ret = 0; - -	ALPM_LOG_FUNC; - -	/* libalpm added code. ensure our strings are not null */ -	if(!a) { -		if(!b) return(0); -		return(-1); -	} -	if(!b) return(1); - -	/* easy comparison to see if versions are identical */ -	if(strcmp(a, b) == 0) return(0); - -	str1 = strdup(a); -	str2 = strdup(b); - -	one = str1; -	two = str2; - -	/* loop through each version segment of str1 and str2 and compare them */ -	while(*one && *two) { -		while(*one && !isalnum((int)*one)) one++; -		while(*two && !isalnum((int)*two)) two++; - -		/* If we ran to the end of either, we are finished with the loop */ -		if(!(*one && *two)) break; - -		ptr1 = one; -		ptr2 = two; - -		/* grab first completely alpha or completely numeric segment */ -		/* leave one and two pointing to the start of the alpha or numeric */ -		/* segment and walk ptr1 and ptr2 to end of segment */ -		if(isdigit((int)*ptr1)) { -			while(*ptr1 && isdigit((int)*ptr1)) ptr1++; -			while(*ptr2 && isdigit((int)*ptr2)) ptr2++; -			isnum = 1; -		} else { -			while(*ptr1 && isalpha((int)*ptr1)) ptr1++; -			while(*ptr2 && isalpha((int)*ptr2)) ptr2++; -			isnum = 0; -		} - -		/* save character at the end of the alpha or numeric segment */ -		/* so that they can be restored after the comparison */ -		oldch1 = *ptr1; -		*ptr1 = '\0'; -		oldch2 = *ptr2; -		*ptr2 = '\0'; - -		/* this cannot happen, as we previously tested to make sure that */ -		/* the first string has a non-null segment */ -		if (one == ptr1) { -			ret = -1;	/* arbitrary */ -			goto cleanup; -		} - -		/* take care of the case where the two version segments are */ -		/* different types: one numeric, the other alpha (i.e. empty) */ -		/* numeric segments are always newer than alpha segments */ -		/* XXX See patch #60884 (and details) from bugzilla #50977. */ -		if (two == ptr2) { -			ret = isnum ? 1 : -1; -			goto cleanup; -		} - -		if (isnum) { -			/* this used to be done by converting the digit segments */ -			/* to ints using atoi() - it's changed because long  */ -			/* digit segments can overflow an int - this should fix that. */ - -			/* throw away any leading zeros - it's a number, right? */ -			while (*one == '0') one++; -			while (*two == '0') two++; - -			/* whichever number has more digits wins */ -			if (strlen(one) > strlen(two)) { -				ret = 1; -				goto cleanup; -			} -			if (strlen(two) > strlen(one)) { -				ret = -1; -				goto cleanup; -			} -		} - -		/* strcmp will return which one is greater - even if the two */ -		/* segments are alpha or if they are numeric.  don't return  */ -		/* if they are equal because there might be more segments to */ -		/* compare */ -		rc = strcmp(one, two); -		if (rc) { -			ret = rc < 1 ? -1 : 1; -			goto cleanup; -		} - -		/* restore character that was replaced by null above */ -		*ptr1 = oldch1; -		one = ptr1; -		*ptr2 = oldch2; -		two = ptr2; - -		/* libalpm added code. check if version strings have hit the pkgrel -		 * portion. depending on which strings have hit, take correct action. -		 * this is all based on the premise that we only have one dash in -		 * the version string, and it separates pkgver from pkgrel. */ -		if(*ptr1 == '-' && *ptr2 == '-') { -			/* no-op, continue comparing since we are equivalent throughout */ -		} else if(*ptr1 == '-') { -			/* ptr1 has hit the pkgrel and ptr2 has not. continue version -			 * comparison after stripping the pkgrel from ptr1. */ -			*ptr1 = '\0'; -		} else if(*ptr2 == '-') { -			/* ptr2 has hit the pkgrel and ptr1 has not. continue version -			 * comparison after stripping the pkgrel from ptr2. */ -			*ptr2 = '\0'; -		} -	} - -	/* this catches the case where all numeric and alpha segments have */ -	/* compared identically but the segment separating characters were */ -	/* different */ -	if ((!*one) && (!*two)) { -		ret = 0; -		goto cleanup; -	} - -	/* the final showdown. we never want a remaining alpha string to -	 * beat an empty string. the logic is a bit weird, but: -	 * - if one is empty and two is not an alpha, two is newer. -	 * - if one is an alpha, two is newer. -	 * - otherwise one is newer. -	 * */ -	if ( ( !*one && !isalpha((int)*two) ) -			|| isalpha((int)*one) ) { -		ret = -1; -	} else { -		ret = 1; -	} - -cleanup: -	free(str1); -	free(str2); -	return(ret); -} -  /** @} */  pmpkg_t *_alpm_pkg_new(void) diff --git a/lib/libalpm/version.c b/lib/libalpm/version.c new file mode 100644 index 00000000..1c838f41 --- /dev/null +++ b/lib/libalpm/version.c @@ -0,0 +1,198 @@ +/* + *  Copyright (c) 2006-2010 Pacman Development Team <pacman-dev@archlinux.org> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 2 of the License, or + *  (at your option) any later version. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ + +#include "config.h" + +#include <string.h> +#include <ctype.h> + +/* libalpm */ +#include "log.h" +#include "util.h" + +/** Compare two version strings and determine which one is 'newer'. + * Returns a value comparable to the way strcmp works. Returns 1 + * if a is newer than b, 0 if a and b are the same version, or -1 + * if b is newer than a. + * + * This function has been adopted from the rpmvercmp function located + * at lib/rpmvercmp.c, and was most recently updated against rpm + * version 4.4.2.3. Small modifications have been made to make it more + * consistent with the libalpm coding style. + * + * Keep in mind that the pkgrel is only compared if it is available + * on both versions handed to this function. For example, comparing + * 1.5-1 and 1.5 will yield 0; comparing 1.5-1 and 1.5-2 will yield + * -1 as expected. This is mainly for supporting versioned dependencies + * that do not include the pkgrel. + */ +int SYMEXPORT alpm_pkg_vercmp(const char *a, const char *b) +{ +	char oldch1, oldch2; +	char *str1, *str2; +	char *ptr1, *ptr2; +	char *one, *two; +	int rc; +	int isnum; +	int ret = 0; + +	ALPM_LOG_FUNC; + +	/* libalpm added code. ensure our strings are not null */ +	if(!a) { +		if(!b) return(0); +		return(-1); +	} +	if(!b) return(1); + +	/* easy comparison to see if versions are identical */ +	if(strcmp(a, b) == 0) return(0); + +	str1 = strdup(a); +	str2 = strdup(b); + +	one = str1; +	two = str2; + +	/* loop through each version segment of str1 and str2 and compare them */ +	while(*one && *two) { +		while(*one && !isalnum((int)*one)) one++; +		while(*two && !isalnum((int)*two)) two++; + +		/* If we ran to the end of either, we are finished with the loop */ +		if(!(*one && *two)) break; + +		ptr1 = one; +		ptr2 = two; + +		/* grab first completely alpha or completely numeric segment */ +		/* leave one and two pointing to the start of the alpha or numeric */ +		/* segment and walk ptr1 and ptr2 to end of segment */ +		if(isdigit((int)*ptr1)) { +			while(*ptr1 && isdigit((int)*ptr1)) ptr1++; +			while(*ptr2 && isdigit((int)*ptr2)) ptr2++; +			isnum = 1; +		} else { +			while(*ptr1 && isalpha((int)*ptr1)) ptr1++; +			while(*ptr2 && isalpha((int)*ptr2)) ptr2++; +			isnum = 0; +		} + +		/* save character at the end of the alpha or numeric segment */ +		/* so that they can be restored after the comparison */ +		oldch1 = *ptr1; +		*ptr1 = '\0'; +		oldch2 = *ptr2; +		*ptr2 = '\0'; + +		/* this cannot happen, as we previously tested to make sure that */ +		/* the first string has a non-null segment */ +		if (one == ptr1) { +			ret = -1;	/* arbitrary */ +			goto cleanup; +		} + +		/* take care of the case where the two version segments are */ +		/* different types: one numeric, the other alpha (i.e. empty) */ +		/* numeric segments are always newer than alpha segments */ +		/* XXX See patch #60884 (and details) from bugzilla #50977. */ +		if (two == ptr2) { +			ret = isnum ? 1 : -1; +			goto cleanup; +		} + +		if (isnum) { +			/* this used to be done by converting the digit segments */ +			/* to ints using atoi() - it's changed because long  */ +			/* digit segments can overflow an int - this should fix that. */ + +			/* throw away any leading zeros - it's a number, right? */ +			while (*one == '0') one++; +			while (*two == '0') two++; + +			/* whichever number has more digits wins */ +			if (strlen(one) > strlen(two)) { +				ret = 1; +				goto cleanup; +			} +			if (strlen(two) > strlen(one)) { +				ret = -1; +				goto cleanup; +			} +		} + +		/* strcmp will return which one is greater - even if the two */ +		/* segments are alpha or if they are numeric.  don't return  */ +		/* if they are equal because there might be more segments to */ +		/* compare */ +		rc = strcmp(one, two); +		if (rc) { +			ret = rc < 1 ? -1 : 1; +			goto cleanup; +		} + +		/* restore character that was replaced by null above */ +		*ptr1 = oldch1; +		one = ptr1; +		*ptr2 = oldch2; +		two = ptr2; + +		/* libalpm added code. check if version strings have hit the pkgrel +		 * portion. depending on which strings have hit, take correct action. +		 * this is all based on the premise that we only have one dash in +		 * the version string, and it separates pkgver from pkgrel. */ +		if(*ptr1 == '-' && *ptr2 == '-') { +			/* no-op, continue comparing since we are equivalent throughout */ +		} else if(*ptr1 == '-') { +			/* ptr1 has hit the pkgrel and ptr2 has not. continue version +			 * comparison after stripping the pkgrel from ptr1. */ +			*ptr1 = '\0'; +		} else if(*ptr2 == '-') { +			/* ptr2 has hit the pkgrel and ptr1 has not. continue version +			 * comparison after stripping the pkgrel from ptr2. */ +			*ptr2 = '\0'; +		} +	} + +	/* this catches the case where all numeric and alpha segments have */ +	/* compared identically but the segment separating characters were */ +	/* different */ +	if ((!*one) && (!*two)) { +		ret = 0; +		goto cleanup; +	} + +	/* the final showdown. we never want a remaining alpha string to +	 * beat an empty string. the logic is a bit weird, but: +	 * - if one is empty and two is not an alpha, two is newer. +	 * - if one is an alpha, two is newer. +	 * - otherwise one is newer. +	 * */ +	if ( ( !*one && !isalpha((int)*two) ) +			|| isalpha((int)*one) ) { +		ret = -1; +	} else { +		ret = 1; +	} + +cleanup: +	free(str1); +	free(str2); +	return(ret); +} + +/* vim: set ts=2 sw=2 noet: */ | 
