/** * 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; }
int main(int argc, char *argv[]) { const char *err; struct versionrevision ver, ref; if (argc < 4) { fprintf(stderr, "usage: %s: version op refversion\n", argv[0]); return 2; } err = parseversion(&ver, argv[1]); if (err) { fprintf(stderr, "Invalid version `%s': %s\n", argv[1], err); return 2; } err = parseversion(&ref, argv[3]); if (err) { fprintf(stderr, "Invalid version `%s': %s\n", argv[3], err); return 2; } return ! versionsatisfied3(&ver, &ref, argv[2]); }
int main(int argc, char *argv[]) { const char *err; struct versionrevision ver, ref; if (argc < 4) { fprintf(stderr, "usage: %s version1 lt|gt|le|ge|eq version2\n return value 0 if true, else 1\n", argv[0]); return 2; } err = parseversion(&ver, argv[1]); if (err) { fprintf(stderr, "Invalid version `%s': %s\n", argv[1], err); return 2; } err = parseversion(&ref, argv[3]); if (err) { fprintf(stderr, "Invalid version `%s': %s\n", argv[3], err); return 2; } return ! versionsatisfied3(&ver, &ref, argv[2]); }
void add_dependencies(struct pkginfo *dpkg, psys_pkg_t pkg) { struct dependency *dep; struct deppossi *depp; dep = nfmalloc(sizeof(*dep)); dep->up = dpkg; dep->next = NULL; dep->type = dep_depends; depp = nfmalloc(sizeof(*depp)); depp->up = dep; depp->next = NULL; depp->nextrev = NULL; depp->backrev = NULL; depp->ed = findpackage("lsb"); depp->verrel = dvr_laterequal; parseversion(&depp->version, psys_pkg_lsbversion(pkg)); dep->list = depp; dpkg->installed.depends = dep; }
/** * 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); }
static int do_register(psys_pkg_t pkg, psys_err_t *err, jmp_buf *buf) { int ret; char *dpkgname = NULL; const char *dpkgarch; struct pkginfo *dpkg; psys_flist_t flist = NULL; char *filelist_path = NULL; char *md5list_path = NULL; set_error_handler(err, *buf, out); dpkgname = dpkg_name(psys_pkg_vendor(pkg), psys_pkg_name(pkg)); dpkg = findpackage(dpkgname); if (ensure_not_installed(dpkg, err)) { ret = -1; goto out; } if (ensure_dependencies_met(pkg, err)) { ret = -1; goto out; } blankpackage(dpkg); blankpackageperfile(&dpkg->installed); /* Name, Version */ dpkg->name = dpkgname; parseversion(&dpkg->installed.version, psys_pkg_version(pkg)); /* Architecture */ dpkgarch = dpkg_arch(psys_pkg_arch(pkg), err); if (!dpkgarch) { ret = -1; goto out; } dpkg->installed.architecture = dpkgarch; /* Description */ set_description(dpkg, pkg); /* * Maintainer * * FIXME: Our Maintainer value does not conform to the format * mandated by the Debian Policy Manual (which is "Name <E-Mail>"), * but this is better than not specifying a Maintainer at all * (which is a mandatory field) */ dpkg->installed.maintainer = nfstrsave(psys_pkg_vendor(pkg)); /* Priority */ dpkg->priority = pri_optional; /* Dependencies */ add_dependencies(dpkg, pkg); flist = psys_pkg_flist(pkg, err); if (!flist) { ret = -1; goto out; } /* Installed Size */ set_installed_size(dpkg, flist); /* File List */ filelist_path = create_file_list(dpkg, flist, err); if (!filelist_path) { ret = -1; goto out; } /* MD5SUMS List */ md5list_path = create_md5sums_list(dpkg, flist, err); if (!md5list_path) { ret = -1; goto out; } dpkg->want = want_install; dpkg->status = stat_installed; modstatdb_note(dpkg); ret = 0; out: if (md5list_path) { if (ret == -1) remove(md5list_path); free(md5list_path); } if (filelist_path) { if (ret == -1) remove(filelist_path); free(filelist_path); } if (flist) psys_flist_free(flist); return ret; }
void 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; const char *emsg; struct versionrevision a, b; 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>")) { emsg= parseversion(&a,argv[0]); if (emsg) ohshit(_("version '%s' has bad syntax: %s"), argv[0], emsg); } else { blankversion(&a); } if (*argv[2] && strcmp(argv[2],"<unknown>")) { emsg= parseversion(&b,argv[2]); if (emsg) ohshit(_("version '%s' has bad syntax: %s"), argv[2], emsg); } else { blankversion(&b); } if (!informativeversion(&a)) { exit(informativeversion(&b) ? rip->if_none_a : rip->if_none_both); } else if (!informativeversion(&b)) { exit(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) exit(rip->if_greater); else if (r<0) exit(rip->if_lesser); else exit(rip->if_equal); }
static void test_version_parse(void) { struct versionrevision a, b; /* Test 0 versions. */ blankversion(&a); b = version(0, "0", ""); test_pass(parseversion(&a, "0") == NULL); test_pass(versioncompare(&a, &b) == 0); test_pass(parseversion(&a, "0:0") == NULL); test_pass(versioncompare(&a, &b) == 0); test_pass(parseversion(&a, "0:0-") == NULL); test_pass(versioncompare(&a, &b) == 0); b = version(0, "0", "0"); test_pass(parseversion(&a, "0:0-0") == NULL); test_pass(versioncompare(&a, &b) == 0); b = version(0, "0.0", "0.0"); test_pass(parseversion(&a, "0:0.0-0.0") == NULL); test_pass(versioncompare(&a, &b) == 0); /* Test epoched versions. */ b = version(1, "0", ""); test_pass(parseversion(&a, "1:0") == NULL); test_pass(versioncompare(&a, &b) == 0); b = version(5, "1", ""); test_pass(parseversion(&a, "5:1") == NULL); test_pass(versioncompare(&a, &b) == 0); /* Test multiple dashes. */ b = version(0, "0-0", "0"); test_pass(parseversion(&a, "0:0-0-0") == NULL); test_pass(versioncompare(&a, &b) == 0); b = version(0, "0-0-0", "0"); test_pass(parseversion(&a, "0:0-0-0-0") == NULL); test_pass(versioncompare(&a, &b) == 0); /* Test multiple colons. */ b = version(0, "0:0", "0"); test_pass(parseversion(&a, "0:0:0-0") == NULL); test_pass(versioncompare(&a, &b) == 0); b = version(0, "0:0:0", "0"); test_pass(parseversion(&a, "0:0:0:0-0") == NULL); test_pass(versioncompare(&a, &b) == 0); /* Test multiple dashes and colons. */ b = version(0, "0:0-0", "0"); test_pass(parseversion(&a, "0:0:0-0-0") == NULL); test_pass(versioncompare(&a, &b) == 0); b = version(0, "0-0:0", "0"); test_pass(parseversion(&a, "0:0-0:0-0") == NULL); test_pass(versioncompare(&a, &b) == 0); /* Test valid characters in upstream version. */ b = version(0, "azAZ09.-+~:", "0"); test_pass(parseversion(&a, "0:azAZ09.-+~:-0") == NULL); test_pass(versioncompare(&a, &b) == 0); /* Test valid characters in revision. */ b = version(0, "0", "azAZ09.+~"); test_pass(parseversion(&a, "0:0-azAZ09.+~") == NULL); test_pass(versioncompare(&a, &b) == 0); /* Test invalid characters in epoch. */ test_fail(parseversion(&a, "a:0-0") == NULL); test_fail(parseversion(&a, "A:0-0") == NULL); /* FIXME: parseversion() should validate input! */ #if 0 /* Test invalid characters in upstream version. */ test_fail(parseversion(&a, "0:!#@$%&/|\\<>()[]{};,=*^'-0") == NULL); /* Test invalid characters in revision. */ test_fail(parseversion(&a, "0:0-!#@$%&/|\\<>()[]{};,=*^'") == NULL); #endif /* FIXME: Complete. */ }
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 dpkg_version 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 { dpkg_version_blank(&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 { dpkg_version_blank(&b); } if (!dpkg_version_is_informative(&a)) { if (dpkg_version_is_informative(&b)) return rip->if_none_a; else return rip->if_none_both; } else if (!dpkg_version_is_informative(&b)) { return rip->if_none_b; } r = dpkg_version_compare(&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; }