static inline int rpmdsCompareEVR(const char *AEVR, uint32_t AFlags, const char *BEVR, uint32_t BFlags, int nopromote) { const char *aE, *aV, *aR, *bE, *bV, *bR; char *aEVR = xstrdup(AEVR); char *bEVR = xstrdup(BEVR); int sense = 0; int result = 0; parseEVR(aEVR, &aE, &aV, &aR); parseEVR(bEVR, &bE, &bV, &bR); /* Compare {A,B} [epoch:]version[-release] */ if (aE && *aE && bE && *bE) sense = rpmvercmp(aE, bE); else if (aE && *aE && atol(aE) > 0) { if (!nopromote) { sense = 0; } else sense = 1; } else if (bE && *bE && atol(bE) > 0) sense = -1; if (sense == 0) { sense = rpmvercmp(aV, bV); if (sense == 0) { if (aR && *aR && bR && *bR) { sense = rpmvercmp(aR, bR); } else { /* always matches if the side with no release has SENSE_EQUAL */ if ((aR && *aR && (BFlags & RPMSENSE_EQUAL)) || (bR && *bR && (AFlags & RPMSENSE_EQUAL))) { aEVR = _free(aEVR); bEVR = _free(bEVR); result = 1; goto exit; } } } } /* Detect overlap of {A,B} range. */ if (sense < 0 && ((AFlags & RPMSENSE_GREATER) || (BFlags & RPMSENSE_LESS))) { result = 1; } else if (sense > 0 && ((AFlags & RPMSENSE_LESS) || (BFlags & RPMSENSE_GREATER))) { result = 1; } else if (sense == 0 && (((AFlags & RPMSENSE_EQUAL) && (BFlags & RPMSENSE_EQUAL)) || ((AFlags & RPMSENSE_LESS) && (BFlags & RPMSENSE_LESS)) || ((AFlags & RPMSENSE_GREATER) && (BFlags & RPMSENSE_GREATER)))) { result = 1; } exit: free(aEVR); free(bEVR); return result; }
/** Compare two version strings and determine which one is 'newer'. * Returns a value comparable to the way strcmp works. Returns 1 * if a is newer than b, 0 if a and b are the same version, or -1 * if b is newer than a. * * Different epoch values for version strings will override any further * comparison. If no epoch is provided, 0 is assumed. * * Keep in mind that the pkgrel is only compared if it is available * on both versions handed to this function. For example, comparing * 1.5-1 and 1.5 will yield 0; comparing 1.5-1 and 1.5-2 will yield * -1 as expected. This is mainly for supporting versioned dependencies * that do not include the pkgrel. */ int SYMEXPORT alpm_pkg_vercmp(const char *a, const char *b) { char *full1, *full2; const char *epoch1, *ver1, *rel1; const char *epoch2, *ver2, *rel2; int ret; /* ensure our strings are not null */ if(!a && !b) { return 0; } else if(!a) { return -1; } else if(!b) { return 1; } /* another quick shortcut- if full version specs are equal */ if(strcmp(a, b) == 0) { return 0; } /* Parse both versions into [epoch:]version[-release] triplets. We probably * don't need epoch and release to support all the same magic, but it is * easier to just run it all through the same code. */ full1 = strdup(a); full2 = strdup(b); /* parseEVR modifies passed in version, so have to dupe it first */ parseEVR(full1, &epoch1, &ver1, &rel1); parseEVR(full2, &epoch2, &ver2, &rel2); ret = rpmvercmp(epoch1, epoch2); if(ret == 0) { ret = rpmvercmp(ver1, ver2); if(ret == 0 && rel1 && rel2) { ret = rpmvercmp(rel1, rel2); } } free(full1); free(full2); return ret; }
int rpmdsCompare(const rpmds A, const rpmds B) { char *aEVR, *bEVR; const char *aE, *aV, *aR, *bE, *bV, *bR; int result; int sense; /* Different names don't overlap. */ if (!rstreq(A->N[A->i], B->N[B->i])) { result = 0; goto exit; } /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */ if (!(A->EVR && A->Flags && B->EVR && B->Flags)) { result = 1; goto exit; } /* Same name. If either A or B is an existence test, always overlap. */ if (!((A->Flags[A->i] & RPMSENSE_SENSEMASK) && (B->Flags[B->i] & RPMSENSE_SENSEMASK))) { result = 1; goto exit; } /* If either EVR is non-existent or empty, always overlap. */ if (!(A->EVR[A->i] && *A->EVR[A->i] && B->EVR[B->i] && *B->EVR[B->i])) { result = 1; goto exit; } /* Both AEVR and BEVR exist. */ aEVR = xstrdup(A->EVR[A->i]); parseEVR(aEVR, &aE, &aV, &aR); bEVR = xstrdup(B->EVR[B->i]); parseEVR(bEVR, &bE, &bV, &bR); /* Compare {A,B} [epoch:]version[-release] */ sense = 0; if (aE && *aE && bE && *bE) sense = rpmvercmp(aE, bE); else if (aE && *aE && atol(aE) > 0) { if (!B->nopromote) { sense = 0; } else sense = 1; } else if (bE && *bE && atol(bE) > 0) sense = -1; if (sense == 0) { sense = rpmvercmp(aV, bV); if (sense == 0) { if (aR && *aR && bR && *bR) { sense = rpmvercmp(aR, bR); } else { /* always matches if the side with no release has SENSE_EQUAL */ if ((aR && *aR && (B->Flags[B->i] & RPMSENSE_EQUAL)) || (bR && *bR && (A->Flags[A->i] & RPMSENSE_EQUAL))) { aEVR = _free(aEVR); bEVR = _free(bEVR); result = 1; goto exit; } } } } aEVR = _free(aEVR); bEVR = _free(bEVR); /* Detect overlap of {A,B} range. */ result = 0; if (sense < 0 && ((A->Flags[A->i] & RPMSENSE_GREATER) || (B->Flags[B->i] & RPMSENSE_LESS))) { result = 1; } else if (sense > 0 && ((A->Flags[A->i] & RPMSENSE_LESS) || (B->Flags[B->i] & RPMSENSE_GREATER))) { result = 1; } else if (sense == 0 && (((A->Flags[A->i] & RPMSENSE_EQUAL) && (B->Flags[B->i] & RPMSENSE_EQUAL)) || ((A->Flags[A->i] & RPMSENSE_LESS) && (B->Flags[B->i] & RPMSENSE_LESS)) || ((A->Flags[A->i] & RPMSENSE_GREATER) && (B->Flags[B->i] & RPMSENSE_GREATER)))) { result = 1; } exit: return result; }