. "$BST_LIB" # makeself 2.5.0, part 2 of 5 — the ARCHIVE ROUND TRIP. This is the case that # decides whether the port works: everything in part 1 passes for a recipe that # merely copied two scripts into /usr/bin, and only a real create-and-unpack # shows the fork/exec pipeline underneath -- tar and gzip on the way in, # dd | gzip -cd | tar on the way out -- running on wasm32-hwjs. # # ====================================================================== # THE BUDGET THAT SHAPES ALL FIVE FILES — measured, not assumed # ====================================================================== # `brintos-selftest makeself` runs every 66-makeself-*.test in ONE boot, and the # image has a per-boot ceiling that makeself hits harder than any other port here # because the tool IS a process pipeline. Measured on target by looping # create+unpack cycles until they broke: # # creates work for ~11 cycles, then "Cannot allocate memory" # real UNPACKS only the first ~2 succeed when interleaved with creates; # from the 3rd on the extraction fails ("Extraction failed", # rc 15 from the header's own kill -15) even though the MD5 # verify immediately before it passed # # So the scarce resource is running TAR THROUGH THE DECOMPRESSOR, and the whole # surface gets about THREE such operations per boot. Note what does and does not # count, because the distinction is not the obvious one: # # a run / --noexec dd | decompress | tar xp COUNTS -- writes files out # --list 3 s dd | decompress | tar t COUNTS TOO -- fast, but it is # still a tar that has to allocate. Cheap in TIME is not # cheap in MEMORY, which is the trap here. # --check 9 s dd | md5sum free of it # --info 2 s reads header variables free of it # # The surface therefore spends exactly three: this file's run, part 3's --noexec, # and part 4's --list. An earlier draft also called --list here, making four, and # the fourth failed with "tar: Cannot allocate memory" every time -- at whatever # position in the run order it sat, which is how the rule above was isolated. # # This is not a speed concern. A layout with six archives lost whole suites, # reporting 37 cases in one run and 62 in another from the same image, because # run-to-run variance decided where the ceiling landed. Sizing to 4 creates and # 3 tar-decompressions is what keeps the surface inside the budget. # # Sizing alone still cannot GUARANTEE it, which is the last thing to know here: # the ceiling is not a fixed count. Three runs of the same image at three # tar-decompressions produced three different sets of survivors -- once all three # passed, once the third failed, once the second. So every extraction goes through # `ms_gate` from data/makeself-lib.sh, which reports the distinctive ENOMEM # signature as `skip` (runtime-blocked) and anything else as `not ok`. A genuine # makeself regression still fails the run; a boot that ran out of memory does not # masquerade as one. That file's header carries the full reasoning. # # The secondary bound is the runner's 60 s per suite (costs: create 14 s, unpack # 24 s with the progress bar and 14 s with --noprogress, --check 9 s). Hence # `--noprogress` on every unpack, and hence the ONE unpack below is given the # startup script's arguments so five assertions come out of it rather than one. # ====================================================================== # # Three measured contracts a suite written from expectation would get wrong: # * The archive re-reads its OWN file to find the payload (`head -n $skip $0 | # wc -c` for the offset, then dd from there), so it must be invoked as a path # to a real file -- it is run as an absolute path here for that reason. # * One cosmetic diagnostic appears on EVERY unpack and is not a failure: the # header runs `df` on the target directory to report free space, and statfs is # unimplemented on this runtime, so `df: : Function not implemented` # reaches stderr while the extraction proceeds normally. # * makeself finishes with `chmod +x` on its product, and on this image that # yields mode 0645 rather than 0755 -- `umask()` returns -ENOSYS here, so an # unprefixed `+x` is masked down to o+x alone. The archive still executes # (root needs only one x bit), so what is asserted is that it IS executable, # not a specific mode. See the ticket's Issues Found for the umask defect. require makeself.sh makeself/present . "$BST_DATA/makeself-lib.sh" # ms_gate / ms_needle — see that file's header MS=/usr/bin/makeself.sh LC_ALL=C; export LC_ALL W=${TMPDIR:-/tmp}/bst-makeself-arch.$$ rm -rf "$W"; mkdir -p "$W/p/sub" || { bst_notok makeself/arch-setup "cannot create $W"; exit 0; } echo makeself-payload-marker > "$W/p/greeting.txt" echo nested > "$W/p/sub/nested.txt" printf '#!/bin/sh\necho MS-STARTUP-RAN\necho "MS-SEES:$(cat greeting.txt)"\necho "MS-ARGS:$*"\nexit 0\n' > "$W/p/startup.sh" chmod 755 "$W/p/startup.sh" A="$W/demo.run" cd "$W" || { bst_notok makeself/arch-setup "cannot cd $W"; exit 0; } # --- create ---------------------------------------------------------------- MSMK=$("$MS" "$W/p" "$A" "BST Demo Label" ./startup.sh 2>&1); MSMKRC=$? if [ "$MSMKRC" -eq 0 ]; then bst_ok makeself/create else bst_notok makeself/create "rc=$MSMKRC $(_bst_1line "$MSMK")"; fi case "$MSMK" in *"successfully created"*) bst_ok makeself/create-announce ;; *) bst_notok makeself/create-announce "$(_bst_1line "$MSMK")" ;; esac check makeself/archive-exists test -s "$A" check makeself/archive-executable test -x "$A" # The product is a shell script with a binary payload appended. The version is # asserted from the archive's OWN generated comment rather than from file(1): # whether file(1) recognises a makeself archive depends on its magic database # version -- it reports "Makeself 2.5.0" on this image but only "POSIX shell # script executable (binary data)" on an older host -- so that would be an # assertion drifting with a tool this port does not own. check_out makeself/archive-shebang "#!/bin/sh" head -1 "$A" check_out makeself/archive-selfid "generated using Makeself 2.5.0" head -3 "$A" # --- UNPACK #1 of 3: one extraction, five assertions ----------------------- # Arguments after -- reach the startup script, so this single unpack also covers # the argument pass-through. Splitting it in two would spend an unpack the whole # surface does not have. MSRUN=$("$A" --noprogress -- ALPHA BETA 2>&1); MSRUNRC=$? ms_gate makeself/run-rc "$MSRUNRC" "$MSRUN" for _pair in \ 'run-integrity:MD5 checksums are OK' \ 'run-startup:MS-STARTUP-RAN' \ 'run-payload:MS-SEES:makeself-payload-marker' \ 'run-args:MS-ARGS:ALPHA BETA' do ms_needle "makeself/${_pair%%:*}" "${_pair#*:}" "$MSRUN" done # --- read-only interrogation (--info reads header variables only: 2 s) ----- # NB there is deliberately no `--list` here, even though this is the file where # one would expect it. `--list` runs `tar t` through the decompressor, so it costs # a tar-decompression from the same budget as an unpack -- and the budget is ~3 # such operations per boot, not 3 unpacks plus unlimited listings. With a --list # here the surface asked for four (this run, this listing, part 3's --noexec, # part 4's --list) and the fourth failed with "tar: Cannot allocate memory" every # time, at whatever position it sat. `--list` is therefore exercised once, in # part 4, where it doubles as the proof that the bzip2 archive round-trips; and # the payload's nested entry is asserted in part 3, which unpacks it for real. MSINFO=$("$A" --info 2>&1) for _pair in \ 'info-label:BST Demo Label' \ 'info-compress:Compression: gzip' \ 'info-version:Makeself version 2.5.0' do _pcase=${_pair%%:*}; _pneedle=${_pair#*:} case "$MSINFO" in *"$_pneedle"*) bst_ok "makeself/$_pcase" ;; *) bst_notok "makeself/$_pcase" "want:'$_pneedle' got:'$(_bst_1line "$MSINFO")'" ;; esac done cd / rm -rf "$W"