diff --git a/src/add.c b/src/add.c index 2863761..b26018e 100644 --- a/src/add.c +++ b/src/add.c @@ -111,7 +111,7 @@ static int add_main(void *ctx, struct apk_database *db, int argc, char **argv) apk_blob_t b = APK_BLOB_STR(argv[i]); apk_blob_pull_dep(&b, db, &dep); - if (APK_BLOB_IS_NULL(b)) { + if (APK_BLOB_IS_NULL(b) || b.len > 0) { apk_error("'%s' is not a valid dependency, format is name(@tag)([<>=]version)", argv[i]); return -1; diff --git a/src/apk_blob.h b/src/apk_blob.h index 55c21b7..55838ad 100644 --- a/src/apk_blob.h +++ b/src/apk_blob.h @@ -12,6 +12,7 @@ #ifndef APK_BLOB_H #define APK_BLOB_H +#include #include #include @@ -73,6 +74,14 @@ static inline apk_blob_t APK_BLOB_STR(const char *str) return ((apk_blob_t){strlen(str), (void *)(str)}); } +static inline apk_blob_t apk_blob_trim(apk_blob_t blob) +{ + apk_blob_t b = blob; + while (b.len > 0 && isspace(b.ptr[b.len-1])) + b.len--; + return b; +} + char *apk_blob_cstr(apk_blob_t str); int apk_blob_spn(apk_blob_t blob, const char *accept, apk_blob_t *l, apk_blob_t *r); int apk_blob_cspn(apk_blob_t blob, const char *reject, apk_blob_t *l, apk_blob_t *r); @@ -90,6 +99,11 @@ static inline void apk_blob_checksum(apk_blob_t b, const EVP_MD *md, struct apk_ csum->type = EVP_MD_size(md); EVP_Digest(b.ptr, b.len, csum->data, NULL, md, NULL); } +static inline char *apk_blob_chr(apk_blob_t b, unsigned char ch) +{ + return memchr(b.ptr, ch, b.len); +} + static inline const int apk_checksum_compare(const struct apk_checksum *a, const struct apk_checksum *b) { diff --git a/src/apk_database.h b/src/apk_database.h index c72a946..485afbe 100644 --- a/src/apk_database.h +++ b/src/apk_database.h @@ -133,6 +133,7 @@ struct apk_database { int missing_tags : 1; int compat_newfeatures : 1; int compat_notinstallable : 1; + int compat_old_world : 1; struct apk_dependency_array *world; struct apk_string_array *protected_paths; diff --git a/src/apk_package.h b/src/apk_package.h index a241a67..4fc6910 100644 --- a/src/apk_package.h +++ b/src/apk_package.h @@ -127,7 +127,7 @@ void apk_blob_pull_dep(apk_blob_t *from, struct apk_database *, struct apk_depen void apk_blob_pull_deps(apk_blob_t *from, struct apk_database *, struct apk_dependency_array **); int apk_deps_write(struct apk_database *db, struct apk_dependency_array *deps, - struct apk_ostream *os); + struct apk_ostream *os, apk_blob_t separator); int apk_deps_add(struct apk_dependency_array **depends, struct apk_dependency *dep); diff --git a/src/database.c b/src/database.c index e3c10c5..57c9009 100644 --- a/src/database.c +++ b/src/database.c @@ -917,6 +917,9 @@ static int apk_db_read_state(struct apk_database *db, int flags) blob = apk_blob_from_file(db->root_fd, apk_world_file); if (APK_BLOB_IS_NULL(blob)) return -ENOENT; + blob = apk_blob_trim(blob); + if (apk_blob_chr(blob, ' ')) + db->compat_old_world = 1; apk_blob_pull_deps(&blob, db, &db->world); free(blob.ptr); } @@ -1312,10 +1315,11 @@ int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts) goto ret_r; } - for (i = 0; i < db->num_repo_tags; i++) { + /* repository id 0 is the no-tag repo */ + for (i = 1; i < db->num_repo_tags; i++) { if (!db->repo_tags[i].allowed_repos) { - apk_warning("Repository tag '" BLOB_FMT "' used in world is no longer available", - BLOB_PRINTF(*db->repo_tags[i].name)); + apk_warning("Repository tag (%d) '" BLOB_FMT "' used in world is no longer available", + i, BLOB_PRINTF(*db->repo_tags[i].name)); db->missing_tags = 1; } } @@ -1364,7 +1368,7 @@ int apk_db_write_config(struct apk_database *db) if (os == NULL) return -1; - apk_deps_write(db, db->world, os); + apk_deps_write(db, db->world, os, APK_BLOB_PTR_LEN(db->compat_old_world ? " " : "\n", 1)); os->write(os, "\n", 1); r = os->close(os); if (r < 0) diff --git a/src/info.c b/src/info.c index 25731cc..28ce855 100644 --- a/src/info.c +++ b/src/info.c @@ -75,7 +75,11 @@ static int info_exists(struct info_ctx *ctx, struct apk_database *db, for (i = 0; i < argc; i++) { apk_blob_t b = APK_BLOB_STR(argv[i]); + apk_blob_pull_dep(&b, db, &dep); + if (APK_BLOB_IS_NULL(b) || b.len > 0) + continue; + name = dep.name; if (name == NULL) continue; @@ -131,7 +135,7 @@ static int info_who_owns(struct info_ctx *ctx, struct apk_database *db, struct apk_ostream *os; os = apk_ostream_to_fd(STDOUT_FILENO); - apk_deps_write(db, deps, os); + apk_deps_write(db, deps, os, APK_BLOB_PTR_LEN(" ", 1)); os->write(os, "\n", 1); os->close(os); } diff --git a/src/lua-apk.c b/src/lua-apk.c index e41e785..6fbd1cf 100644 --- a/src/lua-apk.c +++ b/src/lua-apk.c @@ -208,7 +208,7 @@ static int Papk_exists(lua_State *L) apk_blob_t blob = APK_BLOB_STR(depstr); apk_blob_pull_dep(&blob, db, &dep); - if (APK_BLOB_IS_NULL(blob)) + if (APK_BLOB_IS_NULL(blob) || b.len > 0) goto ret_nil; name = dep.name; diff --git a/src/package.c b/src/package.c index 97a45c6..1cd85dd 100644 --- a/src/package.c +++ b/src/package.c @@ -189,27 +189,36 @@ void apk_deps_del(struct apk_dependency_array **pdeps, } } -struct parse_depend_ctx { - struct apk_database *db; - struct apk_dependency_array **depends; -}; - void apk_blob_pull_dep(apk_blob_t *b, struct apk_database *db, struct apk_dependency *dep) { struct apk_name *name; - apk_blob_t bname, bop, bver = APK_BLOB_NULL, btag; + apk_blob_t bdep, bname, bop, bver = APK_BLOB_NULL, btag; int mask = APK_DEPMASK_REQUIRE, optional = 0, tag = 0; - size_t len; - /* [!]name[<,<=,=,>=,>]ver */ + /* [!]name[<,<=,=,>=,>,><]ver */ if (APK_BLOB_IS_NULL(*b)) goto fail; - if (b->ptr[0] == '!') { - b->ptr++; - b->len--; + + /* grap one token */ + if (!apk_blob_cspn(*b, " \n", &bdep, NULL)) + bdep = *b; + b->ptr += bdep.len; + b->len -= bdep.len; + + /* skip also all separator chars */ + if (!apk_blob_spn(*b, " \n", NULL, b)) { + b->ptr += b->len; + b->len = 0; + } + + /* parse the version */ + if (bdep.ptr[0] == '!') { + bdep.ptr++; + bdep.len--; optional = 1; } - if (apk_blob_cspn(*b, "<>= ", &bname, &bop)) { + + if (apk_blob_cspn(bdep, "<>=", &bname, &bop)) { int i; if (mask == 0) @@ -234,17 +243,15 @@ void apk_blob_pull_dep(apk_blob_t *b, struct apk_database *db, struct apk_depend !apk_version_validate(bver)) goto fail; } else { - bname = *b; + bname = bdep; bop = APK_BLOB_NULL; bver = APK_BLOB_NULL; } - len = bname.len + bop.len + bver.len; - b->ptr += len; - b->len -= len; if (apk_blob_split(bname, APK_BLOB_STR("@"), &bname, &btag)) tag = apk_db_get_tag_id(db, btag); + /* convert to apk_dependency */ name = apk_db_get_name(db, bname); if (name == NULL) goto fail; @@ -265,6 +272,19 @@ fail: *b = APK_BLOB_NULL; } +void apk_blob_pull_deps(apk_blob_t *b, struct apk_database *db, struct apk_dependency_array **deps) +{ + struct apk_dependency dep; + + while (b->len > 0) { + apk_blob_pull_dep(b, db, &dep); + if (APK_BLOB_IS_NULL(*b) || dep.name == NULL) + break; + + *apk_dependency_array_add(deps) = dep; + } +} + void apk_dep_from_pkg(struct apk_dependency *dep, struct apk_database *db, struct apk_package *pkg) { @@ -281,26 +301,6 @@ void apk_dep_from_pkg(struct apk_dependency *dep, struct apk_database *db, }; } -static int parse_depend(void *ctx, apk_blob_t blob) -{ - struct parse_depend_ctx *pctx = (struct parse_depend_ctx *) ctx; - struct apk_dependency *dep, p; - - if (blob.len == 0) - return 0; - - apk_blob_pull_dep(&blob, pctx->db, &p); - if (p.name == NULL || blob.len != 0) - return -1; - - dep = apk_dependency_array_add(pctx->depends); - if (dep == NULL) - return -1; - *dep = p; - - return 0; -} - int apk_dep_is_satisfied(struct apk_dependency *dep, struct apk_package *pkg) { if (pkg == NULL) @@ -322,16 +322,6 @@ int apk_dep_is_satisfied(struct apk_dependency *dep, struct apk_package *pkg) return 0; } -void apk_blob_pull_deps(apk_blob_t *b, struct apk_database *db, struct apk_dependency_array **deps) -{ - struct parse_depend_ctx ctx = { db, deps }; - - if (b->len > 0 && b->ptr[b->len-1] == '\n') - b->len--; - - apk_blob_for_each_segment(*b, " ", parse_depend, &ctx); -} - void apk_blob_push_dep(apk_blob_t *to, struct apk_database *db, struct apk_dependency *dep) { int result_mask = dep->result_mask; @@ -366,7 +356,7 @@ void apk_blob_push_deps(apk_blob_t *to, struct apk_database *db, struct apk_depe } } -int apk_deps_write(struct apk_database *db, struct apk_dependency_array *deps, struct apk_ostream *os) +int apk_deps_write(struct apk_database *db, struct apk_dependency_array *deps, struct apk_ostream *os, apk_blob_t separator) { apk_blob_t blob; char tmp[256]; @@ -378,7 +368,7 @@ int apk_deps_write(struct apk_database *db, struct apk_dependency_array *deps, s for (i = 0; i < deps->num; i++) { blob = APK_BLOB_BUF(tmp); if (i) - apk_blob_push_blob(&blob, APK_BLOB_PTR_LEN(" ", 1)); + apk_blob_push_blob(&blob, separator); apk_blob_push_dep(&blob, db, &deps->item[i]); blob = apk_blob_pushed(APK_BLOB_BUF(tmp), blob); @@ -1008,7 +998,7 @@ static int write_depends(struct apk_ostream *os, const char *field, if (os->write(os, field, 2) != 2) return -1; - r = apk_deps_write(NULL, deps, os); + r = apk_deps_write(NULL, deps, os, APK_BLOB_PTR_LEN(" ", 1)); if (r < 0) return r; if (os->write(os, "\n", 1) != 1)