io: rework apk_istream_get_* to not return erros in blob value

The interface was slightly cumbersome, so replace these functions
to return explicit error, and make the return blob a pointer arg.
cute-signatures
Timo Teräs 2021-07-17 15:43:08 +03:00
parent 94c5e01038
commit b559a81694
10 changed files with 68 additions and 66 deletions

View File

@ -20,12 +20,12 @@ int adb_walk_text(struct adb_walk *d, struct apk_istream *is)
uint8_t started[64] = {0}; uint8_t started[64] = {0};
if (IS_ERR_OR_NULL(is)) return PTR_ERR(is); if (IS_ERR_OR_NULL(is)) return PTR_ERR(is);
l = apk_istream_get_delim(is, token); if (apk_istream_get_delim(is, token, &l) != 0) goto err;
apk_blob_pull_blob_match(&l, APK_BLOB_STR("#%SCHEMA: ")); apk_blob_pull_blob_match(&l, APK_BLOB_STR("#%SCHEMA: "));
if ((r = d->ops->schema(d, apk_blob_pull_uint(&l, 16))) != 0) goto err; if ((r = d->ops->schema(d, apk_blob_pull_uint(&l, 16))) != 0) goto err;
started[0] = 1; started[0] = 1;
while (!APK_BLOB_IS_NULL(l = apk_istream_get_delim(is, token))) { while (apk_istream_get_delim(is, token, &l) == 0) {
for (i = 0; l.len >= 2 && l.ptr[0] == ' ' && l.ptr[1] == ' '; i++, l.ptr += 2, l.len -= 2) for (i = 0; l.len >= 2 && l.ptr[0] == ' ' && l.ptr[1] == ' '; i++, l.ptr += 2, l.len -= 2)
if (multi_line && i >= multi_line) break; if (multi_line && i >= multi_line) break;

View File

@ -64,7 +64,6 @@ static inline const EVP_MD *apk_checksum_default(void)
#define APK_BLOB_IS_NULL(blob) ((blob).ptr == NULL) #define APK_BLOB_IS_NULL(blob) ((blob).ptr == NULL)
#define APK_BLOB_NULL ((apk_blob_t){0, NULL}) #define APK_BLOB_NULL ((apk_blob_t){0, NULL})
#define APK_BLOB_ERROR(err) ((apk_blob_t){err, NULL})
#define APK_BLOB_BUF(buf) ((apk_blob_t){sizeof(buf), (char *)(buf)}) #define APK_BLOB_BUF(buf) ((apk_blob_t){sizeof(buf), (char *)(buf)})
#define APK_BLOB_CSUM(csum) ((apk_blob_t){(csum).type, (char *)(csum).data}) #define APK_BLOB_CSUM(csum) ((apk_blob_t){(csum).type, (char *)(csum).data})
#define APK_BLOB_STRUCT(s) ((apk_blob_t){sizeof(s), (char*)&(s)}) #define APK_BLOB_STRUCT(s) ((apk_blob_t){sizeof(s), (char*)&(s)})

View File

@ -98,9 +98,9 @@ apk_blob_t apk_istream_mmap(struct apk_istream *is);
ssize_t apk_istream_read(struct apk_istream *is, void *ptr, size_t size); ssize_t apk_istream_read(struct apk_istream *is, void *ptr, size_t size);
void *apk_istream_peek(struct apk_istream *is, size_t len); void *apk_istream_peek(struct apk_istream *is, size_t len);
void *apk_istream_get(struct apk_istream *is, size_t len); void *apk_istream_get(struct apk_istream *is, size_t len);
apk_blob_t apk_istream_get_max(struct apk_istream *is, size_t size); int apk_istream_get_max(struct apk_istream *is, size_t size, apk_blob_t *data);
apk_blob_t apk_istream_get_delim(struct apk_istream *is, apk_blob_t token); int apk_istream_get_delim(struct apk_istream *is, apk_blob_t token, apk_blob_t *data);
static inline apk_blob_t apk_istream_get_all(struct apk_istream *is) { return apk_istream_get_max(is, APK_IO_ALL); } static inline int apk_istream_get_all(struct apk_istream *is, apk_blob_t *data) { return apk_istream_get_max(is, APK_IO_ALL, data); }
ssize_t apk_istream_splice(struct apk_istream *is, int fd, size_t size, ssize_t apk_istream_splice(struct apk_istream *is, int fd, size_t size,
apk_progress_cb cb, void *cb_ctx, struct apk_digest_ctx *dctx); apk_progress_cb cb, void *cb_ctx, struct apk_digest_ctx *dctx);
ssize_t apk_stream_copy(struct apk_istream *is, struct apk_ostream *os, size_t size, ssize_t apk_stream_copy(struct apk_istream *is, struct apk_ostream *os, size_t size,

View File

@ -86,19 +86,17 @@ static int read_triggers(struct conv_ctx *ctx, struct apk_istream *is)
if (IS_ERR(is)) return PTR_ERR(is); if (IS_ERR(is)) return PTR_ERR(is);
while (!APK_BLOB_IS_NULL(l = apk_istream_get_delim(is, nl))) { while (apk_istream_get_delim(is, nl, &l) == 0) {
if (!apk_blob_split(l, spc, &l, &r)) continue; if (!apk_blob_split(l, spc, &l, &r)) continue;
s = find_pkg(ctx, l, ADBI_SCRPT_TRIGGER); s = find_pkg(ctx, l, ADBI_SCRPT_TRIGGER);
if (!s) continue; if (!s) continue;
s->triggers = apk_atomize_dup(&ctx->atoms, r); s->triggers = apk_atomize_dup(&ctx->atoms, r);
} }
return apk_istream_close(is);
apk_istream_close(is);
return 0;
} }
static void convert_idb(struct conv_ctx *ctx, struct apk_istream *is) static int convert_idb(struct conv_ctx *ctx, struct apk_istream *is)
{ {
struct apk_id_cache *idc = apk_ctx_get_id_cache(ctx->ac); struct apk_id_cache *idc = apk_ctx_get_id_cache(ctx->ac);
struct apk_checksum csum; struct apk_checksum csum;
@ -117,7 +115,7 @@ static void convert_idb(struct conv_ctx *ctx, struct apk_istream *is)
adb_wo_alloca(&pkg, &schema_package, &ctx->dbp); adb_wo_alloca(&pkg, &schema_package, &ctx->dbp);
adb_wo_alloca(&acl, &schema_acl, &ctx->dbp); adb_wo_alloca(&acl, &schema_acl, &ctx->dbp);
while (!APK_BLOB_IS_NULL(l = apk_istream_get_delim(is, nl))) { while (apk_istream_get_delim(is, nl, &l) == 0) {
if (l.len < 2) { if (l.len < 2) {
adb_wa_append_obj(&files, &file); adb_wa_append_obj(&files, &file);
adb_wo_obj(&path, ADBI_DI_FILES, &files); adb_wo_obj(&path, ADBI_DI_FILES, &files);
@ -191,6 +189,7 @@ static void convert_idb(struct conv_ctx *ctx, struct apk_istream *is)
break; break;
} }
} }
return apk_istream_close(is);
} }
static int conv_main(void *pctx, struct apk_ctx *ac, struct apk_string_array *args) static int conv_main(void *pctx, struct apk_ctx *ac, struct apk_string_array *args)

View File

@ -21,7 +21,7 @@ static void convert_index(struct conv_ctx *ctx, struct apk_istream *is)
adb_wo_alloca(&pkginfo, &schema_pkginfo, &ctx->dbi); adb_wo_alloca(&pkginfo, &schema_pkginfo, &ctx->dbi);
while (!APK_BLOB_IS_NULL(l = apk_istream_get_delim(is, token))) { while (apk_istream_get_delim(is, token, &l) == 0) {
if (l.len < 2) { if (l.len < 2) {
adb_wa_append_obj(&ctx->pkgs, &pkginfo); adb_wa_append_obj(&ctx->pkgs, &pkginfo);
continue; continue;

View File

@ -109,33 +109,32 @@ static adb_val_t mkndx_read_v2_pkginfo(struct adb *db, struct apk_istream *is, s
}; };
struct field *f, key; struct field *f, key;
struct adb_obj pkginfo, deps[3]; struct adb_obj pkginfo, deps[3];
apk_blob_t line, l, r, token = APK_BLOB_STR("\n"), bdep; apk_blob_t line, k, v, token = APK_BLOB_STR("\n"), bdep;
int e = 0, i = 0; int r, e = 0, i = 0;
adb_wo_alloca(&pkginfo, &schema_pkginfo, db); adb_wo_alloca(&pkginfo, &schema_pkginfo, db);
adb_wo_alloca(&deps[0], &schema_dependency_array, db); adb_wo_alloca(&deps[0], &schema_dependency_array, db);
adb_wo_alloca(&deps[1], &schema_dependency_array, db); adb_wo_alloca(&deps[1], &schema_dependency_array, db);
adb_wo_alloca(&deps[2], &schema_dependency_array, db); adb_wo_alloca(&deps[2], &schema_dependency_array, db);
while (!APK_BLOB_IS_NULL(line = apk_istream_get_delim(is, token))) { while ((r = apk_istream_get_delim(is, token, &line)) == 0) {
if (sctx) apk_sign_ctx_parse_pkginfo_line(sctx, line); if (sctx) apk_sign_ctx_parse_pkginfo_line(sctx, line);
if (line.len < 1 || line.ptr[0] == '#') continue; if (line.len < 1 || line.ptr[0] == '#') continue;
if (!apk_blob_split(line, APK_BLOB_STR(" = "), &l, &r)) continue; if (!apk_blob_split(line, APK_BLOB_STR(" = "), &k, &v)) continue;
key.str = l; key.str = k;
f = bsearch(&key, fields, ARRAY_SIZE(fields), sizeof(fields[0]), cmpfield); f = bsearch(&key, fields, ARRAY_SIZE(fields), sizeof(fields[0]), cmpfield);
if (!f || f->ndx == 0) continue; if (!f || f->ndx == 0) continue;
if (adb_ro_val(&pkginfo, f->ndx) != ADB_NULL) { if (adb_ro_val(&pkginfo, f->ndx) != ADB_NULL) {
/* Workaround abuild bug that emitted multiple license lines */ /* Workaround abuild bug that emitted multiple license lines */
if (f->ndx == ADBI_PI_LICENSE) continue; if (f->ndx == ADBI_PI_LICENSE) continue;
e = ADB_ERROR(APKE_ADB_PACKAGE_FORMAT); return ADB_ERROR(APKE_ADB_PACKAGE_FORMAT);
continue;
} }
switch (f->ndx) { switch (f->ndx) {
case ADBI_PI_ARCH: case ADBI_PI_ARCH:
if (!APK_BLOB_IS_NULL(rewrite_arch)) r = rewrite_arch; if (!APK_BLOB_IS_NULL(rewrite_arch)) v = rewrite_arch;
break; break;
case ADBI_PI_DEPENDS: case ADBI_PI_DEPENDS:
i = 0; i = 0;
@ -146,13 +145,15 @@ static adb_val_t mkndx_read_v2_pkginfo(struct adb *db, struct apk_istream *is, s
case ADBI_PI_REPLACES: case ADBI_PI_REPLACES:
i = 2; i = 2;
parse_deps: parse_deps:
while (!ADB_IS_ERROR(e) && apk_dep_split(&r, &bdep)) while (apk_dep_split(&v, &bdep)) {
e = adb_wa_append_fromstring(&deps[i], bdep); e = adb_wa_append_fromstring(&deps[i], bdep);
if (ADB_IS_ERROR(e)) return e;
}
continue; continue;
} }
adb_wo_pkginfo(&pkginfo, f->ndx, r); adb_wo_pkginfo(&pkginfo, f->ndx, v);
} }
if (ADB_IS_ERROR(e)) return e; if (r != -APKE_EOF) return ADB_ERROR(-r);
adb_wo_arr(&pkginfo, ADBI_PI_DEPENDS, &deps[0]); adb_wo_arr(&pkginfo, ADBI_PI_DEPENDS, &deps[0]);
adb_wo_arr(&pkginfo, ADBI_PI_PROVIDES, &deps[1]); adb_wo_arr(&pkginfo, ADBI_PI_PROVIDES, &deps[1]);

View File

@ -727,21 +727,26 @@ int apk_db_read_overlay(struct apk_database *db, struct apk_istream *is)
struct apk_package *pkg; struct apk_package *pkg;
struct apk_installed_package *ipkg; struct apk_installed_package *ipkg;
apk_blob_t token = APK_BLOB_STR("\n"), line, bdir, bfile; apk_blob_t token = APK_BLOB_STR("\n"), line, bdir, bfile;
int r = -1;
if (IS_ERR_OR_NULL(is)) return -1; if (IS_ERR_OR_NULL(is)) return PTR_ERR(is);
pkg = apk_pkg_new(); pkg = apk_pkg_new();
if (pkg == NULL) goto err; if (!pkg) goto no_mem;
ipkg = apk_pkg_install(db, pkg); ipkg = apk_pkg_install(db, pkg);
if (ipkg == NULL) goto err; if (ipkg == NULL) {
no_mem:
apk_istream_error(is, -ENOMEM);
goto err;
}
diri_node = hlist_tail_ptr(&ipkg->owned_dirs); diri_node = hlist_tail_ptr(&ipkg->owned_dirs);
while (!APK_BLOB_IS_NULL(line = apk_istream_get_delim(is, token))) { while (apk_istream_get_delim(is, token, &line) == 0) {
if (!apk_blob_rsplit(line, '/', &bdir, &bfile)) if (!apk_blob_rsplit(line, '/', &bdir, &bfile)) {
apk_istream_error(is, -APKE_V2PKG_FORMAT);
break; break;
}
if (bfile.len == 0) { if (bfile.len == 0) {
diri = apk_db_diri_new(db, pkg, bdir, &diri_node); diri = apk_db_diri_new(db, pkg, bdir, &diri_node);
@ -756,10 +761,8 @@ int apk_db_read_overlay(struct apk_database *db, struct apk_istream *is)
(void) apk_db_file_get(db, diri, bfile, &file_diri_node); (void) apk_db_file_get(db, diri, bfile, &file_diri_node);
} }
} }
r = 0;
err: err:
apk_istream_close(is); return apk_istream_close(is);
return r;
} }
int apk_db_index_read(struct apk_database *db, struct apk_istream *is, int repo) int apk_db_index_read(struct apk_database *db, struct apk_istream *is, int repo)
@ -781,7 +784,7 @@ int apk_db_index_read(struct apk_database *db, struct apk_istream *is, int repo)
if (IS_ERR_OR_NULL(is)) return PTR_ERR(is); if (IS_ERR_OR_NULL(is)) return PTR_ERR(is);
while (!APK_BLOB_IS_NULL(l = apk_istream_get_delim(is, token))) { while (apk_istream_get_delim(is, token, &l) == 0) {
lineno++; lineno++;
if (l.len < 2) { if (l.len < 2) {
@ -901,7 +904,6 @@ int apk_db_index_read(struct apk_database *db, struct apk_istream *is, int repo)
} }
if (APK_BLOB_IS_NULL(l)) goto bad_entry; if (APK_BLOB_IS_NULL(l)) goto bad_entry;
} }
return apk_istream_close(is); return apk_istream_close(is);
old_apk_tools: old_apk_tools:
/* Installed db should not have unsupported fields */ /* Installed db should not have unsupported fields */
@ -1135,7 +1137,7 @@ static int apk_db_triggers_read(struct apk_database *db, struct apk_istream *is)
if (IS_ERR(is)) return PTR_ERR(is); if (IS_ERR(is)) return PTR_ERR(is);
while (!APK_BLOB_IS_NULL(l = apk_istream_get_delim(is, APK_BLOB_STR("\n")))) { while (apk_istream_get_delim(is, APK_BLOB_STR("\n"), &l) == 0) {
apk_blob_pull_csum(&l, &csum); apk_blob_pull_csum(&l, &csum);
apk_blob_pull_char(&l, ' '); apk_blob_pull_char(&l, ' ');
@ -1150,9 +1152,7 @@ static int apk_db_triggers_read(struct apk_database *db, struct apk_istream *is)
list_add_tail(&ipkg->trigger_pkgs_list, list_add_tail(&ipkg->trigger_pkgs_list,
&db->installed.triggers); &db->installed.triggers);
} }
apk_istream_close(is); return apk_istream_close(is);
return 0;
} }
static int apk_db_read_state(struct apk_database *db, int flags) static int apk_db_read_state(struct apk_database *db, int flags)
@ -2428,7 +2428,7 @@ static int apk_db_install_archive_entry(void *_ctx,
if (ae->name[0] != '.') return 0; if (ae->name[0] != '.') return 0;
if (strcmp(ae->name, ".PKGINFO") == 0) { if (strcmp(ae->name, ".PKGINFO") == 0) {
apk_blob_t l, token = APK_BLOB_STR("\n"); apk_blob_t l, token = APK_BLOB_STR("\n");
while (!APK_BLOB_IS_NULL(l = apk_istream_get_delim(is, token))) while (apk_istream_get_delim(is, token, &l) == 0)
read_info_line(ctx, l); read_info_line(ctx, l);
return 0; return 0;
} }

View File

@ -160,21 +160,22 @@ void *apk_istream_get(struct apk_istream *is, size_t len)
return p; return p;
} }
apk_blob_t apk_istream_get_max(struct apk_istream *is, size_t max) int apk_istream_get_max(struct apk_istream *is, size_t max, apk_blob_t *data)
{ {
if (is->ptr == is->end) if (is->ptr == is->end)
__apk_istream_fill(is); __apk_istream_fill(is);
if (is->ptr != is->end) { if (is->ptr != is->end) {
apk_blob_t ret = APK_BLOB_PTR_LEN((char*)is->ptr, min((size_t)(is->end - is->ptr), max)); *data = APK_BLOB_PTR_LEN((char*)is->ptr, min((size_t)(is->end - is->ptr), max));
is->ptr += ret.len; is->ptr += data->len;
return ret; return 0;
} }
return (struct apk_blob) { .len = is->err < 0 ? is->err : 0 }; *data = APK_BLOB_NULL;
return is->err < 0 ? is->err : -APKE_EOF;
} }
apk_blob_t apk_istream_get_delim(struct apk_istream *is, apk_blob_t token) int apk_istream_get_delim(struct apk_istream *is, apk_blob_t token, apk_blob_t *data)
{ {
apk_blob_t ret = APK_BLOB_NULL, left = APK_BLOB_NULL; apk_blob_t ret = APK_BLOB_NULL, left = APK_BLOB_NULL;
@ -195,9 +196,11 @@ apk_blob_t apk_istream_get_delim(struct apk_istream *is, apk_blob_t token)
if (!APK_BLOB_IS_NULL(ret)) { if (!APK_BLOB_IS_NULL(ret)) {
is->ptr = (uint8_t*)left.ptr; is->ptr = (uint8_t*)left.ptr;
is->end = (uint8_t*)left.ptr + left.len; is->end = (uint8_t*)left.ptr + left.len;
return ret; *data = ret;
return 0;
} }
return (struct apk_blob) { .len = is->err < 0 ? is->err : 0 }; *data = APK_BLOB_NULL;
return is->err < 0 ? is->err : -APKE_EOF;
} }
static void blob_get_meta(struct apk_istream *is, struct apk_file_meta *meta) static void blob_get_meta(struct apk_istream *is, struct apk_file_meta *meta)
@ -559,11 +562,10 @@ ssize_t apk_stream_copy(struct apk_istream *is, struct apk_ostream *os, size_t s
while (done < size) { while (done < size) {
if (cb != NULL) cb(cb_ctx, done); if (cb != NULL) cb(cb_ctx, done);
d = apk_istream_get_max(is, size - done); r = apk_istream_get_max(is, size - done, &d);
if (APK_BLOB_IS_NULL(d)) { if (r < 0) {
if (d.len) return d.len; if (r == -APKE_EOF && d.len) return d.len;
if (size != APK_IO_ALL) return -APKE_EOF; return r;
break;
} }
if (dctx) apk_digest_ctx_update(dctx, d.ptr, d.len); if (dctx) apk_digest_ctx_update(dctx, d.ptr, d.len);
@ -609,7 +611,7 @@ ssize_t apk_istream_splice(struct apk_istream *is, int fd, size_t size,
togo = min(size - done, bufsz); togo = min(size - done, bufsz);
r = apk_istream_read(is, buf, togo); r = apk_istream_read(is, buf, togo);
if (r <= 0) { if (r <= 0) {
if (r) goto err; if (r && r != -APKE_EOF) goto err;
if (size != APK_IO_ALL && done != size) { if (size != APK_IO_ALL && done != size) {
r = -APKE_EOF; r = -APKE_EOF;
goto err; goto err;
@ -827,12 +829,12 @@ int apk_fileinfo_get(int atfd, const char *filename, unsigned int flags,
apk_blob_t blob; apk_blob_t blob;
if (apk_digest_ctx_init(&dctx, hash_alg) == 0) { if (apk_digest_ctx_init(&dctx, hash_alg) == 0) {
while (!APK_BLOB_IS_NULL(blob = apk_istream_get_all(is))) while (apk_istream_get_all(is, &blob) == 0)
apk_digest_ctx_update(&dctx, blob.ptr, blob.len); apk_digest_ctx_update(&dctx, blob.ptr, blob.len);
apk_digest_ctx_final(&dctx, &fi->digest); apk_digest_ctx_final(&dctx, &fi->digest);
apk_digest_ctx_free(&dctx); apk_digest_ctx_free(&dctx);
} }
apk_istream_close(is); return apk_istream_close(is);
} }
} }

View File

@ -67,17 +67,18 @@ static ssize_t gzi_read(struct apk_istream *is, void *ptr, size_t size)
APK_BLOB_PTR_LEN(gis->cbprev, APK_BLOB_PTR_LEN(gis->cbprev,
(void *)gis->zs.next_in - gis->cbprev)); (void *)gis->zs.next_in - gis->cbprev));
} }
blob = apk_istream_get_all(gis->zis); r = apk_istream_get_all(gis->zis, &blob);
gis->cbprev = blob.ptr; gis->cbprev = blob.ptr;
gis->zs.avail_in = blob.len; gis->zs.avail_in = blob.len;
gis->zs.next_in = (void *) gis->cbprev; gis->zs.next_in = (void *) gis->cbprev;
if (blob.len < 0) { if (r < 0) {
gis->is.err = blob.len; if (r == -APKE_EOF) {
goto ret; gis->is.err = 1;
} else if (gis->zs.avail_in == 0) { gis->cbarg = APK_BLOB_NULL;
gis->is.err = 1; gzi_boundary_change(gis);
gis->cbarg = APK_BLOB_NULL; } else {
gzi_boundary_change(gis); gis->is.err = r;
}
goto ret; goto ret;
} }
} }

View File

@ -643,7 +643,7 @@ int apk_sign_ctx_verify_tar(void *sctx, const struct apk_file_info *fi,
if (strcmp(fi->name, ".PKGINFO") == 0) { if (strcmp(fi->name, ".PKGINFO") == 0) {
apk_blob_t l, token = APK_BLOB_STR("\n"); apk_blob_t l, token = APK_BLOB_STR("\n");
while (!APK_BLOB_IS_NULL(l = apk_istream_get_delim(is, token))) while (apk_istream_get_delim(is, token, &l) == 0)
apk_sign_ctx_parse_pkginfo_line(ctx, l); apk_sign_ctx_parse_pkginfo_line(ctx, l);
} }
@ -900,7 +900,7 @@ static int read_info_entry(void *ctx, const struct apk_file_info *ae,
if (strcmp(ae->name, ".PKGINFO") == 0) { if (strcmp(ae->name, ".PKGINFO") == 0) {
/* APK 2.0 format */ /* APK 2.0 format */
apk_blob_t l, token = APK_BLOB_STR("\n"); apk_blob_t l, token = APK_BLOB_STR("\n");
while (!APK_BLOB_IS_NULL(l = apk_istream_get_delim(is, token))) while (apk_istream_get_delim(is, token, &l) == 0)
read_info_line(ctx, l); read_info_line(ctx, l);
} else if (strcmp(ae->name, ".INSTALL") == 0) { } else if (strcmp(ae->name, ".INSTALL") == 0) {
apk_warn(&ri->db->ctx->out, apk_warn(&ri->db->ctx->out,