[meta-swupdate][PATCH] swupdate: fail the build when cpio drops files from the .swu

15 views
Skip to first unread message

Johannes Schrimpf

unread,
Jun 9, 2026, 12:48:35 PMJun 9
to swup...@googlegroups.com
From: Johannes Schrimpf <johannes...@blueye.no>
Date: Tue, 9 Jun 2026 14:36:50 +0200

swupdate_create_cpio ran cpio via os.system() through a shell pipe and
discarded the exit status. When an artifact exceeds the cpio crc format's
32-bit (4 GiB) file-size field, cpio prints a non-fatal warning, skips that
one file, and still exits 0 -- so do_swuimage "succeeded" and produced a
truncated .swu silently missing the main partition image.

Pipe the file list to cpio over stdin instead of a shell pipe so its exit
status is no longer masked, and compare the files cpio reports archiving (its
-v output on stderr) against the requested list: if any are missing, bb.fatal.
The content check is the part that matters, since cpio exits 0 on the
oversized-file skip. The archive is streamed straight to the .swu file and
only cpio's stderr is captured, so no extra read or in-memory buffering.

Signed-off-by: Johannes Schrimpf <johannes...@blueye.no>
---
classes-recipe/swupdate-common.bbclass | 30 ++++++++++++++++++++++++--
1 file changed, 28 insertions(+), 2 deletions(-)

diff --git a/classes-recipe/swupdate-common.bbclass
b/classes-recipe/swupdate-common.bbclass
index 0fbcd20..8cea668 100644
--- a/classes-recipe/swupdate-common.bbclass
+++ b/classes-recipe/swupdate-common.bbclass
@@ -317,11 +317,37 @@ def swupdate_add_artifacts(d, list_for_cpio):


def swupdate_create_cpio(d, swudeploydir, list_for_cpio):
+ import subprocess
+
workdir = d.getVar('WORKDIR')
os.chdir(workdir)
updateimage = d.getVar('IMAGE_NAME') + '.swu'
- line = 'for i in ' + ' '.join(list_for_cpio) + '; do echo $i;done
| cpio -ov -H crc --reproducible > ' + os.path.join(swudeploydir,
updateimage)
- os.system(line)
+ swu_path = os.path.join(swudeploydir, updateimage)
+
+ # Feed the file list to cpio over stdin instead of a shell pipe so its exit
+ # status is not masked. The archive is streamed straight to the .swu file;
+ # only cpio's (small) stderr is captured. cpio -v prints each archived file
+ # to stderr, while a file too large for the crc format's 4GB size field is
+ # skipped with just a warning and cpio still exits 0 -- which used to
+ # silently truncate the .swu. So check what cpio reported archiving against
+ # what we asked for.
+ filelist = ''.join(i + '\n' for i in list_for_cpio)
+ with open(swu_path, 'wb') as out:
+ proc = subprocess.run(['cpio', '-ov', '-H', 'crc', '--reproducible'],
+ input=filelist.encode(), stdout=out,
+ stderr=subprocess.PIPE)
+ stderr = proc.stderr.decode(errors='replace')
+ bb.note(stderr)
+ if proc.returncode != 0:
+ bb.fatal("swupdate: cpio failed to create %s (exit %d)" %
(updateimage, proc.returncode))
+
+ archived = set(stderr.splitlines())
+ missing = [i for i in list_for_cpio if i not in archived]
+ if missing:
+ bb.fatal("swupdate: cpio dropped %s from %s (a file larger than the "
+ "cpio crc 4GB limit is the usual cause)"
+ % (' '.join(missing), updateimage))
+
os.chdir(swudeploydir)
updateimage_link = d.getVar('IMAGE_LINK_NAME')
if updateimage_link:
--
2.43.0
Reply all
Reply to author
Forward
0 new messages