#define _POSIX_C_SOURCE 200809L #include #include #include #include #include "zpm.h" #include "sqlite3.h" #include "lib/jsw/jsw_atree.h" #define DMARK fprintf(stderr, "mark %s %s:%d\n", __FILE__, __func__, __LINE__) /* * flags 0 = find installed * flags 1 = skip installed * flags 2 = skip not installed */ struct zpm_package *zpm_package_alloc(struct zpm *zpm) { struct zpm_package *pkg; pkg = malloc(sizeof *pkg); if (pkg) { pkg->zpm = zpm; pkg->release = 0; } return pkg; } void zpm_sqlite_error(struct zpm *zpm) { zpm->error = 1; if (zpm->errmsg) free(zpm->errmsg); zpm->errmsg = strdup((const char *)sqlite3_errmsg(zpm->db)); } char *zpm_findlib(struct zpm *zpm, char *soname, char *where) { sqlite3_str *sql; char *query, *pkgid = 0; char *select = "select printf('%%s-%%s-%%s',P.package,P.version,P.release) as pkgid, P.package, P.version, P.release\ from packagefiles PF\ join elflibraries EL on EL.file = PF.hash\ join packages P on P.package = PF.package and P.version = PF.version and P.release = PF.release"; char *order = "order by P.package, P.version, cast(P.release as integer)"; /* null pkgstr find "best" package * best is shortest complete package if any are complete * shortest incomplete if any are incomplete * where more than one version is in those sets, best is * latest as determined by vercmp */ sql = sqlite3_str_new(zpm->db); sqlite3_str_appendall(sql, select); sqlite3_str_appendf(sql, " where P.hash is not null and EL.soname = %Q", soname); if (where) { sqlite3_str_appendall(sql, " and "); sqlite3_str_appendall(sql, where); } sqlite3_str_appendall(sql, " "); sqlite3_str_appendall(sql, order); sqlite3_str_appendall(sql, " limit 1;"); if (sqlite3_str_errcode(sql)) { zpm->error = 1; sqlite3_free(sqlite3_str_finish(sql)); return 0; } query = sqlite3_str_finish(sql); pkgid = zpm_db_string(zpm, query);; sqlite3_free(query); return pkgid; } int zpm_packages_needed(struct zpm *zpm, char *pkgid, jsw_atree_t *list) { char *pkglibsneeded = "select soname, selfsatisfied from package_libraries_needed where pkgid = %Q"; sqlite3_stmt *st; int count = 0; int rv; st = zpm_dbquery(zpm, pkglibsneeded, pkgid); while ((rv = sqlite3_step(st)) == SQLITE_ROW) { char *soname; int self; soname = (char *)sqlite3_column_text(st, 0); /* TODO check and skip self sats */ self = sqlite3_column_int(st,1); if (self) { continue; } count++; /* if it's in needed, we've already looked at this one */ if (list && !jsw_afind(list, soname)) { jsw_ainsert(list, soname); } } sqlite3_finalize(st); return count; } int zpm_libraries_needed(struct zpm *zpm, char *pkgid, jsw_atree_t *list) { char *pkglibsneeded = "select soname, selfsatisfied from package_libraries_needed where pkgid = %Q"; sqlite3_stmt *st; int count = 0; int rv; st = zpm_dbquery(zpm, pkglibsneeded, pkgid); while ((rv = sqlite3_step(st)) == SQLITE_ROW) { char *soname; int self; soname = (char *)sqlite3_column_text(st, 0); /* TODO check and skip self sats */ self = sqlite3_column_int(st,1); if (self) { continue; } count++; /* if it's in needed, we've already looked at this one */ if (list && !jsw_afind(list, soname)) { jsw_ainsert(list, soname); } } sqlite3_finalize(st); return count; } char *zpm_findpkg(struct zpm *zpm, char *pkgstr, char *where) { char *select = "select pkgid, package, version, release from packages_pkgid"; #if 0 char *group = "group by package having max( version||'-'||release collate vercmp) order by length(package), package, version||'-'||release collate vercmp"; #else char *group = "order by package, version collate vercmp desc, cast(release as integer)"; //group = "order by package, version , cast(release as integer)"; #endif sqlite3_str *sql; char *query, *pkgid = 0; /* null pkgstr find "best" package * best is shortest complete package if any are complete * shortest incomplete if any are incomplete * where more than one version is in those sets, best is * latest as determined by vercmp */ sql = sqlite3_str_new(zpm->db); sqlite3_str_appendall(sql, select); sqlite3_str_appendall(sql, " where true"); if (pkgstr) { int release; char version[32]; char package[32]; zpm_parse_package(pkgstr, package, version, &release); if (*package != 0) { sqlite3_str_appendf(sql, " and package = %Q", package); } if (*version != 0) { sqlite3_str_appendf(sql, " and version = %Q", version); } if (release != 0) { sqlite3_str_appendf(sql, " and release = %d", release); } } if (where) { sqlite3_str_appendall(sql, " and "); sqlite3_str_appendall(sql, where); } sqlite3_str_appendall(sql, " "); sqlite3_str_appendall(sql, group); sqlite3_str_appendall(sql, " limit 1;"); if (sqlite3_str_errcode(sql)) { zpm->error = 1; sqlite3_free(sqlite3_str_finish(sql)); return 0; } query = sqlite3_str_finish(sql); pkgid = zpm_db_string(zpm, query);; sqlite3_free(query); return pkgid; } char *zpm_findpkg_range(struct zpm *zpm, char *minpkg, char *maxpkg, char *where, int wantleast) { int release; char version[32]; char package[32]; char *select = "select pkgid, package, version, release from packages_pkgid"; char *last = "order by version collate vercmp desc, cast(release as integer) desc"; char *first = "order by version collate vercmp, cast(release as integer)"; char *group; char *query, *pkgid = 0; sqlite3_str *sql; group = wantleast ? first : last; /* null pkgstr find "best" package * best is shortest complete package if any are complete * shortest incomplete if any are incomplete * where more than one version is in those sets, best is * latest as determined by vercmp */ sql = sqlite3_str_new(zpm->db); sqlite3_str_appendall(sql, select); sqlite3_str_appendall(sql, " where true"); if (minpkg) { sqlite3_str_appendf(sql, " and pkgid >= %Q collate vercmp", minpkg); zpm_parse_package(minpkg, package, version, &release); if (*package != 0) { sqlite3_str_appendf(sql, " and package = %Q", package); } } if (maxpkg) { sqlite3_str_appendf(sql, " and pkgid <= %Q collate vercmp", maxpkg); zpm_parse_package(maxpkg, package, version, &release); if (*package != 0) { sqlite3_str_appendf(sql, " and package = %Q", package); } } if (where) { sqlite3_str_appendall(sql, " and "); sqlite3_str_appendall(sql, where); } sqlite3_str_appendall(sql, " "); sqlite3_str_appendall(sql, group); sqlite3_str_appendall(sql, " limit 1;"); if (sqlite3_str_errcode(sql)) { zpm->error = 1; sqlite3_free(sqlite3_str_finish(sql)); return 0; } query = sqlite3_str_finish(sql); pkgid = zpm_db_string(zpm, query);; sqlite3_free(query); return pkgid; }