rpm 5.2.1
|
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 /*@unchecked@*/ 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 /*@-observertrans -readonlytrans @*/ 00030 evr->F[RPMEVR_E] = "0"; 00031 evr->F[RPMEVR_V] = ""; 00032 evr->F[RPMEVR_R] = ""; 00033 evr->F[RPMEVR_D] = ""; 00034 /*@=observertrans =readonlytrans @*/ 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 /* XXX Force digits to beat alphas. See bugzilla #50977. */ 00050 /*@unchecked@*/ 00051 #if defined(RPM_VENDOR_MANDRIVA) /* old-comparision-behaviour */ 00052 static int _invert_digits_alphas_comparison = -1; 00053 #else 00054 static int _invert_digits_alphas_comparison = 1; 00055 #endif 00056 00057 /* XXX Punctuation characters that are not treated as alphas */ 00058 /*@unchecked@*/ /*@observer@*/ 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 /*@-globstate@*/ 00075 return rc; 00076 /*@=globstate@*/ 00077 } 00078 00079 int rpmEVRcmp(const char * a, const char * b) 00080 /*@*/ 00081 { 00082 const char * ae = NULL, * be = NULL; 00083 int rc = 0; /* assume equal */ 00084 00085 assert(a != NULL); 00086 assert(b != NULL); 00087 /* Compare version strings segment by segment. */ 00088 for (; *a && *b && rc == 0; a = ae, b = be) { 00089 00090 /* Skip leading non-alpha, non-digit characters. */ 00091 while (*a && !(xisdigit((int)*a) || xisrpmalpha((int)*a))) a++; 00092 while (*b && !(xisdigit((int)*b) || xisrpmalpha((int)*b))) b++; 00093 00094 /* Wildcard comparison? */ 00095 /* Note: limited to suffix-only wildcard matching at the moment. */ 00096 if (a[0] == '*' && a[1] == '\0') { 00097 be = strchr(b, '\0'); /* XXX be = b + strlen(b); */ 00098 } else 00099 if (b[0] == '*' && b[1] == '\0') { 00100 ae = strchr(a, '\0'); /* XXX ae = a + strlen(a); */ 00101 } else 00102 /* Digit string comparison? */ 00103 if (xisdigit((int)*a) || xisdigit((int)*b)) { 00104 /* Discard leading zeroes. */ 00105 while (a[0] == '0' && xisdigit((int)a[1])) a++; 00106 while (b[0] == '0' && xisdigit((int)b[1])) b++; 00107 00108 /* Find end of digit strings. */ 00109 ae = a; while (xisdigit((int)*ae)) ae++; 00110 be = b; while (xisdigit((int)*be)) be++; 00111 00112 /* Calculate digit comparison return code. */ 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 /* Find end of alpha strings. */ 00122 ae = a; while (xisrpmalpha((int)*ae)) ae++; 00123 be = b; while (xisrpmalpha((int)*be)) be++; 00124 00125 /* Calculate alpha comparison return code. */ 00126 rc = strncmp(a, b, MAX((ae - a), (be - b))); 00127 } 00128 } 00129 00130 /* Longer string wins. */ 00131 if (!rc) 00132 rc = (int)(*a - *b); 00133 00134 /* Force strict -1, 0, 1 return. */ 00135 rc = (rc > 0 ? 1 00136 : rc < 0 ? -1 00137 : 0); 00138 return rc; 00139 } 00140 00141 /*@unchecked@*/ /*@observer@*/ /*@null@*/ 00142 static const char * _evr_tuple_match = 00143 "^(?:([^:-]+):)?([^:-]+)(?:-([^:-]+))?(?::([^:-]+))?$"; 00144 /*@unchecked@*/ /*@only@*/ /*@observer@*/ /*@null@*/ 00145 const char * evr_tuple_match = NULL; 00146 /*@unchecked@*/ /*@refcounted@*/ /*@null@*/ 00147 miRE evr_tuple_mire = NULL; 00148 00149 static miRE rpmEVRmire(void) 00150 /*@*/ 00151 { 00152 /*@-globs -internalglobs -mods @*/ 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 /*@=globs =internalglobs =mods @*/ 00165 assert(evr_tuple_match != NULL && evr_tuple_mire != NULL); 00166 /*@-globstate -retalias@*/ 00167 return evr_tuple_mire; 00168 /*@=globstate =retalias@*/ 00169 } 00170 00171 int rpmEVRparse(const char * evrstr, EVR_t evr) 00172 /*@modifies evrstr, evr @*/ 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; /*@notreached@*/ /*@switchbreak@*/ break; 00199 case 1: ix = RPMEVR_E; /*@switchbreak@*/break; 00200 case 2: ix = RPMEVR_V; /*@switchbreak@*/break; 00201 case 3: ix = RPMEVR_R; /*@switchbreak@*/break; 00202 case 4: ix = RPMEVR_D; /*@switchbreak@*/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 /* XXX HACK: postpone committing to single "missing" value for now. */ 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 /*@unchecked@*/ /*@only@*/ /*@observer@*/ /*@null@*/ 00241 static const char * evr_tuple_order = NULL; 00242 00247 /*@observer@*/ 00248 static const char * rpmEVRorder(void) 00249 /*@*/ 00250 { 00251 /*@-globs -internalglobs -mods @*/ 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 /*@=globs =internalglobs =mods @*/ 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; /*@notreached@*/ /*@switchbreak@*/break; 00280 case 'E': ix = RPMEVR_E; /*@switchbreak@*/break; 00281 case 'V': ix = RPMEVR_V; /*@switchbreak@*/break; 00282 case 'R': ix = RPMEVR_R; /*@switchbreak@*/break; 00283 case 'D': ix = RPMEVR_D; /*@switchbreak@*/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 /* XXX HACK: postpone committing to single "missing" value for now. */ 00300 /*@-mods -observertrans -readonlytrans @*/ 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 /*@=mods =observertrans =readonlytrans @*/ 00310 sense = rpmEVRcompare(a, b); 00311 00312 /* Detect overlap of {A,B} range. */ 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 /*@-redecl@*/ 00330 int (*rpmvercmp) (const char *a, const char *b) = rpmEVRcmp; 00331 /*@=redecl@*/ 00332 00335 /*@unchecked@*/ /*@observer@*/ 00336 static struct EVRop_s { 00337 /*@observer@*/ /*@null@*/ 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; /*@notreached@*/ /*@switchbreak@*/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 /*@switchbreak@*/ 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 /*@switchbreak@*/ 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 /*@switchbreak@*/ 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 /*@switchbreak@*/ 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 }