/** * Parse a version string coming from a database file. * * It parses a version string, and prints a warning or an error depending * on the parse options. * * @param ps The parsedb state. * @param version The version to parse into. * @param value The version string to parse from. * * @retval 0 On success, and err is reset. * @retval -1 On failure, and err is set accordingly. */ int parse_db_version(struct parsedb_state *ps, struct dpkg_version *version, const char *value) { dpkg_error_destroy(&ps->err); if (parseversion(version, value, &ps->err) == 0) return 0; /* If not in lax mode, turn everything into an error. */ if (!(ps->flags & pdb_lax_version_parser)) ps->err.type = DPKG_MSG_ERROR; return -1; }
/** * Parse a version string coming from a database file. * * It parses a version string, and prints a warning or an error depending * on the parse options. * * @param ps The parsedb state. * @param version The version to parse into. * @param value The version string to parse from. * @param fmt The error format string. */ void parse_db_version(struct parsedb_state *ps, struct versionrevision *version, const char *value, const char *fmt, ...) { struct dpkg_error err; va_list args; char buf[1000]; if (parseversion(version, value, &err) == 0) return; va_start(args, fmt); vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); if (err.type == DPKG_MSG_WARN && (ps->flags & pdb_lax_parser)) parse_warn(ps, "%s: %.250s", buf, err.str); else parse_error(ps, "%s: %.250s", buf, err.str); dpkg_error_destroy(&err); }
int cmpversions(const char *const *argv) { struct relationinfo { const char *string; /* These values are exit status codes, so 0 = true, 1 = false. */ int if_lesser, if_equal, if_greater; int if_none_a, if_none_both, if_none_b; }; static const struct relationinfo relationinfos[]= { /* < = > !a!2!b */ { "le", 0,0,1, 0,0,1 }, { "lt", 0,1,1, 0,1,1 }, { "eq", 1,0,1, 1,0,1 }, { "ne", 0,1,0, 0,1,0 }, { "ge", 1,0,0, 1,0,0 }, { "gt", 1,1,0, 1,1,0 }, /* These treat an empty version as later than any version. */ { "le-nl", 0,0,1, 1,0,0 }, { "lt-nl", 0,1,1, 1,1,0 }, { "ge-nl", 1,0,0, 0,0,1 }, { "gt-nl", 1,1,0, 0,1,1 }, /* For compatibility with dpkg control file syntax. */ { "<", 0,0,1, 0,0,1 }, { "<=", 0,0,1, 0,0,1 }, { "<<", 0,1,1, 0,1,1 }, { "=", 1,0,1, 1,0,1 }, { ">", 1,0,0, 1,0,0 }, { ">=", 1,0,0, 1,0,0 }, { ">>", 1,1,0, 1,1,0 }, { NULL } }; const struct relationinfo *rip; struct versionrevision a, b; struct dpkg_error err; int r; if (!argv[0] || !argv[1] || !argv[2] || argv[3]) badusage(_("--compare-versions takes three arguments:" " <version> <relation> <version>")); for (rip=relationinfos; rip->string && strcmp(rip->string,argv[1]); rip++); if (!rip->string) badusage(_("--compare-versions bad relation")); if (*argv[0] && strcmp(argv[0],"<unknown>")) { if (parseversion(&a, argv[0], &err) < 0) { if (err.type == DPKG_MSG_WARN) warning(_("version '%s' has bad syntax: %s"), argv[0], err.str); else ohshit(_("version '%s' has bad syntax: %s"), argv[0], err.str); dpkg_error_destroy(&err); } } else { blankversion(&a); } if (*argv[2] && strcmp(argv[2],"<unknown>")) { if (parseversion(&b, argv[2], &err) < 0) { if (err.type == DPKG_MSG_WARN) warning(_("version '%s' has bad syntax: %s"), argv[2], err.str); else ohshit(_("version '%s' has bad syntax: %s"), argv[2], err.str); dpkg_error_destroy(&err); } } else { blankversion(&b); } if (!informativeversion(&a)) { return informativeversion(&b) ? rip->if_none_a : rip->if_none_both; } else if (!informativeversion(&b)) { return rip->if_none_b; } r= versioncompare(&a,&b); debug(dbg_general,"cmpversions a=`%s' b=`%s' r=%d", versiondescribe(&a,vdew_always), versiondescribe(&b,vdew_always), r); if (r > 0) return rip->if_greater; else if (r < 0) return rip->if_lesser; else return rip->if_equal; }