Programs
The browser
XerisOS does not ship Chrome, and shipping a unit with Chrome already on the disk is distribution no matter where the bytes came from. So the browser is not part of the product: the owner brings it, once, from a USB stick they make on their own machine.
That decision is a licensing one, not a technical one. Chromium is BSD-licensed and redistributable; Google Chrome is not. The branded build adds proprietary codecs, Google APIs, and the Widevine CDM, and its terms license the AVC patent portfolio for the personal and non-commercial use of a consumer — which is not obviously what a machine sold with it preinstalled is doing. If you ever want Chrome in the box, that is an OEM agreement with Google, and it is worth twenty minutes of a lawyer's time before it is worth any of mine.
What used to happen#
release.mk's payload-full copied all 487 MB of build/data_run into the public update bucket — Chromium, glibc, GTK, Mesa, and WidevineCdm/. That is fixed: FULL_OWN is now an allowlist of files we actually own, and every skipped file is named at release time so the omission is visible rather than assumed.
Still outstanding: if a full release was ever pushed, those objects are still live in R2. Uploaded objects persist independently of manifest.txt, so deletion has to be explicit and per-key. Delete WidevineCdm/ first.
Making the stick (on your PC)#
python tools/chrome_fetch.py --check # what version is Google serving?
python tools/chrome_fetch.py --out E:\ # write a stick
python tools/chrome_fetch.py --out build/data_run # or the dev tree
It fetches https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb — Google's own server, over HTTPS, from your machine — unpacks the ar/tar container in pure Python (no dpkg, so it works on Windows), lays out opt/google/chrome/* with chrome renamed to CHROME.ELF, and writes two receipts: MANIFEST.JSN for humans and MANIFEST.TXT for the OS.
WidevineCdm/ is skipped deliberately. DRM video — Netflix, Spotify, anything using Encrypted Media Extensions — will not play. Widevine is licensed per device and cannot be redistributed by copying a .so.
On version pinning, honestly#
Google serves one URL for the stable channel and it always points at whatever is current; there is no version-addressed URL to pin. So the script uses trust-on-first-use: tools/chrome_pin.json records the version and the SHA-256 of the .deb, and later runs report when Google has moved. That is a change-detector, not an authenticity proof — the authenticity comes from HTTPS to dl.google.com.
An earlier version of this file carried a PINNED_SHA256 constant that had never been computed from a real download. A security check with an invented expected value is worse than no check: it fails on first contact and teaches whoever hits it to pass --accept-new-hash without thinking. It is gone.
The syscall layer has been exercised against Chrome 152.0.7977.75 — the build in build/data_run today. linux_compat.c carries at least one build-specific address (the StyleFontData GC workaround), so a different version is worth knowing about; the script prints the difference rather than refusing.
Installing it (on the machine)#
chrome where # is there a payload on the stick, and where
chrome install # copy it to the disk, then hash every file that landed
chrome verify # re-check what is installed against the stick
MANIFEST.TXT is deliberately not JSON — # comments, then one line of <64 hex chars> <decimal bytes> <relative path>. A reader for that cannot be subtly wrong, and a JSON parser written for one file on a Sunday can.
Every file is hashed after it lands on the volume, never before it is copied. Verifying the source and trusting the copy would miss the failure that actually happens: a bad write, a full disk, a stick pulled mid-copy. chrome verify reports missing / wrong size / wrong content separately and names the first file that failed, because "install failed" is not an actionable sentence.
A filesystem bug this work uncovered#
Copying Chrome's payload means creating ~770 files with names like libEGL.so.1 — long names, which FAT stores as a chain of entries that must sit in consecutive directory slots. When such a chain did not fit in the tail of a cluster, the old dir_insert moved to a new cluster and left a 0x00 slot behind. 0x00 does not mean "free"; it means end of directory, stop scanning, and every FAT reader obeys it — this one, Windows, Linux. Everything after the hole went invisible while still sitting on disk.
Measured against the real 772-name file list from build/data_run:
| created | readable afterwards | fsck.vfat |
|
|---|---|---|---|
| before | 756 / 772 | 14 | 32 duplicate entries, auto-renamed |
| after | 772 / 772 | 772 | clean |
The duplicate short names were the same bug's second symptom: lfn_alias probes for collisions with dir_find, which stopped at the hole, so two long names were handed one CHROME~1.PAK.
This was never Chrome-specific. Any directory the OS wrote could be truncated — /ARI, autosave, screenshots. A volume written before the fix is still carrying hidden files, and chkdsk on another machine does not find them, because Windows stops at the 0x00 too.
fsrepair # whole volume
fsrepair /ARI # one directory
Nothing was destroyed, so this is a real repair rather than a salvage: the hole becomes 0xE5 ("free, keep scanning") and the entries come back. It writes nothing when nothing is wrong, and it is idempotent. Duplicate 8.3 names are reported and not altered — fixing one means renaming an entry, and the safe move is to re-copy the affected file now that the directory reads again.
Two related fixes went in alongside it: getdents64 was handing Chrome the mangled LIBEGL~1.1 instead of the real name (fine for opening a known path, wrong for anything that scans a directory — fontconfig does), and a lowercase 8.3 name like icudtl.dat was stored shouting; it now uses the NT case flags in byte 12, the way Windows does.