diff options
| author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-11-20 23:41:56 +0000 |
|---|---|---|
| committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-11-20 23:41:56 +0000 |
| commit | b8baf407aacc09167c4e9fa0db55fe323b15854e (patch) | |
| tree | e16b83936ea6dcf30e8b9968c5068d03d6bacf55 | |
| parent | 9a4c0d59a79efeba4e1c5feed7d07b7c6b6b04ce (diff) | |
| download | busybox-w32-b8baf407aacc09167c4e9fa0db55fe323b15854e.tar.gz busybox-w32-b8baf407aacc09167c4e9fa0db55fe323b15854e.tar.bz2 busybox-w32-b8baf407aacc09167c4e9fa0db55fe323b15854e.zip | |
dpkg: better and shorter code to compare versions
(taken from "official" dpkg).
By Eugene T. Bordenkircher (eugebo AT gmail.com)
function old new delta
order - 48 +48
test_version 273 276 +3
version_compare_part 396 187 -209
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 1/1 up/down: 51/-209) Total: -158 bytes
| -rw-r--r-- | archival/dpkg.c | 127 |
1 files changed, 59 insertions, 68 deletions
diff --git a/archival/dpkg.c b/archival/dpkg.c index 1bc8d27ce..577b77fec 100644 --- a/archival/dpkg.c +++ b/archival/dpkg.c | |||
| @@ -6,6 +6,10 @@ | |||
| 6 | * written by glenn mcgrath with the help of others | 6 | * written by glenn mcgrath with the help of others |
| 7 | * copyright (c) 2001 by glenn mcgrath | 7 | * copyright (c) 2001 by glenn mcgrath |
| 8 | * | 8 | * |
| 9 | * parts of the version comparison code is plucked from the real dpkg | ||
| 10 | * application which is licensed GPLv2 and | ||
| 11 | * copyright (c) 1995 Ian Jackson <ian@chiark.greenend.org.uk> | ||
| 12 | * | ||
| 9 | * started life as a busybox implementation of udpkg | 13 | * started life as a busybox implementation of udpkg |
| 10 | * | 14 | * |
| 11 | * licensed under gplv2 or later, see file license in this tarball for details. | 15 | * licensed under gplv2 or later, see file license in this tarball for details. |
| @@ -135,7 +139,7 @@ static void make_hash(const char *key, unsigned *start, unsigned *decrement, con | |||
| 135 | /* shifts the ascii based value and adds it to previous value | 139 | /* shifts the ascii based value and adds it to previous value |
| 136 | * shift amount is mod 24 because long int is 32 bit and data | 140 | * shift amount is mod 24 because long int is 32 bit and data |
| 137 | * to be shifted is 8, don't want to shift data to where it has | 141 | * to be shifted is 8, don't want to shift data to where it has |
| 138 | * no effect*/ | 142 | * no effect */ |
| 139 | hash_num += (key[i] + key[i-1]) << ((key[i] * i) % 24); | 143 | hash_num += (key[i] + key[i-1]) << ((key[i] * i) % 24); |
| 140 | } | 144 | } |
| 141 | *start = (unsigned) hash_num % hash_prime; | 145 | *start = (unsigned) hash_num % hash_prime; |
| @@ -183,60 +187,52 @@ static unsigned search_status_hashtable(const char *key) | |||
| 183 | return probe_address; | 187 | return probe_address; |
| 184 | } | 188 | } |
| 185 | 189 | ||
| 186 | /* Need to rethink version comparison, maybe the official dpkg has something i can use ? */ | 190 | static int order(char x) |
| 187 | static int version_compare_part(const char *version1, const char *version2) | ||
| 188 | { | 191 | { |
| 189 | int upstream_len1 = 0; | 192 | return (x == '~' ? -1 |
| 190 | int upstream_len2 = 0; | 193 | : x == '\0' ? 0 |
| 191 | char *name1_char; | 194 | : isdigit(x) ? 0 |
| 192 | char *name2_char; | 195 | : isalpha(x) ? x |
| 193 | int len1 = 0; | 196 | : (unsigned char)x + 256 |
| 194 | int len2 = 0; | 197 | ); |
| 195 | int tmp_int; | 198 | } |
| 196 | int ver_num1; | 199 | |
| 197 | int ver_num2; | 200 | /* This code is taken from dpkg and modified slightly to work with busybox */ |
| 198 | 201 | static int version_compare_part(const char *val, const char *ref) | |
| 199 | if (version1 == NULL) { | 202 | { |
| 200 | version1 = xstrdup(""); | 203 | if (!val) val = ""; |
| 201 | } | 204 | if (!ref) ref = ""; |
| 202 | if (version2 == NULL) { | 205 | |
| 203 | version2 = xstrdup(""); | 206 | while (*val || *ref) { |
| 204 | } | 207 | int first_diff; |
| 205 | upstream_len1 = strlen(version1); | 208 | |
| 206 | upstream_len2 = strlen(version2); | 209 | while ((*val && !isdigit(*val)) || (*ref && !isdigit(*ref))) { |
| 207 | 210 | int vc = order(*val); | |
| 208 | while ((len1 < upstream_len1) || (len2 < upstream_len2)) { | 211 | int rc = order(*ref); |
| 209 | /* Compare non-digit section */ | 212 | if (vc != rc) |
| 210 | tmp_int = strcspn(&version1[len1], "0123456789"); | 213 | return vc - rc; |
| 211 | name1_char = xstrndup(&version1[len1], tmp_int); | 214 | val++; |
| 212 | len1 += tmp_int; | 215 | ref++; |
| 213 | tmp_int = strcspn(&version2[len2], "0123456789"); | ||
| 214 | name2_char = xstrndup(&version2[len2], tmp_int); | ||
| 215 | len2 += tmp_int; | ||
| 216 | tmp_int = strcmp(name1_char, name2_char); | ||
| 217 | free(name1_char); | ||
| 218 | free(name2_char); | ||
| 219 | if (tmp_int != 0) { | ||
| 220 | return tmp_int; | ||
| 221 | } | 216 | } |
| 222 | 217 | ||
| 223 | /* Compare digits */ | 218 | while (*val == '0') |
| 224 | tmp_int = strspn(&version1[len1], "0123456789"); | 219 | val++; |
| 225 | name1_char = xstrndup(&version1[len1], tmp_int); | 220 | while (*ref == '0') |
| 226 | len1 += tmp_int; | 221 | ref++; |
| 227 | tmp_int = strspn(&version2[len2], "0123456789"); | 222 | |
| 228 | name2_char = xstrndup(&version2[len2], tmp_int); | 223 | first_diff = 0; |
| 229 | len2 += tmp_int; | 224 | while (isdigit(*val) && isdigit(*ref)) { |
| 230 | ver_num1 = atoi(name1_char); | 225 | if (first_diff == 0) |
| 231 | ver_num2 = atoi(name2_char); | 226 | first_diff = *val - *ref; |
| 232 | free(name1_char); | 227 | val++; |
| 233 | free(name2_char); | 228 | ref++; |
| 234 | if (ver_num1 < ver_num2) { | ||
| 235 | return -1; | ||
| 236 | } | 229 | } |
| 237 | if (ver_num1 > ver_num2) { | 230 | if (isdigit(*val)) |
| 238 | return 1; | 231 | return 1; |
| 239 | } | 232 | if (isdigit(*ref)) |
| 233 | return -1; | ||
| 234 | if (first_diff) | ||
| 235 | return first_diff; | ||
| 240 | } | 236 | } |
| 241 | return 0; | 237 | return 0; |
| 242 | } | 238 | } |
| @@ -249,39 +245,34 @@ static int version_compare(const unsigned ver1, const unsigned ver2) | |||
| 249 | { | 245 | { |
| 250 | char *ch_ver1 = name_hashtable[ver1]; | 246 | char *ch_ver1 = name_hashtable[ver1]; |
| 251 | char *ch_ver2 = name_hashtable[ver2]; | 247 | char *ch_ver2 = name_hashtable[ver2]; |
| 252 | 248 | unsigned long epoch1 = 0, epoch2 = 0; | |
| 253 | char epoch1, epoch2; | 249 | char *colon; |
| 254 | char *deb_ver1, *deb_ver2; | 250 | char *deb_ver1, *deb_ver2; |
| 255 | char *ver1_ptr, *ver2_ptr; | ||
| 256 | char *upstream_ver1; | 251 | char *upstream_ver1; |
| 257 | char *upstream_ver2; | 252 | char *upstream_ver2; |
| 258 | int result; | 253 | int result; |
| 259 | 254 | ||
| 260 | /* Compare epoch */ | 255 | /* Compare epoch */ |
| 261 | if (ch_ver1[1] == ':') { | 256 | colon = strchr(ch_ver1, ':'); |
| 262 | epoch1 = ch_ver1[0]; | 257 | if (colon) { |
| 263 | ver1_ptr = strchr(ch_ver1, ':') + 1; | 258 | epoch1 = atoi(ch_ver1); |
| 264 | } else { | 259 | ch_ver1 = colon + 1; |
| 265 | epoch1 = '0'; | ||
| 266 | ver1_ptr = ch_ver1; | ||
| 267 | } | 260 | } |
| 268 | if (ch_ver2[1] == ':') { | 261 | colon = strchr(ch_ver2, ':'); |
| 269 | epoch2 = ch_ver2[0]; | 262 | if (colon) { |
| 270 | ver2_ptr = strchr(ch_ver2, ':') + 1; | 263 | epoch2 = atoi(ch_ver2); |
| 271 | } else { | 264 | ch_ver2 = colon + 1; |
| 272 | epoch2 = '0'; | ||
| 273 | ver2_ptr = ch_ver2; | ||
| 274 | } | 265 | } |
| 275 | if (epoch1 < epoch2) { | 266 | if (epoch1 < epoch2) { |
| 276 | return -1; | 267 | return -1; |
| 277 | } | 268 | } |
| 278 | else if (epoch1 > epoch2) { | 269 | if (epoch1 > epoch2) { |
| 279 | return 1; | 270 | return 1; |
| 280 | } | 271 | } |
| 281 | 272 | ||
| 282 | /* Compare upstream version */ | 273 | /* Compare upstream version */ |
| 283 | upstream_ver1 = xstrdup(ver1_ptr); | 274 | upstream_ver1 = xstrdup(ch_ver1); |
| 284 | upstream_ver2 = xstrdup(ver2_ptr); | 275 | upstream_ver2 = xstrdup(ch_ver2); |
| 285 | 276 | ||
| 286 | /* Chop off debian version, and store for later use */ | 277 | /* Chop off debian version, and store for later use */ |
| 287 | deb_ver1 = strrchr(upstream_ver1, '-'); | 278 | deb_ver1 = strrchr(upstream_ver1, '-'); |
