From 6ded697826ad97609d56b286c1c4e43b68f400d8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi>
Date: Mon, 10 Apr 2023 20:17:25 +0300
Subject: [PATCH] io: make apk_blob_from_* return error

---
 src/apk_io.h     |  4 ++--
 src/app_mkpkg.c  | 11 ++++++-----
 src/database.c   | 18 +++++++++---------
 src/extract_v2.c |  4 ++--
 src/io.c         | 47 ++++++++++++++++++++++++++++-------------------
 src/package.c    |  4 +++-
 6 files changed, 50 insertions(+), 38 deletions(-)

diff --git a/src/apk_io.h b/src/apk_io.h
index e7ca1f0f..49b27596 100644
--- a/src/apk_io.h
+++ b/src/apk_io.h
@@ -177,8 +177,8 @@ static inline int apk_ostream_close(struct apk_ostream *os)
 	return os->ops->close(os) ?: rc;
 }
 
-apk_blob_t apk_blob_from_istream(struct apk_istream *istream, size_t size);
-apk_blob_t apk_blob_from_file(int atfd, const char *file);
+int apk_blob_from_istream(struct apk_istream *is, size_t size, apk_blob_t *b);
+int apk_blob_from_file(int atfd, const char *file, apk_blob_t *b);
 
 #define APK_BTF_ADD_EOL		0x00000001
 int apk_blob_to_file(int atfd, const char *file, apk_blob_t b, unsigned int flags);
diff --git a/src/app_mkpkg.c b/src/app_mkpkg.c
index f1a121d8..f1cffc5f 100644
--- a/src/app_mkpkg.c
+++ b/src/app_mkpkg.c
@@ -88,7 +88,7 @@ static int option_parse_applet(void *ctx, struct apk_ctx *ac, int optch, const c
 	struct apk_out *out = &ac->out;
 	struct mkpkg_ctx *ictx = ctx;
 	apk_blob_t l, r;
-	int i;
+	int i, ret;
 
 	switch (optch) {
 	case OPT_MKPKG_info:
@@ -106,10 +106,11 @@ static int option_parse_applet(void *ctx, struct apk_ctx *ac, int optch, const c
 			apk_err(out, "invalid script type: " BLOB_FMT, BLOB_PRINTF(l));
 			return -EINVAL;
 		}
-		ictx->script[i] = apk_blob_from_file(AT_FDCWD, r.ptr);
-		if (APK_BLOB_IS_NULL(ictx->script[i])) {
-			apk_err(out, "failed to load script: " BLOB_FMT, BLOB_PRINTF(r));
-			return -ENOENT;
+		ret = apk_blob_from_file(AT_FDCWD, r.ptr, &ictx->script[i]);
+		if (ret) {
+			apk_err(out, "failed to load script: " BLOB_FMT ": %s",
+				BLOB_PRINTF(r), apk_error_str(ret));
+			return ret;
 		}
 		ictx->has_scripts = 1;
 		break;
diff --git a/src/database.c b/src/database.c
index 178aa0e2..d7b2aa9e 100644
--- a/src/database.c
+++ b/src/database.c
@@ -1208,11 +1208,11 @@ static int apk_db_read_layer(struct apk_database *db, unsigned layer)
 
 	if (!(flags & APK_OPENF_NO_WORLD)) {
 		if (layer == APK_DB_LAYER_ROOT)
-			world = apk_blob_from_file(db->root_fd, apk_world_file);
+			ret = apk_blob_from_file(db->root_fd, apk_world_file, &world);
 		else
-			world = apk_blob_from_file(fd, "world");
+			ret = apk_blob_from_file(fd, "world", &world);
 
-		if (!APK_BLOB_IS_NULL(world)) {
+		if (!ret) {
 			blob = apk_blob_trim(world);
 			apk_blob_pull_deps(&blob, db, &db->world);
 			free(world.ptr);
@@ -1367,8 +1367,7 @@ static int add_protected_paths_from_file(void *ctx, int dirfd, const char *file)
 	if (!file_ends_with_dot_list(file))
 		return 0;
 
-	blob = apk_blob_from_file(dirfd, file);
-	if (APK_BLOB_IS_NULL(blob))
+	if (apk_blob_from_file(dirfd, file, &blob))
 		return 0;
 
 	apk_blob_for_each_segment(blob, "\n", add_protected_path, db);
@@ -1401,8 +1400,10 @@ static int add_repos_from_file(void *ctx, int dirfd, const char *file)
 			return 0;
 	}
 
-	blob = apk_blob_from_file(dirfd, file);
-	if (APK_BLOB_IS_NULL(blob)) {
+	if (!file_ends_with_dot_list(file))
+		return 0;
+
+	if (apk_blob_from_file(dirfd, file, &blob)) {
 		if (dirfd != AT_FDCWD) return 0;
 		apk_err(out, "failed to read repositories: %s", file);
 		apk_msg(out, "NOTE: --repositories-file is relative to the startup directory since apk 2.12.0_rc2");
@@ -1705,8 +1706,7 @@ int apk_db_open(struct apk_database *db, struct apk_ctx *ac)
 		db->write_arch = 1;
 	} else {
 		apk_blob_t arch;
-		arch = apk_blob_from_file(db->root_fd, apk_arch_file);
-		if (!APK_BLOB_IS_NULL(arch)) {
+		if (!apk_blob_from_file(db->root_fd, apk_arch_file, &arch)) {
 			db->arch = apk_atomize_dup(&db->atoms, apk_blob_trim(arch));
 			free(arch.ptr);
 		} else {
diff --git a/src/extract_v2.c b/src/extract_v2.c
index f75c5531..cc236350 100644
--- a/src/extract_v2.c
+++ b/src/extract_v2.c
@@ -166,7 +166,7 @@ static int apk_sign_ctx_process_file(struct apk_sign_ctx *ctx, const struct apk_
 	if (pkey) {
 		ctx->md = md;
 		ctx->signature.pkey = pkey->key;
-		ctx->signature.data = apk_blob_from_istream(is, fi->size);
+		apk_blob_from_istream(is, fi->size, &ctx->signature.data);
 	}
 	return 0;
 }
@@ -322,7 +322,7 @@ static int apk_extract_v2_entry(void *pctx, const struct apk_file_info *fi, stru
 			if (!ectx->ops->v2index) return -APKE_FORMAT_NOT_SUPPORTED;
 			if (strcmp(fi->name, "DESCRIPTION") == 0) {
 				free(ectx->desc.ptr);
-				ectx->desc = apk_blob_from_istream(is, fi->size);
+				apk_blob_from_istream(is, fi->size, &ectx->desc);
 			} else if (strcmp(fi->name, "APKINDEX") == 0) {
 				return ectx->ops->v2index(ectx, &ectx->desc, is);
 			}
diff --git a/src/io.c b/src/io.c
index 2d3566ed..f7b94e66 100644
--- a/src/io.c
+++ b/src/io.c
@@ -653,50 +653,59 @@ ssize_t apk_stream_copy(struct apk_istream *is, struct apk_ostream *os, size_t s
 	return done;
 }
 
-apk_blob_t apk_blob_from_istream(struct apk_istream *is, size_t size)
+int apk_blob_from_istream(struct apk_istream *is, size_t size, apk_blob_t *b)
 {
 	void *ptr;
+	int r;
+
+	*b = APK_BLOB_NULL;
 
 	ptr = malloc(size);
-	if (ptr == NULL)
-		return APK_BLOB_NULL;
+	if (!ptr) return -ENOMEM;
 
-	if (apk_istream_read(is, ptr, size) < 0) {
+	r = apk_istream_read(is, ptr, size);
+	if (r < 0) {
 		free(ptr);
-		return APK_BLOB_NULL;
+		return r;
 	}
-	return APK_BLOB_PTR_LEN(ptr, size);
+	*b = APK_BLOB_PTR_LEN(ptr, size);
+	return r;
 }
 
-apk_blob_t apk_blob_from_file(int atfd, const char *file)
+int apk_blob_from_file(int atfd, const char *file, apk_blob_t *b)
 {
-	int fd;
 	struct stat st;
 	char *buf;
+	ssize_t n;
+	int fd;
 
-	if (atfd_error(atfd)) return APK_BLOB_NULL;
+	*b = APK_BLOB_NULL;
 
-	fd = openat(atfd, file, O_RDONLY | O_CLOEXEC);
-	if (fd < 0)
-		return APK_BLOB_NULL;
+	if (atfd_error(atfd)) return atfd;
 
-	if (fstat(fd, &st) < 0)
-		goto err_fd;
+	fd = openat(atfd, file, O_RDONLY | O_CLOEXEC);
+	if (fd < 0) goto err;
+	if (fstat(fd, &st) < 0) goto err_fd;
 
 	buf = malloc(st.st_size);
-	if (buf == NULL)
-		goto err_fd;
+	if (!buf) goto err_fd;
 
-	if (read(fd, buf, st.st_size) != st.st_size)
+	n = read(fd, buf, st.st_size);
+	if (n != st.st_size) {
+		if (n >= 0) errno = EIO;
 		goto err_read;
+	}
 
 	close(fd);
-	return APK_BLOB_PTR_LEN(buf, st.st_size);
+	*b = APK_BLOB_PTR_LEN(buf, st.st_size);
+	return 0;
+
 err_read:
 	free(buf);
 err_fd:
 	close(fd);
-	return APK_BLOB_NULL;
+err:
+	return -errno;
 }
 
 int apk_blob_to_file(int atfd, const char *file, apk_blob_t b, unsigned int flags)
diff --git a/src/package.c b/src/package.c
index e1a86833..049f6ef7 100644
--- a/src/package.c
+++ b/src/package.c
@@ -767,7 +767,9 @@ int apk_ipkg_add_script(struct apk_installed_package *ipkg,
 			struct apk_istream *is,
 			unsigned int type, unsigned int size)
 {
-	return apk_ipkg_assign_script(ipkg, type, apk_blob_from_istream(is, size));
+	apk_blob_t b;
+	apk_blob_from_istream(is, size, &b);
+	return apk_ipkg_assign_script(ipkg, type, b);
 }
 
 #ifdef __linux__
-- 
GitLab