Skip to content

K2GO-90 fix(rootfs): move the manifest onto the product's name, reading both - #532

Merged
luisguzman-adfa merged 3 commits into
mainfrom
fix/K2GO-90-accept-both-manifest-names
Sep 3, 2026
Merged

K2GO-90 fix(rootfs): move the manifest onto the product's name, reading both#532
luisguzman-adfa merged 3 commits into
mainfrom
fix/K2GO-90-accept-both-manifest-names

Conversation

@luisguzman-adfa

Copy link
Copy Markdown
Collaborator

The app reads the rootfs manifest under both the iiab- and k2go- names, and both writers now
produce the new one. The staged OTA APK follows.

Why both halves land together

The reader has to be tolerant before anything writes the new name, or archives built either side of
the switch stop being restorable. That much is ordering. The reason to write it now rather than
later is the population: with developers and a handful of users, the set of archives carrying the
old name closes today. Ship the writer later and it grows with every backup taken in between —
which is what would make the tolerance impossible to ever drop.

reads accepts
RootfsIdentity kind = iiab-rootfs or k2go-rootfs
RootfsManifest member iiab/.iiab-rootfs.json or iiab/.k2go-rootfs.json
RootfsIntegrity either .integrity.json sibling
writes now emits
BackupEngine .k2go-rootfs.json, kind: k2go-rootfs, first tar member
tools/rootfs-builder the same, plus the integrity sibling

The integrity member is matched for a sharper reason than symmetry: it is excluded from the tree
hash it declares, so failing to recognise it would fold it into its own digest and read every
archive as CORRUPT.

Verified on device, both names in one session

An image built by the old writer — the one in the bucket today — installs and carries
.iiab-rootfs.json. A backup taken from it carries .k2go-rootfs.json as the tar's first member.
Restoring that backup completes, and the restored tree carries the new manifest. If the integrity
member had gone unrecognised, validation would have reported CORRUPT before extraction began.

Incidentally confirming a change from earlier in this ticket: at 62% — still the verify pass — the
damage marker was not yet planted. It goes down at the first byte written, so an ungraceful exit
during verification no longer declares a false DAMAGED.

The staged OTA APK

Its fallback name — used only when the download URL does not end in .apk — becomes
k2go_update.apk. It had been spelled out twice, once when staging the file and once as the default
when reading the name back out of SharedPreferences: drifting apart would stage the file under one
name and have the verifier look for it under another, on the one path nobody exercises. One constant
now, read by both sides.

Tests

Four cases on the pure rule, including the actual risk of this change: accepting a second kind
must not become a way around the ABI check. A k2go-rootfs built for 32-bit is still WRONG_ARCH
on a 64-bit device, and anything that is neither kind is still NOT_A_ROOTFS.

Not in scope

The seven iiab_* SharedPreferences names, the ADB keystore alias and the iiab_sync handshake
token stay as they are. Those are not branding: renaming a preferences file abandons its contents,
the alias renames a key that is already paired, and the handshake token is verified by the phone on
the other end.

… broken window

The identity manifest, its integrity sibling and the kind they declare are matched under both the
iiab- and k2go- names. The builder still writes the old one: this only removes the reason it cannot
stop.

The reader has to ship before the writer changes. An app that only knew the new name would reject
every archive built before the switch — including the backups users are told to make before
migrating, which is the one moment when a rejected restore is unrecoverable.

The integrity member is matched the same way for a sharper reason: it is excluded from the tree hash
it declares, so failing to recognise it would fold it into its own digest and read every archive as
CORRUPT.
The fallback name for the staged OTA APK was iiab_update.apk. It is only used when the download URL
does not end in .apk, so it rarely surfaces — but it was spelled out twice, once when staging the
file and once as the default when reading the name back out of SharedPreferences. Two literals for
one fact: drifting apart would stage the file under one name and have the verifier look for it under
another, on the one path nobody exercises.

It is k2go_update.apk now, in a single constant both sides read.
Both writers move together: BackupEngine, which stamps the manifest into user backups, and
build-iiab-rootfs.sh, which stamps it into the images. They have to agree, because the validator
compares an archive against what a rootfs image looks like.

Done now rather than later on purpose. The installed base is developers and a handful of users, so
the set of archives carrying the old name closes today instead of growing with every backup written
from here on — which is what would have made the tolerance for it impossible to ever drop.

Verified on device: an image built with the old writer installs, a backup taken from it carries the
new name as the tar's first member, and restoring that backup completes. The integrity member is
recognised under the new name too, which is the failure that would otherwise have read every archive
as CORRUPT.
@luisguzman-adfa
luisguzman-adfa merged commit 79f0699 into main Sep 3, 2026
2 of 3 checks passed
@luisguzman-adfa
luisguzman-adfa deleted the fix/K2GO-90-accept-both-manifest-names branch September 3, 2026 09:52
@luisguzman-adfa
luisguzman-adfa restored the fix/K2GO-90-accept-both-manifest-names branch September 3, 2026 09:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant