rpm 5.3.7
|
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(uint32_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 /*@-observertrans -readonlytrans@*/ 00217 if (evr->F[RPMEVR_E] == NULL) evr->F[RPMEVR_E] = "0"; 00218 if (evr->F[RPMEVR_V] == NULL) evr->F[RPMEVR_V] = ""; 00219 if (evr->F[RPMEVR_R] == NULL) evr->F[RPMEVR_R] = ""; 00220 if (evr->F[RPMEVR_D] == NULL) evr->F[RPMEVR_D] = ""; 00221 /*@=observertrans =readonlytrans@*/ 00222 00223 evr->Elong = strtoul(evr->F[RPMEVR_E], NULL, 10); 00224 00225 xx = mireSetEOptions(mire, NULL, 0); 00226 00227 return 0; 00228 } 00229 00236 static int compare_values(const char *a, const char *b) 00237 /*@*/ 00238 { 00239 return rpmvercmp(a, b); 00240 } 00241 00242 /*@unchecked@*/ /*@only@*/ /*@observer@*/ /*@null@*/ 00243 static const char * evr_tuple_order = NULL; 00244 00249 /*@observer@*/ 00250 static const char * rpmEVRorder(void) 00251 /*@*/ 00252 { 00253 /*@-globs -internalglobs -mods @*/ 00254 if (evr_tuple_order == NULL) { 00255 evr_tuple_order = rpmExpand("%{?evr_tuple_order}", NULL); 00256 if (evr_tuple_order == NULL || evr_tuple_order[0] == '\0') 00257 evr_tuple_order = xstrdup("EVR"); 00258 } 00259 /*@=globs =internalglobs =mods @*/ 00260 assert(evr_tuple_order != NULL && evr_tuple_order[0] != '\0'); 00261 return evr_tuple_order; 00262 } 00263 00264 int rpmEVRcompare(const EVR_t a, const EVR_t b) 00265 { 00266 const char * s; 00267 int rc = 0; 00268 00269 assert(a->F[RPMEVR_E] != NULL); 00270 assert(a->F[RPMEVR_V] != NULL); 00271 assert(a->F[RPMEVR_R] != NULL); 00272 assert(a->F[RPMEVR_D] != NULL); 00273 assert(b->F[RPMEVR_E] != NULL); 00274 assert(b->F[RPMEVR_V] != NULL); 00275 assert(b->F[RPMEVR_R] != NULL); 00276 assert(b->F[RPMEVR_D] != NULL); 00277 00278 for (s = rpmEVRorder(); *s != '\0'; s++) { 00279 int ix; 00280 #if defined(RPM_VENDOR_MANDRIVA) /* mdvbz#55810 */ 00281 if(*s == 'R' && (b->Flags & (~RPMSENSE_GREATER & RPMSENSE_EQUAL)) 00282 && *(b->F[RPMEVR_R]) == '\0') 00283 break; 00284 #endif 00285 00286 switch ((int)*s) { 00287 default: continue; /*@notreached@*/ /*@switchbreak@*/break; 00288 case 'E': ix = RPMEVR_E; /*@switchbreak@*/break; 00289 case 'V': ix = RPMEVR_V; /*@switchbreak@*/break; 00290 case 'R': ix = RPMEVR_R; /*@switchbreak@*/break; 00291 case 'D': ix = RPMEVR_D; /*@switchbreak@*/break; 00292 } 00293 rc = compare_values(a->F[ix], b->F[ix]); 00294 if (rc) 00295 break; 00296 } 00297 return rc; 00298 } 00299 00300 int rpmEVRoverlap(EVR_t a, EVR_t b) 00301 { 00302 rpmsenseFlags aF = a->Flags; 00303 rpmsenseFlags bF = b->Flags; 00304 int sense; 00305 int result; 00306 00307 /* XXX HACK: postpone committing to single "missing" value for now. */ 00308 /*@-mods -observertrans -readonlytrans @*/ 00309 if (a->F[RPMEVR_E] == NULL) a->F[RPMEVR_E] = "0"; 00310 if (b->F[RPMEVR_E] == NULL) b->F[RPMEVR_E] = "0"; 00311 if (a->F[RPMEVR_V] == NULL) a->F[RPMEVR_V] = ""; 00312 if (b->F[RPMEVR_V] == NULL) b->F[RPMEVR_V] = ""; 00313 if (a->F[RPMEVR_R] == NULL) a->F[RPMEVR_R] = ""; 00314 if (b->F[RPMEVR_R] == NULL) b->F[RPMEVR_R] = ""; 00315 if (a->F[RPMEVR_D] == NULL) a->F[RPMEVR_D] = ""; 00316 if (b->F[RPMEVR_D] == NULL) b->F[RPMEVR_D] = ""; 00317 /*@=mods =observertrans =readonlytrans @*/ 00318 sense = rpmEVRcompare(a, b); 00319 00320 /* Detect overlap of {A,B} range. */ 00321 if (aF == RPMSENSE_NOTEQUAL || bF == RPMSENSE_NOTEQUAL) 00322 result = (sense != 0); 00323 else if (sense < 0 && ((aF & RPMSENSE_GREATER) || (bF & RPMSENSE_LESS))) 00324 result = 1; 00325 else if (sense > 0 && ((aF & RPMSENSE_LESS) || (bF & RPMSENSE_GREATER))) 00326 result = 1; 00327 else if (sense == 0 && 00328 (((aF & RPMSENSE_EQUAL) && (bF & RPMSENSE_EQUAL)) || 00329 ((aF & RPMSENSE_LESS) && (bF & RPMSENSE_LESS)) || 00330 ((aF & RPMSENSE_GREATER) && (bF & RPMSENSE_GREATER)))) 00331 result = 1; 00332 else 00333 result = 0; 00334 return result; 00335 } 00336 00337 /*@-redecl@*/ 00338 int (*rpmvercmp) (const char *a, const char *b) = rpmEVRcmp; 00339 /*@=redecl@*/ 00340 00343 /*@unchecked@*/ /*@observer@*/ 00344 static struct EVRop_s { 00345 /*@observer@*/ /*@null@*/ 00346 const char * operator; 00347 rpmsenseFlags sense; 00348 } cops[] = { 00349 { "<=", RPMSENSE_LESS ^ RPMSENSE_EQUAL}, 00350 { "=<", RPMSENSE_LESS ^ RPMSENSE_EQUAL}, 00351 00352 { "==", RPMSENSE_EQUAL}, 00353 { "!=", RPMSENSE_NOTEQUAL}, 00354 00355 { ">=", RPMSENSE_GREATER ^ RPMSENSE_EQUAL}, 00356 { "=>", RPMSENSE_GREATER ^ RPMSENSE_EQUAL}, 00357 00358 { "<", RPMSENSE_LESS}, 00359 { "=", RPMSENSE_EQUAL}, 00360 { ">", RPMSENSE_GREATER}, 00361 00362 { NULL, 0 }, 00363 }; 00364 00365 rpmsenseFlags rpmEVRflags(const char *op, const char **end) 00366 { 00367 rpmsenseFlags Flags = 0; 00368 struct EVRop_s *cop; 00369 00370 if (op == NULL || *op == '\0') 00371 Flags = RPMSENSE_EQUAL; 00372 else 00373 for (cop = cops; cop->operator != NULL; cop++) { 00374 if (strncmp(op, cop->operator, strlen(cop->operator))) 00375 continue; 00376 Flags = cop->sense; 00377 if (end) 00378 *end = op + strlen(cop->operator); 00379 break; 00380 } 00381 return Flags; 00382 } 00383 00384 int rpmVersionCompare(Header A, Header B) 00385 { 00386 HE_t Ahe = memset(alloca(sizeof(*Ahe)), 0, sizeof(*Ahe)); 00387 HE_t Bhe = memset(alloca(sizeof(*Bhe)), 0, sizeof(*Bhe)); 00388 const char * one, * two; 00389 rpmuint32_t Eone, Etwo; 00390 const char * s; 00391 int rc = 0; 00392 int xx; 00393 00394 for (s = rpmEVRorder(); *s != '\0'; s++) { 00395 switch ((int)*s) { 00396 default: continue; /*@notreached@*/ /*@switchbreak@*/break; 00397 case 'E': 00398 Ahe->tag = RPMTAG_EPOCH; 00399 xx = headerGet(A, Ahe, 0); 00400 Eone = (xx && Ahe->p.ui32p ? Ahe->p.ui32p[0] : 0); 00401 Bhe->tag = RPMTAG_EPOCH; 00402 xx = headerGet(B, Bhe, 0); 00403 Etwo = (xx && Bhe->p.ui32p ? Bhe->p.ui32p[0] : 0); 00404 if (Eone < Etwo) 00405 rc = -1; 00406 else if (Eone > Etwo) 00407 rc = 1; 00408 /*@switchbreak@*/ break; 00409 case 'V': 00410 Ahe->tag = RPMTAG_VERSION; 00411 xx = headerGet(A, Ahe, 0); 00412 one = (xx && Ahe->p.str ? Ahe->p.str : ""); 00413 Bhe->tag = RPMTAG_VERSION; 00414 xx = headerGet(B, Bhe, 0); 00415 two = (xx && Bhe->p.str ? Bhe->p.str : ""); 00416 rc = rpmvercmp(one, two); 00417 /*@switchbreak@*/ break; 00418 case 'R': 00419 Ahe->tag = RPMTAG_RELEASE; 00420 xx = headerGet(A, Ahe, 0); 00421 one = (xx && Ahe->p.str ? Ahe->p.str : ""); 00422 Bhe->tag = RPMTAG_RELEASE; 00423 xx = headerGet(B, Bhe, 0); 00424 two = (xx && Bhe->p.str ? Bhe->p.str : ""); 00425 rc = rpmvercmp(one, two); 00426 /*@switchbreak@*/ break; 00427 case 'D': 00428 Ahe->tag = RPMTAG_DISTEPOCH; 00429 xx = headerGet(A, Ahe, 0); 00430 one = (xx && Ahe->p.str ? Ahe->p.str : ""); 00431 Bhe->tag = RPMTAG_DISTEPOCH; 00432 xx = headerGet(B, Bhe, 0); 00433 two = (xx && Bhe->p.str ? Bhe->p.str : ""); 00434 rc = rpmvercmp(one, two); 00435 /*@switchbreak@*/ break; 00436 } 00437 Ahe->p.ptr = _free(Ahe->p.ptr); 00438 Bhe->p.ptr = _free(Bhe->p.ptr); 00439 if (rc) 00440 break; 00441 } 00442 return rc; 00443 }