[openwrt/openwrt] apk-tools: implement compression of on-device scripts.tar
LEDE Commits
lede-commits at lists.infradead.org
Tue Nov 18 08:25:10 PST 2025
robimarko pushed a commit to openwrt/openwrt.git, branch main:
https://git.openwrt.org/5d85657f6dbbbcb1c43bc34bf5b85693f58dd781
commit 5d85657f6dbbbcb1c43bc34bf5b85693f58dd781
Author: Eric Fahlgren <ericfahlgren at gmail.com>
AuthorDate: Sat Nov 15 08:32:00 2025 -0800
apk-tools: implement compression of on-device scripts.tar
Default behavior for apk was to create an uncompressed scripts.tar
file. Due to the structure of tar files, with fixed block
size and null padding, this file becomes very large on OpenWrt
installations where there are typically two scripts per package.
This could cause the raw tar file to easily grow to over 500KB,
whereas the compressed file is generally around 20-30KB.
When stored in the /rom partition of a squashfs device, the file
is compressed and this is not an issue. But, as soon as you add
or delete a package, the scripts.tar file is fully expanded into
the /overlay partition and can cause issues on small-flash devices.
This issue was addressed in an upstream commit by detecting
whether the scripts.tar file is compressed (its name must be
exactly 'scripts.tar.gz'), and then retaining that compression by
reading/writing the file using a compressed stream.
This commit applies a cherrypicked patch for the upstream commit, and
compresses the scripts.tar during construction of the device rootfs.
Fixes: https://github.com/openwrt/openwrt/issues/17108
Link: https://gitlab.alpinelinux.org/alpine/apk-tools/-/commit/012cdcfdf981453b572a70c9568e8df6d0fe0ca1
Signed-off-by: Eric Fahlgren <ericfahlgren at gmail.com>
Link: https://github.com/openwrt/openwrt/pull/20795
Signed-off-by: Robert Marko <robimarko at gmail.com>
---
include/rootfs.mk | 4 +-
package/system/apk/Makefile | 2 +-
.../system/apk/patches/999-small-scripts-tar.patch | 55 ++++++++++++++++++++++
3 files changed, 58 insertions(+), 3 deletions(-)
diff --git a/include/rootfs.mk b/include/rootfs.mk
index 26f249d818..ebf4e40683 100644
--- a/include/rootfs.mk
+++ b/include/rootfs.mk
@@ -78,7 +78,7 @@ define prepare_rootfs
cd $(1); \
if [ -n "$(CONFIG_USE_APK)" ]; then \
IPKG_POSTINST_PATH=./lib/apk/db/*.post-install; \
- $(STAGING_DIR_HOST)/bin/tar -C ./lib/apk/db/ -xf ./lib/apk/db/scripts.tar --wildcards "*.post-install"; \
+ $(STAGING_DIR_HOST)/bin/tar -C ./lib/apk/db/ -xzf ./lib/apk/db/scripts.tar.gz --wildcards "*.post-install"; \
else \
IPKG_POSTINST_PATH=./usr/lib/opkg/info/*.postinst; \
fi; \
@@ -89,7 +89,7 @@ define prepare_rootfs
echo "postinst script $$script has failed with exit code $$ret" >&2; \
exit 1; \
fi; \
- [ -n "$(CONFIG_USE_APK)" ] && $(STAGING_DIR_HOST)/bin/tar --delete -f ./lib/apk/db/scripts.tar $$(basename $$script); \
+ [ -n "$(CONFIG_USE_APK)" ] && $(STAGING_DIR_HOST)/bin/tar --delete -zf ./lib/apk/db/scripts.tar.gz $$(basename $$script); \
done; \
if [ -z "$(CONFIG_USE_APK)" ]; then \
$(if $(IB),,awk -i inplace \
diff --git a/package/system/apk/Makefile b/package/system/apk/Makefile
index 53a9a6c006..3e4f0c1466 100644
--- a/package/system/apk/Makefile
+++ b/package/system/apk/Makefile
@@ -1,7 +1,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=apk
-PKG_RELEASE:=1
+PKG_RELEASE:=2
PKG_SOURCE_URL=https://gitlab.alpinelinux.org/alpine/apk-tools.git
PKG_SOURCE_PROTO:=git
diff --git a/package/system/apk/patches/999-small-scripts-tar.patch b/package/system/apk/patches/999-small-scripts-tar.patch
new file mode 100644
index 0000000000..ff93e821eb
--- /dev/null
+++ b/package/system/apk/patches/999-small-scripts-tar.patch
@@ -0,0 +1,55 @@
+diff --git a/doc/apk.8.scd b/doc/apk.8.scd
+index bd15fe75d7a4..cbac8c6c8b7b 100644
+--- a/doc/apk.8.scd
++++ b/doc/apk.8.scd
+@@ -461,7 +461,8 @@ timeout 120
+ */lib/apk/db/installed*
+ Database of installed packages and their contents.
+
+-*/lib/apk/db/scripts.tar*
++*/lib/apk/db/scripts.tar*++
++*/lib/apk/db/scripts.tar.gz*
+ Collection of all package scripts from currently installed packages.
+
+ */lib/apk/db/triggers*
+diff --git a/src/apk_database.h b/src/apk_database.h
+index 9f8670ac8ebb..10f1414c9e06 100644
+--- a/src/apk_database.h
++++ b/src/apk_database.h
+@@ -202,6 +202,7 @@ struct apk_database {
+ unsigned int compat_depversions : 1;
+ unsigned int sorted_names : 1;
+ unsigned int sorted_installed_packages : 1;
++ unsigned int scripts_tar : 1;
+
+ struct apk_dependency_array *world;
+ struct apk_id_cache *id_cache;
+diff --git a/src/database.c b/src/database.c
+index cbe58ebbf885..cb1b709140af 100644
+--- a/src/database.c
++++ b/src/database.c
+@@ -1255,8 +1255,11 @@ static int apk_db_read_layer(struct apk_database *db, unsigned layer)
+ }
+
+ if (!(flags & APK_OPENF_NO_SCRIPTS)) {
+- r = apk_tar_parse(apk_istream_from_file(fd, "scripts.tar"),
+- apk_read_script_archive_entry, db, db->id_cache);
++ struct apk_istream *is = apk_istream_from_file(fd, "scripts.tar");
++ if (!IS_ERR(is) || PTR_ERR(is) != -ENOENT) db->scripts_tar = 1;
++ else is = apk_istream_gunzip(apk_istream_from_file(fd, "scripts.tar.gz"));
++
++ r = apk_tar_parse(is, apk_read_script_archive_entry, db, db->id_cache);
+ if (!ret && r != -ENOENT) ret = r;
+ }
+
+@@ -2128,8 +2131,9 @@ static int apk_db_write_layers(struct apk_database *db)
+ continue;
+ }
+ ld->installed = apk_ostream_to_file(ld->fd, "installed", 0644);
+- ld->scripts = apk_ostream_to_file(ld->fd, "scripts.tar", 0644);
+ ld->triggers = apk_ostream_to_file(ld->fd, "triggers", 0644);
++ if (db->scripts_tar) ld->scripts = apk_ostream_to_file(ld->fd, "scripts.tar", 0644);
++ else ld->scripts = apk_ostream_gzip(apk_ostream_to_file(ld->fd, "scripts.tar.gz", 0644));
+
+ if (i == APK_DB_LAYER_ROOT)
+ os = apk_ostream_to_file(db->root_fd, apk_world_file, 0644);
More information about the lede-commits
mailing list