| /* |
| * libdpkg - Debian packaging suite library routines |
| * vercmp.c - comparison of version numbers |
| * |
| * Copyright © 1995 Ian Jackson <ian@chiark.greenend.org.uk> |
| * |
| * This is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * This is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program. If not, see <http://www.gnu.org/licenses/>. |
| */ |
| |
| #include <config.h> |
| #include <compat.h> |
| |
| #include <ctype.h> |
| #include <string.h> |
| |
| #include <dpkg/dpkg.h> |
| #include <dpkg/dpkg-db.h> |
| #include <dpkg/parsedump.h> |
| |
| bool |
| epochsdiffer(const struct versionrevision *a, |
| const struct versionrevision *b) |
| { |
| return a->epoch != b->epoch; |
| } |
| |
| /** |
| * Give a weight to the character to order in the version comparison. |
| * |
| * @param c An ASCII character. |
| */ |
| static int |
| order(int c) |
| { |
| if (cisdigit(c)) |
| return 0; |
| else if (cisalpha(c)) |
| return c; |
| else if (c == '~') |
| return -1; |
| else if (c) |
| return c + 256; |
| else |
| return 0; |
| } |
| |
| static int verrevcmp(const char *val, const char *ref) { |
| if (!val) val= ""; |
| if (!ref) ref= ""; |
| |
| while (*val || *ref) { |
| int first_diff= 0; |
| |
| while ( (*val && !cisdigit(*val)) || (*ref && !cisdigit(*ref)) ) { |
| int vc= order(*val), rc= order(*ref); |
| if (vc != rc) return vc - rc; |
| val++; ref++; |
| } |
| |
| while ( *val == '0' ) val++; |
| while ( *ref == '0' ) ref++; |
| while (cisdigit(*val) && cisdigit(*ref)) { |
| if (!first_diff) first_diff= *val - *ref; |
| val++; ref++; |
| } |
| if (cisdigit(*val)) return 1; |
| if (cisdigit(*ref)) return -1; |
| if (first_diff) return first_diff; |
| } |
| return 0; |
| } |
| |
| int versioncompare(const struct versionrevision *version, |
| const struct versionrevision *refversion) { |
| int r; |
| |
| if (version->epoch > refversion->epoch) return 1; |
| if (version->epoch < refversion->epoch) return -1; |
| r= verrevcmp(version->version,refversion->version); if (r) return r; |
| return verrevcmp(version->revision,refversion->revision); |
| } |
| |
| bool |
| versionsatisfied3(const struct versionrevision *it, |
| const struct versionrevision *ref, |
| enum depverrel verrel) |
| { |
| int r; |
| if (verrel == dvr_none) |
| return true; |
| r= versioncompare(it,ref); |
| switch (verrel) { |
| case dvr_earlierequal: return r <= 0; |
| case dvr_laterequal: return r >= 0; |
| case dvr_earlierstrict: return r < 0; |
| case dvr_laterstrict: return r > 0; |
| case dvr_exact: return r == 0; |
| default: |
| internerr("unknown depverrel '%d'", verrel); |
| } |
| return false; |
| } |
| |
| bool |
| versionsatisfied(struct pkgbin *it, struct deppossi *against) |
| { |
| return versionsatisfied3(&it->version,&against->version,against->verrel); |
| } |