00001
00004 #include "system.h"
00005
00006 #include <rpmiotypes.h>
00007 #include <rpmmacro.h>
00008 #define _MIRE_INTERNAL
00009 #include <mire.h>
00010
00011 #include <rpmtag.h>
00012 #define _RPMEVR_INTERNAL
00013 #include <rpmevr.h>
00014
00015 #include "debug.h"
00016
00017
00018 int _rpmevr_debug = 0;
00019
00020 #if !defined(MAX)
00021 #define MAX(x, y) ( ((x)>(y))?(x):(y) )
00022 #endif
00023
00024 EVR_t rpmEVRnew(rpmuint32_t Flags, int initialize)
00025 {
00026 EVR_t evr = xcalloc(1, sizeof(*evr));
00027 evr->Flags = Flags;
00028 if (initialize) {
00029
00030 evr->F[RPMEVR_E] = "0";
00031 evr->F[RPMEVR_V] = "";
00032 evr->F[RPMEVR_R] = "";
00033 evr->F[RPMEVR_D] = "";
00034
00035 }
00036 return evr;
00037 }
00038
00039 EVR_t rpmEVRfree(EVR_t evr)
00040 {
00041 if (evr != NULL) {
00042 evr->str = _free(evr->str);
00043 memset(evr, 0, sizeof(*evr));
00044 evr = _free(evr);
00045 }
00046 return NULL;
00047 }
00048
00049
00050
00051 #if defined(RPM_VENDOR_MANDRIVA)
00052 static int _invert_digits_alphas_comparison = -1;
00053 #else
00054 static int _invert_digits_alphas_comparison = 1;
00055 #endif
00056
00057
00058
00059 static const char * _rpmnotalpha = ".:-";
00060
00066 static inline int xisrpmalpha(int c)
00067
00068 {
00069 int rc = xisalpha(c);
00070 if (!rc)
00071 rc = xispunct(c);
00072 if (rc && _rpmnotalpha && *_rpmnotalpha)
00073 rc = (strchr(_rpmnotalpha, c) == NULL);
00074
00075 return rc;
00076
00077 }
00078
00079 int rpmEVRcmp(const char * a, const char * b)
00080
00081 {
00082 const char * ae = NULL, * be = NULL;
00083 int rc = 0;
00084
00085 assert(a != NULL);
00086 assert(b != NULL);
00087
00088 for (; *a && *b && rc == 0; a = ae, b = be) {
00089
00090
00091 while (*a && !(xisdigit((int)*a) || xisrpmalpha((int)*a))) a++;
00092 while (*b && !(xisdigit((int)*b) || xisrpmalpha((int)*b))) b++;
00093
00094
00095
00096 if (a[0] == '*' && a[1] == '\0') {
00097 be = strchr(b, '\0');
00098 } else
00099 if (b[0] == '*' && b[1] == '\0') {
00100 ae = strchr(a, '\0');
00101 } else
00102
00103 if (xisdigit((int)*a) || xisdigit((int)*b)) {
00104
00105 while (a[0] == '0' && xisdigit((int)a[1])) a++;
00106 while (b[0] == '0' && xisdigit((int)b[1])) b++;
00107
00108
00109 ae = a; while (xisdigit((int)*ae)) ae++;
00110 be = b; while (xisdigit((int)*be)) be++;
00111
00112
00113 if (a == ae || b == be)
00114 rc = (int)(*a - *b) * _invert_digits_alphas_comparison;
00115 else {
00116 rc = (ae - a) - (be - b);
00117 if (!rc)
00118 rc = strncmp(a, b, (ae - a));
00119 }
00120 } else {
00121
00122 ae = a; while (xisrpmalpha((int)*ae)) ae++;
00123 be = b; while (xisrpmalpha((int)*be)) be++;
00124
00125
00126 rc = strncmp(a, b, MAX((ae - a), (be - b)));
00127 }
00128 }
00129
00130
00131 if (!rc)
00132 rc = (int)(*a - *b);
00133
00134
00135 rc = (rc > 0 ? 1
00136 : rc < 0 ? -1
00137 : 0);
00138 return rc;
00139 }
00140
00141
00142 static const char * _evr_tuple_match =
00143 "^(?:([^:-]+):)?([^:-]+)(?:-([^:-]+))?(?::([^:-]+))?$";
00144
00145 const char * evr_tuple_match = NULL;
00146
00147 miRE evr_tuple_mire = NULL;
00148
00149 static miRE rpmEVRmire(void)
00150
00151 {
00152
00153 if (evr_tuple_mire == NULL) {
00154 int xx;
00155 evr_tuple_match = rpmExpand("%{?evr_tuple_match}", NULL);
00156 if (evr_tuple_match == NULL || evr_tuple_match[0] == '\0')
00157 evr_tuple_match = xstrdup(_evr_tuple_match);
00158
00159 evr_tuple_mire = mireNew(RPMMIRE_REGEX, 0);
00160 xx = mireSetCOptions(evr_tuple_mire, RPMMIRE_REGEX, 0, 0, NULL);
00161 xx = mireRegcomp(evr_tuple_mire, evr_tuple_match);
00162
00163 }
00164
00165 assert(evr_tuple_match != NULL && evr_tuple_mire != NULL);
00166
00167 return evr_tuple_mire;
00168
00169 }
00170
00171 int rpmEVRparse(const char * evrstr, EVR_t evr)
00172
00173 {
00174 miRE mire = rpmEVRmire();
00175 int noffsets = 6 * 3;
00176 int offsets[6 * 3];
00177 size_t nb;
00178 int xx;
00179 int i;
00180
00181 memset(evr, 0, sizeof(*evr));
00182 evr->str = xstrdup(evrstr);
00183 nb = strlen(evr->str);
00184
00185 memset(offsets, -1, sizeof(offsets));
00186 xx = mireSetEOptions(mire, offsets, noffsets);
00187
00188 xx = mireRegexec(mire, evr->str, strlen(evr->str));
00189
00190 for (i = 0; i < noffsets; i += 2) {
00191 int ix;
00192
00193 if (offsets[i] < 0)
00194 continue;
00195
00196 switch (i/2) {
00197 default:
00198 case 0: continue; break;
00199 case 1: ix = RPMEVR_E; break;
00200 case 2: ix = RPMEVR_V; break;
00201 case 3: ix = RPMEVR_R; break;
00202 case 4: ix = RPMEVR_D; break;
00203 }
00204
00205 assert(offsets[i ] >= 0 && offsets[i ] <= (int)nb);
00206 assert(offsets[i+1] >= 0 && offsets[i+1] <= (int)nb);
00207 { char * te = (char *) evr->str;
00208 evr->F[ix] = te + offsets[i];
00209 te += offsets[i+1];
00210 *te = '\0';
00211 }
00212
00213 }
00214
00215
00216 if (evr->F[RPMEVR_E] == NULL) evr->F[RPMEVR_E] = "0";
00217 if (evr->F[RPMEVR_V] == NULL) evr->F[RPMEVR_V] = "";
00218 if (evr->F[RPMEVR_R] == NULL) evr->F[RPMEVR_R] = "";
00219 if (evr->F[RPMEVR_D] == NULL) evr->F[RPMEVR_D] = "";
00220
00221 evr->Elong = strtoul(evr->F[RPMEVR_E], NULL, 10);
00222
00223 xx = mireSetEOptions(mire, NULL, 0);
00224
00225 return 0;
00226 }
00227
00234 static int compare_values(const char *a, const char *b)
00235
00236 {
00237 return rpmvercmp(a, b);
00238 }
00239
00240
00241 static const char * evr_tuple_order = NULL;
00242
00247
00248 static const char * rpmEVRorder(void)
00249
00250 {
00251
00252 if (evr_tuple_order == NULL) {
00253 evr_tuple_order = rpmExpand("%{?evr_tuple_order}", NULL);
00254 if (evr_tuple_order == NULL || evr_tuple_order[0] == '\0')
00255 evr_tuple_order = xstrdup("EVR");
00256 }
00257
00258 assert(evr_tuple_order != NULL && evr_tuple_order[0] != '\0');
00259 return evr_tuple_order;
00260 }
00261
00262 int rpmEVRcompare(const EVR_t a, const EVR_t b)
00263 {
00264 const char * s;
00265 int rc = 0;
00266
00267 assert(a->F[RPMEVR_E] != NULL);
00268 assert(a->F[RPMEVR_V] != NULL);
00269 assert(a->F[RPMEVR_R] != NULL);
00270 assert(a->F[RPMEVR_D] != NULL);
00271 assert(b->F[RPMEVR_E] != NULL);
00272 assert(b->F[RPMEVR_V] != NULL);
00273 assert(b->F[RPMEVR_R] != NULL);
00274 assert(b->F[RPMEVR_D] != NULL);
00275
00276 for (s = rpmEVRorder(); *s != '\0'; s++) {
00277 int ix;
00278 switch ((int)*s) {
00279 default: continue; break;
00280 case 'E': ix = RPMEVR_E; break;
00281 case 'V': ix = RPMEVR_V; break;
00282 case 'R': ix = RPMEVR_R; break;
00283 case 'D': ix = RPMEVR_D; break;
00284 }
00285 rc = compare_values(a->F[ix], b->F[ix]);
00286 if (rc)
00287 break;
00288 }
00289 return rc;
00290 }
00291
00292 int rpmEVRoverlap(EVR_t a, EVR_t b)
00293 {
00294 rpmsenseFlags aF = a->Flags;
00295 rpmsenseFlags bF = b->Flags;
00296 int sense;
00297 int result;
00298
00299
00300
00301 if (a->F[RPMEVR_E] == NULL) a->F[RPMEVR_E] = "0";
00302 if (b->F[RPMEVR_E] == NULL) b->F[RPMEVR_E] = "0";
00303 if (a->F[RPMEVR_V] == NULL) a->F[RPMEVR_V] = "";
00304 if (b->F[RPMEVR_V] == NULL) b->F[RPMEVR_V] = "";
00305 if (a->F[RPMEVR_R] == NULL) a->F[RPMEVR_R] = "";
00306 if (b->F[RPMEVR_R] == NULL) b->F[RPMEVR_R] = "";
00307 if (a->F[RPMEVR_D] == NULL) a->F[RPMEVR_D] = "";
00308 if (b->F[RPMEVR_D] == NULL) b->F[RPMEVR_D] = "";
00309
00310 sense = rpmEVRcompare(a, b);
00311
00312
00313 if (aF == RPMSENSE_NOTEQUAL || bF == RPMSENSE_NOTEQUAL)
00314 result = (sense != 0);
00315 else if (sense < 0 && ((aF & RPMSENSE_GREATER) || (bF & RPMSENSE_LESS)))
00316 result = 1;
00317 else if (sense > 0 && ((aF & RPMSENSE_LESS) || (bF & RPMSENSE_GREATER)))
00318 result = 1;
00319 else if (sense == 0 &&
00320 (((aF & RPMSENSE_EQUAL) && (bF & RPMSENSE_EQUAL)) ||
00321 ((aF & RPMSENSE_LESS) && (bF & RPMSENSE_LESS)) ||
00322 ((aF & RPMSENSE_GREATER) && (bF & RPMSENSE_GREATER))))
00323 result = 1;
00324 else
00325 result = 0;
00326 return result;
00327 }
00328
00329
00330 int (*rpmvercmp) (const char *a, const char *b) = rpmEVRcmp;
00331
00332
00335
00336 static struct EVRop_s {
00337
00338 const char * operator;
00339 rpmsenseFlags sense;
00340 } cops[] = {
00341 { "<=", RPMSENSE_LESS ^ RPMSENSE_EQUAL},
00342 { "=<", RPMSENSE_LESS ^ RPMSENSE_EQUAL},
00343
00344 { "==", RPMSENSE_EQUAL},
00345 { "!=", RPMSENSE_NOTEQUAL},
00346
00347 { ">=", RPMSENSE_GREATER ^ RPMSENSE_EQUAL},
00348 { "=>", RPMSENSE_GREATER ^ RPMSENSE_EQUAL},
00349
00350 { "<", RPMSENSE_LESS},
00351 { "=", RPMSENSE_EQUAL},
00352 { ">", RPMSENSE_GREATER},
00353
00354 { NULL, 0 },
00355 };
00356
00357 rpmsenseFlags rpmEVRflags(const char *op, const char **end)
00358 {
00359 rpmsenseFlags Flags = 0;
00360 struct EVRop_s *cop;
00361
00362 if (op == NULL || *op == '\0')
00363 Flags = RPMSENSE_EQUAL;
00364 else
00365 for (cop = cops; cop->operator != NULL; cop++) {
00366 if (strncmp(op, cop->operator, strlen(cop->operator)))
00367 continue;
00368 Flags = cop->sense;
00369 if (end)
00370 *end = op + strlen(cop->operator);
00371 break;
00372 }
00373 return Flags;
00374 }
00375
00376 int rpmVersionCompare(Header A, Header B)
00377 {
00378 HE_t Ahe = memset(alloca(sizeof(*Ahe)), 0, sizeof(*Ahe));
00379 HE_t Bhe = memset(alloca(sizeof(*Bhe)), 0, sizeof(*Bhe));
00380 const char * one, * two;
00381 rpmuint32_t Eone, Etwo;
00382 const char * s;
00383 int rc = 0;
00384 int xx;
00385
00386 for (s = rpmEVRorder(); *s != '\0'; s++) {
00387 switch ((int)*s) {
00388 default: continue; break;
00389 case 'E':
00390 Ahe->tag = RPMTAG_EPOCH;
00391 xx = headerGet(A, Ahe, 0);
00392 Eone = (xx && Ahe->p.ui32p ? Ahe->p.ui32p[0] : 0);
00393 Bhe->tag = RPMTAG_EPOCH;
00394 xx = headerGet(B, Bhe, 0);
00395 Etwo = (xx && Bhe->p.ui32p ? Bhe->p.ui32p[0] : 0);
00396 if (Eone < Etwo)
00397 rc = -1;
00398 else if (Eone > Etwo)
00399 rc = 1;
00400 break;
00401 case 'V':
00402 Ahe->tag = RPMTAG_VERSION;
00403 xx = headerGet(A, Ahe, 0);
00404 one = (xx && Ahe->p.str ? Ahe->p.str : "");
00405 Bhe->tag = RPMTAG_VERSION;
00406 xx = headerGet(B, Bhe, 0);
00407 two = (xx && Bhe->p.str ? Bhe->p.str : "");
00408 rc = rpmvercmp(one, two);
00409 break;
00410 case 'R':
00411 Ahe->tag = RPMTAG_RELEASE;
00412 xx = headerGet(A, Ahe, 0);
00413 one = (xx && Ahe->p.str ? Ahe->p.str : "");
00414 Bhe->tag = RPMTAG_RELEASE;
00415 xx = headerGet(B, Bhe, 0);
00416 two = (xx && Bhe->p.str ? Bhe->p.str : "");
00417 rc = rpmvercmp(one, two);
00418 break;
00419 case 'D':
00420 Ahe->tag = RPMTAG_DISTEPOCH;
00421 xx = headerGet(A, Ahe, 0);
00422 one = (xx && Ahe->p.str ? Ahe->p.str : "");
00423 Bhe->tag = RPMTAG_DISTEPOCH;
00424 xx = headerGet(B, Bhe, 0);
00425 two = (xx && Bhe->p.str ? Bhe->p.str : "");
00426 rc = rpmvercmp(one, two);
00427 break;
00428 }
00429 Ahe->p.ptr = _free(Ahe->p.ptr);
00430 Bhe->p.ptr = _free(Bhe->p.ptr);
00431 if (rc)
00432 break;
00433 }
00434 return rc;
00435 }