aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-11-20 23:41:56 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-11-20 23:41:56 +0000
commitb8baf407aacc09167c4e9fa0db55fe323b15854e (patch)
treee16b83936ea6dcf30e8b9968c5068d03d6bacf55
parent9a4c0d59a79efeba4e1c5feed7d07b7c6b6b04ce (diff)
downloadbusybox-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.c127
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 ? */ 190static int order(char x)
187static 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 201static 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, '-');