diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5a46436c0..baa2496b4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8031,6 +8031,64 @@ jobs: - name: "CRTL->RMS veneer gate — qemu-system-alpha boots the veneer-wired crtl_rms image on the real /dev/vms executive; its decc$fopen writes PORTTEST.DAT via sys$create over the ODS-2 ACP, then an INDEPENDENT reader (DCL DIRECTORY/FULL, a different accessor than the writer's CRTL/RMS handle) asserts PORTTEST.DAT;1 with a genuine ODS-2 File ID a ramfs cannot produce; runs a can-fail selftest (incl. the ramfs-rejection case) before the boot" run: tools/cross-alpha/run-module-gp-activation-alpha.sh crtl-rms-veneer-gate + # ----------------------------------------------------------------------- + # alpha-crtl-rms-fileop (vms-3320, parent vms-b4f, blocks vms-fd1): the + # UN-FAKEABLE CRTL->RMS FILE-OP veneer gate -- extends alpha-crtl-rms-veneer + # from the stdio family to open/creat/unlink/remove/rename/opendir/readdir/ + # closedir. The port image (crtl_rms3_test.c) creats FOPCRE.DAT, creats+unlinks + # FOPDEL.DAT, creats+renames FOPSRC.DAT->FOPDST.DAT via the VECTOR-SUBSTITUTED + # decc$* file-ops (bound by symbol-vector INDEX to the crtl_rms_stdio.c veneer + # -> sys$create/$erase/$rename over the ACP), then an INDEPENDENT reader (DCL + # DIRECTORY, a different accessor) asserts FOPCRE.DAT + FOPDST.DAT present with + # genuine ODS-2 File IDs and FOPDEL.DAT/FOPSRC.DAT gone -- something a ramfs/ + # POSIX write can never produce in the ACP directory. Runs a 4-case can-fail + # selftest before the boot. Same alpha_activation PR trigger + toolchain images. + # ----------------------------------------------------------------------- + alpha-crtl-rms-fileop: + name: "OVMX/Alpha CRTL->RMS file-op veneer gate — boots the veneer-wired crtl_rms3 image on the real /dev/vms executive; its decc$open/creat/unlink/rename/opendir/readdir/closedir reach the ODS-2 ACP, then an INDEPENDENT DIRECTORY reader asserts the created+renamed files landed with genuine File IDs and the deleted+renamed-away files are gone (vms-3320, blocks vms-fd1)" + needs: changes + if: ${{ github.event_name == 'pull_request' && needs.changes.outputs.alpha_activation == 'true' }} + runs-on: ubuntu-latest + timeout-minutes: 150 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Free up disk space + run: | + sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc \ + /opt/hostedtoolcache/CodeQL /usr/local/share/boost || true + df -h / + + - name: Build the alpha-linux-gnu cross toolchain image (gha layer cache) + uses: docker/build-push-action@v6 + with: + context: tools/cross-alpha + file: tools/cross-alpha/Dockerfile + push: false + load: true + tags: ovmx-cross-alpha:latest + cache-from: type=gha,scope=cross-alpha + cache-to: type=gha,mode=max,scope=cross-alpha + + - name: Build the alpha-dec-vms cross toolchain image (gha layer cache) + uses: docker/build-push-action@v6 + with: + context: tools/cross-alpha-vms + file: tools/cross-alpha-vms/Dockerfile + push: false + load: true + tags: ovmx-cross-alpha-vms:latest + cache-from: type=gha,scope=cross-alpha-vms + cache-to: type=gha,mode=max,scope=cross-alpha-vms + + - name: "CRTL->RMS file-op veneer gate — qemu-system-alpha boots the veneer-wired crtl_rms3 image on the real /dev/vms executive; its decc$open/creat/unlink/rename/opendir/readdir/closedir drive sys$create/$open/$erase/$rename/$parse/$search over the ODS-2 ACP, then an INDEPENDENT reader (DCL DIRECTORY, a different accessor than the writer's CRTL handle) asserts FOPCRE.DAT + FOPDST.DAT landed with genuine ODS-2 File IDs and FOPDEL.DAT/FOPSRC.DAT are gone; runs a 4-case can-fail selftest before the boot" + run: tools/cross-alpha/run-module-gp-activation-alpha.sh crtl-rms-fileop-gate + # ----------------------------------------------------------------------- # alpha-mf-multifile (vms-bdd): the MULTI-.O STRICT-link + activation gate -- # the rung above alpha-crtl-rms-n7 (which is single-object). The milestone diff --git a/docs/design-gcc-port-surface-gaps-register.md b/docs/design-gcc-port-surface-gaps-register.md index 291fadf5f..1b3ea5788 100644 --- a/docs/design-gcc-port-surface-gaps-register.md +++ b/docs/design-gcc-port-surface-gaps-register.md @@ -263,6 +263,23 @@ PORT image's DECC$SHR (a build sub-project — the alpha-dec-vms port world has `vms_kif`/RMS substrate yet; the `vms-47e` child, §3.1). Until that lands, the alpha port image's own file writes are still musl-POSIX → Linux-Alpha VFS. +> **UPDATE (vms-3320, blocks vms-fd1):** the CRTL→RMS veneer is now extended +> **beyond the stdio family** to the eight file-ops the GCC-port driver leans on: +> `open`/`creat` (temp-file minting → `sys$create`/`sys$open`), `unlink`/`remove` +> (cleanup → `sys$erase`), `rename` (atomic output finalization → the new +> `sys$rename` RMS service → executive ACP `IO$_MODIFY!IO$M_MOVE`, vms-de7: a +> directory-entry re-link that KEEPS the File ID, NOT erase+create), and +> `opendir`/`readdir`/`closedir` (directory enumeration → `sys$parse`+`sys$search` +> + `rms_search_fid`). All eight are added to `src/vmsrms/crtl_rms_stdio.c` and +> **vector-substituted into the alpha DECC$SHR in their sorted sv# slots** +> (`mk_decc_shr.sh` ALPHA_CRTL_RMS_USE block, in-place — never tail-appended; +> sv# skew is the vms-b14/vms-f49 trap). Proven un-fakeably on the real executive +> by an INDEPENDENT ACP reader for each op (`tests/qemu/test_syssvc_crtl_rms_veneer.c`, +> 40/40 — incl. rename keeping the SAME File ID), and wired as the alpha activation +> gate `crtl-rms-fileop-gate` (`crtl_rms3_test.c` + an independent DIRECTORY reader). +> This closes the **PORT-CRTL binding** for the file-op family; the compiler driver's +> temp-file/cleanup/dir-enum now reach real RMS/ODS-2, not musl-POSIX. + > **rd-ID caveat (Rule 10):** this table's "rd item" column reads `vms-1b5`, but > in rd `vms-1b5` is actually the *decc$feature* item; the RMS-beyond-stdio item > is **`vms-2e72`**. Doc↔rd cross-wiring for the conductor to reconcile. diff --git a/tests/qemu/test_syssvc_crtl_rms_veneer.c b/tests/qemu/test_syssvc_crtl_rms_veneer.c index d2c4ca9d2..7d4b85d0a 100644 --- a/tests/qemu/test_syssvc_crtl_rms_veneer.c +++ b/tests/qemu/test_syssvc_crtl_rms_veneer.c @@ -39,6 +39,7 @@ #include #include #include +#include /* vms-3320: O_* for ovmx_crtl_open */ #include "vms_kif.h" #include "rms/rms.h" @@ -218,12 +219,145 @@ int main(void) } /* ================================================================= * - * 5. Isolation — erase the file so the fixture is restored. * + * 5. FILE-OP VENEER (vms-3320): decc$creat/open/unlink/remove/rename/ * + * opendir/readdir/closedir over RMS, each proven by the SAME * + * INDEPENDENT ACP reader a ramfs cannot fake. * + * ================================================================= */ +#define CREATNAME "CVENEER.DAT" +#define CREATSPEC DIRSPEC CREATNAME +#define RENSRC DIRSPEC "RENSRC.DAT" +#define RENDST DIRSPEC "RENDST.DAT" +#define DIRA DIRSPEC "ENUMA.DAT" +#define DIRB DIRSPEC "ENUMB.DAT" + + /* --- 5.1 creat mints a real ODS-2 file the independent reader sees. --- */ + erase_spec(CREATSPEC ";*"); + int cfd = ovmx_crtl_creat(CREATSPEC, 0); + check(cfd >= OVMX_CRTL_FD_BASE, + "5.1a: ovmx_crtl_creat -> sys$create over the ACP, returns a veneer fd"); + if (cfd >= 0) ovmx_crtl_fdclose(cfd); + { + uint16_t cfid = 0; char ctail[128]; uint32_t cend = 0; + int cn = search_one(CREATSPEC ";*", &cfid, ctail, sizeof(ctail), &cend); + check(cn == 1, + "5.1b: independent sys$search finds the creat-minted file " + "(ramfs cannot appear on the ACP directory)"); + check(cfid != 0, + "5.1c: the creat file carries a genuine nonzero ODS-2 File ID"); + check(strstr(ctail, ";1") != NULL, + "5.1d: creat minted version ;1 (a genuine ODS-2 create)"); + printf(" [independent ACP reader] creat resultant='%s' fid=(%u,...)\n", + ctail, cfid); + } + + /* --- 5.2 unlink removes it; the independent reader sees it GONE. --- */ + check(ovmx_crtl_unlink(CREATSPEC ";*") == 0, + "5.2a: ovmx_crtl_unlink -> sys$erase NORMAL"); + check(search_one(CREATSPEC ";*", NULL, NULL, 0, &endst) == 0, + "5.2b: independent sys$search finds the unlinked file GONE " + "(a real ODS-2 directory-entry removal)"); + + /* --- 5.3 open(O_CREAT) mints; remove() (ISO C) deletes; reader agrees. --- */ + { + erase_spec(CREATSPEC ";*"); + int ofd = ovmx_crtl_open(CREATSPEC, O_CREAT | O_WRONLY | O_TRUNC); + check(ofd >= OVMX_CRTL_FD_BASE, + "5.3a: ovmx_crtl_open(O_CREAT) -> sys$create, returns a veneer fd"); + if (ofd >= 0) ovmx_crtl_fdclose(ofd); + uint16_t ofid = 0; + check(search_one(CREATSPEC ";*", &ofid, NULL, 0, &endst) == 1 && ofid != 0, + "5.3b: independent reader sees the open(O_CREAT) file with a File ID"); + check(ovmx_crtl_remove(CREATSPEC ";*") == 0, + "5.3c: ovmx_crtl_remove -> sys$erase NORMAL"); + check(search_one(CREATSPEC ";*", NULL, NULL, 0, &endst) == 0, + "5.3d: independent reader sees the removed file GONE"); + } + + /* --- 5.4 rename: the ATOMIC re-link keeps the SAME File ID (teeth). --- */ + { + erase_spec(RENSRC ";*"); + erase_spec(RENDST ";*"); + /* Create the source through the proven stdio veneer, capture its FID. */ + OVMX_CRTL_FILE *sf = ovmx_crtl_fopen(RENSRC, "w"); + check(sf != NULL, "5.4a: create RENSRC.DAT (fopen->sys$create)"); + if (sf) { ovmx_crtl_fwrite("RENAMEME", 1, 8, sf); ovmx_crtl_fclose(sf); } + uint16_t src_fid = 0; + check(search_one(RENSRC ";*", &src_fid, NULL, 0, &endst) == 1 && src_fid != 0, + "5.4b: independent reader sees RENSRC.DAT with File ID X"); + + check(ovmx_crtl_rename(RENSRC, RENDST) == 0, + "5.4c: ovmx_crtl_rename -> sys$rename (ACP MODIFY!M_MOVE) NORMAL"); + + check(search_one(RENSRC ";*", NULL, NULL, 0, &endst) == 0, + "5.4d: independent reader sees the OLD name RENSRC.DAT GONE"); + uint16_t dst_fid = 0; char dtail[128]; + int dn = search_one(RENDST ";*", &dst_fid, dtail, sizeof(dtail), &endst); + check(dn == 1, + "5.4e: independent reader sees the NEW name RENDST.DAT present"); + check(dst_fid != 0 && dst_fid == src_fid, + "5.4f: RENDST.DAT carries the SAME File ID as RENSRC had -- proves " + "an ATOMIC directory-entry re-link, NOT erase+create (a new FID)"); + printf(" [independent ACP reader] rename: RENSRC fid=(%u,...) -> " + "RENDST '%s' fid=(%u,...) SAME=%s\n", + src_fid, dtail, dst_fid, (src_fid == dst_fid) ? "YES" : "NO"); + /* On-disk header confirms the moved file keeps its FID + allocation. */ + struct rms_fileattr rattr; memset(&rattr, 0, sizeof rattr); + uint32_t rst = rms_file_attr(RENDST, &rattr); + check($VMS_STATUS_SUCCESS(rst) && rattr.fid_num == src_fid, + "5.4g: RENDST.DAT on-disk header File ID == the source's (two " + "independent readers agree the file kept its FID)"); + erase_spec(RENDST ";*"); + } + + /* --- 5.5 opendir/readdir enumerate the REAL ODS-2 directory entries. --- */ + { + erase_spec(DIRA ";*"); + erase_spec(DIRB ";*"); + OVMX_CRTL_FILE *fa = ovmx_crtl_fopen(DIRA, "w"); + if (fa) ovmx_crtl_fclose(fa); + OVMX_CRTL_FILE *fb = ovmx_crtl_fopen(DIRB, "w"); + if (fb) ovmx_crtl_fclose(fb); + check(fa != NULL && fb != NULL, "5.5a: create ENUMA.DAT + ENUMB.DAT"); + + OVMX_CRTL_DIR *dp = ovmx_crtl_opendir(DIRSPEC); + check(dp != NULL, "5.5b: ovmx_crtl_opendir(dir) -> sys$parse over the ACP"); + int saw_a = 0, saw_b = 0, fid_a = 0, fid_b = 0, total = 0; + if (dp) { + struct ovmx_crtl_dirent *e; + while ((e = ovmx_crtl_readdir(dp)) != NULL) { + total++; + if (strstr(e->d_name, "ENUMA.DAT")) { saw_a = 1; fid_a = e->d_fileid; } + if (strstr(e->d_name, "ENUMB.DAT")) { saw_b = 1; fid_b = e->d_fileid; } + } + check(ovmx_crtl_closedir(dp) == 0, + "5.5c: ovmx_crtl_closedir -> rms_search_end (context released)"); + } + check(saw_a && saw_b, + "5.5d: readdir enumerated BOTH real ODS-2 entries by name"); + check(fid_a != 0 && fid_b != 0 && fid_a != fid_b, + "5.5e: each enumerated entry carries its genuine (distinct) File ID"); + /* Cross-check against the independent single-file searches. */ + uint16_t ia = 0, ib = 0; + search_one(DIRA ";*", &ia, NULL, 0, &endst); + search_one(DIRB ";*", &ib, NULL, 0, &endst); + check((uint16_t)fid_a == ia && (uint16_t)fid_b == ib, + "5.5f: readdir's File IDs match the independent sys$search File IDs " + "(same genuine ODS-2 directory, two readers agree)"); + printf(" [independent ACP reader] readdir enumerated %d entries; " + "ENUMA fid=%d (search %u), ENUMB fid=%d (search %u)\n", + total, fid_a, ia, fid_b, ib); + erase_spec(DIRA ";*"); + erase_spec(DIRB ";*"); + } + + /* ================================================================= * + * 6. Isolation — erase the stdio-veneer file so the fixture is * + * restored. * * ================================================================= */ st = erase_spec(VSPEC ";*"); - check($VMS_STATUS_SUCCESS(st), "5a: sys$erase VENEER.DAT (isolation)"); + check($VMS_STATUS_SUCCESS(st), "6a: sys$erase VENEER.DAT (isolation)"); check(search_one(VSPEC ";*", NULL, NULL, 0, &endst) == 0, - "5b: a final search finds NONE (fixture restored)"); + "6b: a final search finds NONE (fixture restored)"); free(buf); diff --git a/tools/cross-alpha-vms/joint-e2e/build-joint-image.sh b/tools/cross-alpha-vms/joint-e2e/build-joint-image.sh index c2871213d..49e9d1997 100755 --- a/tools/cross-alpha-vms/joint-e2e/build-joint-image.sh +++ b/tools/cross-alpha-vms/joint-e2e/build-joint-image.sh @@ -339,6 +339,11 @@ cp "$WORK/LINK.EXE" "$WORK/DECC\$SHR.EXE" "$WORK/libots/LIBOTS_SHR.EXE" "$OUT/" # SYS$SHARE search-path set -- with no extra copy needed when the veneer path # built it; a plain (non-veneer) run leaves $RMS empty and stages nothing new. echo "== joint-e2e image built (genuine alpha path, vms-864) ==" +# vms-3320: the FILE-OP veneer gate (JOINT_MAIN=crtl_rms3_test.c) drops a marker +# so build-alpha-bootimage.sh stages the FILE-OP independent-reader SYSTARTUP +# (DIRECTORY of the FOP*.DAT set) instead of the stdio VENEER one (which reads +# PORTTEST.DAT). Any other JOINT_MAIN leaves it absent -> unchanged behaviour. +[ "$JOINT_MAIN" = crtl_rms3_test.c ] && { : > "$OUT/FILEOP_PROOF"; echo "== FILEOP_PROOF marker staged (vms-3320 file-op veneer gate) =="; } ls -la "$OUT/" readelf -h "$OUT/joint_e2e.exe" | grep -E "Type|Machine|Entry" readelf -SW "$OUT/joint_e2e.exe" | grep -E "vms\\\$xfer|vms\\\$imp|CODE|DATA" || true diff --git a/tools/cross-alpha-vms/joint-e2e/crtl_rms3_test.c b/tools/cross-alpha-vms/joint-e2e/crtl_rms3_test.c new file mode 100644 index 000000000..98fb6553e --- /dev/null +++ b/tools/cross-alpha-vms/joint-e2e/crtl_rms3_test.c @@ -0,0 +1,151 @@ +/* crtl_rms3_test.c — the alpha-dec-vms CRTL/RMS FILE-OP port program (vms-3320), + * wired as a REPRODUCIBLE joint-e2e VARIANT (build-joint-image.sh JOINT_MAIN). + * + * It advances the vms-b4f / vms-da0 ladder past crtl_rms_test.c (stdio family) + * and crtl_rms2_test.c (line-I/O + fmt + sort): this program drives the FILE-OP + * decc$ surface a real GCC port leans on but which was still musl-POSIX before + * vms-3320 — temp-file minting, cleanup, atomic finalization, dir enumeration: + * + * - open / creat : mint a real ODS-2 file (sys$create) and reopen it (sys$open) + * - unlink : delete a file (sys$erase) — temp cleanup + * - rename : ATOMIC re-link (sys$rename -> ACP MODIFY!M_MOVE) — the + * compiler's "write NAME.tmp, rename over the final" finalize + * - opendir/readdir/closedir : enumerate the REAL ODS-2 directory entries + * + * Every reference is a GENUINE decc$ call: the alpha-dec-vms cross cc1 decorates + * each name to the decc$ surface at codegen, and mk_decc_shr.sh's ALPHA/EVAX + * branch (ALPHA_CRTL_RMS_USE) VECTOR-SUBSTITUTES decc$open/creat/unlink/remove/ + * rename/opendir/readdir/closedir -> src/vmsrms/crtl_rms_stdio.c's ovmx_crtl_* + * (which drive sys$create/$open/$erase/$rename/$parse/$search over the real + * Files-11 ODS-2 executive ACP). Under JOINT_CRTL_RMS_VENEER=1 this is the path + * that runs — NOT musl-POSIX. Fail-honest: any RMS failure returns a sentinel. + * + * This program is its OWN first (same-CRTL) check — it returns sentinel 7 only + * if every op succeeded AND its own decc$opendir/readdir enumeration agrees the + * created + renamed files are present and the deleted + old-name files are gone. + * The UN-FAKEABLE proof is the INDEPENDENT reader the boot runs afterward + * (SYS$MANAGER:SYSTARTUP_VMS -> DCL DIRECTORY over the ACP, a DIFFERENT accessor): + * it must see FOPCRE.DAT + FOPDST.DAT with genuine ODS-2 File IDs and NOT see + * FOPDEL.DAT / FOPSRC.DAT. The program deliberately LEAVES FOPCRE.DAT + FOPDST.DAT + * on the volume for that reader; a ramfs/POSIX write can never appear in the ACP + * directory (see tools/cross-alpha/SYSTARTUP_VMS_FILEOP_PROOF.COM). + * + * SENTINEL-RETURN CONVENTION (deterministic). crt0 maps the return N through + * C$_EXIT1, so $STATUS decodes to C$_EXIT1 + (N-1)*8: + * 7 = FULL SUCCESS (all 8 ops + self-enumeration agreement) + * 1 = creat(FOPCRE.DAT) failed + * 2 = open(FOPCRE.DAT, O_RDONLY) failed + * 3 = creat(FOPDEL.DAT) failed + * 4 = unlink(FOPDEL.DAT) failed + * 5 = creat(FOPSRC.DAT) failed + * 6 = rename(FOPSRC.DAT -> FOPDST.DAT) failed + * 8 = opendir failed, OR self-enumeration disagreed (created/renamed missing, + * or deleted/old-name still present) + */ + +/* alpha-dec-vms is LP64 (-mpointer-size=64). No libc headers in the cross image; + * declare the CRTL surface directly — the NAMES matter for the link and the + * cross cc1 decorates them to decc$ at codegen (matching crtl_rms_test.c). */ +typedef unsigned long ovmx_size_t; + +/* Alpha (OSF/1) open() flag ABI — arch/alpha uapi/asm/fcntl.h, matching the + * OVMX alpha musl bits/fcntl.h the veneer is compiled against. */ +#define O_RDONLY 0x0000 +#define O_WRONLY 0x0001 +#define O_CREAT 0x0200 /* 01000 */ +#define O_TRUNC 0x0400 /* 02000 */ + +extern int open(const char *, int); /* non-variadic: match the veneer ABI (vms-3320) */ +extern int creat(const char *, int); +extern int close(int); +extern int unlink(const char *); +extern int rename(const char *, const char *); +extern void *opendir(const char *); +extern int closedir(void *); +extern int printf(const char *, ...); +extern int fprintf(void *, const char *, ...); +extern char *strstr(const char *, const char *); +extern void *stderr; + +/* decc$readdir returns a struct dirent*; ovmx_crtl_readdir fills a struct whose + * FIRST member is d_name[256] (offset 0), so this layout reads the name back. */ +struct portdirent { + char d_name[256]; + unsigned short d_namlen; + unsigned short d_fileid; +}; +extern struct portdirent *readdir(void *); + +#define DIRSPEC "VDA0:[SYSTMP]" +#define FOPCRE DIRSPEC "FOPCRE.DAT" /* created, LEFT for the reader */ +#define FOPDEL DIRSPEC "FOPDEL.DAT" /* created then unlinked (gone) */ +#define FOPSRC DIRSPEC "FOPSRC.DAT" /* created then renamed away (gone) */ +#define FOPDST DIRSPEC "FOPDST.DAT" /* rename target, LEFT for the reader */ + +int main(int argc, char **argv, char **envp) +{ + (void)argv; (void)envp; + + /* 1. creat mints a real ODS-2 file (sys$create); CLOSE it so sys$close + * finalizes the ODS-2 header/FH2 and its File ID becomes visible to the + * independent reader. Without an explicit close the FID only finalizes at + * clean image exit -- which the post-op vms-c5d crash preempts on alpha + * (that is the x86_64-green / alpha-red split this closes, vms-3320). */ + int cfd = creat(FOPCRE, 0); + if (cfd < 0) + return 1; + close(cfd); /* finalize FOPCRE's File ID */ + + /* 2. open the just-created file read-only (sys$open), then close. */ + int ofd = open(FOPCRE, O_RDONLY); + if (ofd < 0) + return 2; + close(ofd); + + /* 3. create a doomed temp, close it, then unlink it (sys$erase). */ + int dfd = creat(FOPDEL, 0); + if (dfd < 0) + return 3; + close(dfd); + if (unlink(FOPDEL) != 0) + return 4; + + /* 4. create a source, CLOSE it (finalize its FID), then ATOMICALLY rename + * it (sys$rename -> ACP MODIFY!M_MOVE) -- the re-link carries that SAME + * File ID into FOPDST, which the independent reader then confirms. */ + int sfd = creat(FOPSRC, 0); + if (sfd < 0) + return 5; + close(sfd); /* finalize FOPSRC's File ID BEFORE the rename */ + if (rename(FOPSRC, FOPDST) != 0) + return 6; + + /* 5. SELF-CHECK: enumerate the directory via decc$opendir/readdir and + * confirm the created + renamed files are present, the deleted + old + * names gone. (The un-fakeable proof is the independent DIRECTORY reader + * the boot runs next — this is the same-CRTL corroboration.) */ + void *dir = opendir(DIRSPEC); + if (!dir) + return 8; + int saw_cre = 0, saw_dst = 0, saw_del = 0, saw_src = 0, nent = 0; + struct portdirent *e; + while ((e = readdir(dir)) != 0) { + nent++; + if (strstr(e->d_name, "FOPCRE.DAT")) saw_cre = 1; + if (strstr(e->d_name, "FOPDST.DAT")) saw_dst = 1; + if (strstr(e->d_name, "FOPDEL.DAT")) saw_del = 1; + if (strstr(e->d_name, "FOPSRC.DAT")) saw_src = 1; + } + closedir(dir); + + fprintf(stderr, "OVMX CRTL/RMS3 file-op test: enumerated %d entries; " + "cre=%d dst=%d del=%d src=%d\n", nent, saw_cre, saw_dst, saw_del, saw_src); + + if (!saw_cre || !saw_dst || saw_del || saw_src) + return 8; + + printf("OVMX CRTL/RMS3 file-op test: OK " + "(open+creat+unlink+rename+opendir+readdir+closedir over RMS) argc=%d\n", argc); + + return 7; /* distinctive success -> $STATUS = C$_EXIT1 + (7-1)*8 */ +} diff --git a/tools/cross-alpha/SYSTARTUP_VMS_FILEOP_PROOF.COM b/tools/cross-alpha/SYSTARTUP_VMS_FILEOP_PROOF.COM new file mode 100644 index 000000000..01594b2c9 --- /dev/null +++ b/tools/cross-alpha/SYSTARTUP_VMS_FILEOP_PROOF.COM @@ -0,0 +1,53 @@ +$! SYSTARTUP_VMS.COM - CRTL->RMS FILE-OP veneer un-fakeable proof variant +$! (vms-3320, extends the vms-f49 rung-4 veneer proof to the file-op family; +$! harness-only). +$! +$! Harness variant of the Alpha static-bootstrap SYS$MANAGER:SYSTARTUP_VMS.COM, +$! staged onto the ODS-2 volume by tools/cross-alpha/build-alpha-bootimage.sh +$! ONLY when the FILEOP proof marker is present (a crtl_rms3_test.c build); the +$! product rootfs-alpha file is never modified. +$! +$! WHAT THIS PROVES (the anti-fabrication payoff, INV-6). SYS$SYSTEM:JOINT_E2E is +$! the alpha-dec-vms GCC-port image built with the CRTL->RMS veneer wired in +$! (JOINT_CRTL_RMS_VENEER=1): its decc$open/creat/unlink/rename/opendir/readdir/ +$! closedir bind, BY SYMBOL-VECTOR INDEX, to the crtl_rms_stdio.c veneer +$! (ovmx_crtl_* -> sys$create/$open/$erase/$rename/$parse/$search -> +$! LIBVMSRMS$SHR -> ioctl(/dev/vms) -> the Files-11 ACP), NOT to musl-POSIX. It +$! creats FOPCRE.DAT, creats+unlinks FOPDEL.DAT, and creats+renames +$! FOPSRC.DAT -> FOPDST.DAT, all on the live OVMX/Alpha executive, LEAVING +$! FOPCRE.DAT + FOPDST.DAT behind for this reader. +$! +$! Then -- the un-fakeable part -- an INDEPENDENT reader inspects the volume +$! through a DIFFERENT accessor than the writer's CRTL handle: DCL DIRECTORY, +$! which runs its OWN sys$parse+sys$search over the Files-11 ACP directory +$! (dcl_cmd_file.c cmd_directory -> from_acp) and prints the GENUINE ODS-2 File +$! ID the directory search returned. A POSIX/ramfs write cannot appear in the +$! ACP directory at all (it draws %DIRECT-W-NOFILES, NO File ID). So: +$! - FOPCRE.DAT + FOPDST.DAT present WITH File IDs => creat + rename landed; +$! - FOPDEL.DAT + FOPSRC.DAT %DIRECT-W-NOFILES => unlink + rename-away worked. +$! The renamed FOPDST.DAT keeping a genuine File ID proves the ACP MODIFY!M_MOVE +$! re-link (the same-File-ID atomicity is proven exhaustively on the host-arch +$! layer, tests/qemu/test_syssvc_crtl_rms_veneer.c). +$! +$ SET NOON +$! +$ WRITE SYS$OUTPUT "FILEOP-PROOF: === MILESTONE: RUN JOINT_E2E (veneer file-ops over sys$create/$erase/$rename) ===" +$ RUN SYS$SYSTEM:JOINT_E2E +$ WRITE SYS$OUTPUT "FILEOP-PROOF: RUN-STATUS=''$STATUS' SEVERITY=''$SEVERITY'" +$! +$ WRITE SYS$OUTPUT "FILEOP-PROOF: === INDEPENDENT READER: DIRECTORY over the ACP (a DIFFERENT accessor) ===" +$ WRITE SYS$OUTPUT "FILEOP-PROOF: --- created file FOPCRE.DAT (must be present) ---" +$ DIRECTORY/FULL VDA0:[SYSTMP]FOPCRE.DAT +$ WRITE SYS$OUTPUT "FILEOP-PROOF: CRE-STATUS=''$STATUS' SEVERITY=''$SEVERITY'" +$ WRITE SYS$OUTPUT "FILEOP-PROOF: --- renamed target FOPDST.DAT (must be present, genuine File ID) ---" +$ DIRECTORY/FULL VDA0:[SYSTMP]FOPDST.DAT +$ WRITE SYS$OUTPUT "FILEOP-PROOF: DST-STATUS=''$STATUS' SEVERITY=''$SEVERITY'" +$ WRITE SYS$OUTPUT "FILEOP-PROOF: --- unlinked file FOPDEL.DAT (must be GONE) ---" +$ DIRECTORY VDA0:[SYSTMP]FOPDEL.DAT +$ WRITE SYS$OUTPUT "FILEOP-PROOF: DEL-STATUS=''$STATUS' SEVERITY=''$SEVERITY'" +$ WRITE SYS$OUTPUT "FILEOP-PROOF: --- rename source FOPSRC.DAT (must be GONE) ---" +$ DIRECTORY VDA0:[SYSTMP]FOPSRC.DAT +$ WRITE SYS$OUTPUT "FILEOP-PROOF: SRC-STATUS=''$STATUS' SEVERITY=''$SEVERITY'" +$ WRITE SYS$OUTPUT "FILEOP-PROOF: === END INDEPENDENT READER ===" +$! +$ EXIT diff --git a/tools/cross-alpha/build-alpha-bootimage.sh b/tools/cross-alpha/build-alpha-bootimage.sh index 9113c3fc3..c6635e0b0 100755 --- a/tools/cross-alpha/build-alpha-bootimage.sh +++ b/tools/cross-alpha/build-alpha-bootimage.sh @@ -258,9 +258,19 @@ docker run --rm --memory=8g --cpus="$(nproc)" \ && cp "$JOINT/${_vp}\$SHR.EXE" "$ST/vms/SYS0/SYSCOMMON/SYSLIB/${_vp}\$SHR.EXE" \ || { echo "FAIL: veneer producer $JOINT/${_vp}\$SHR.EXE missing"; exit 1; } done - cp /repo/tools/cross-alpha/SYSTARTUP_VMS_VENEER_PROOF.COM \ - "$ST/vms/SYS0/SYSCOMMON/SYSMGR/SYSTARTUP_VMS.COM" - echo " JOINT-E2E (VENEER): joint_e2e.exe -> SYS\$SYSEXE; DECC\$SHR + LIBOTS_SHR + full RMS producer graph (LIBVMSRMS/LIBVMS/LIBVMSFS/LIBVMSLNM/LIBVMSPROCESS/LIBVMSSYS\$SHR) -> SYS\$SHARE; VENEER-proof SYSTARTUP (independent DIRECTORY/FULL reader) staged" + # vms-3320: the FILE-OP veneer gate marks its joint dir (FILEOP_PROOF) + # so it stages its OWN independent-reader SYSTARTUP (DIRECTORY of the + # FOP*.DAT set) instead of the stdio VENEER one (PORTTEST.DAT). The + # producer graph staged just above is identical for both. + if [ -f "$JOINT/FILEOP_PROOF" ]; then + cp /repo/tools/cross-alpha/SYSTARTUP_VMS_FILEOP_PROOF.COM \ + "$ST/vms/SYS0/SYSCOMMON/SYSMGR/SYSTARTUP_VMS.COM" + echo " JOINT-E2E (FILE-OP VENEER): joint_e2e.exe -> SYS\$SYSEXE; full RMS producer graph -> SYS\$SHARE; FILEOP-proof SYSTARTUP (independent DIRECTORY reader over creat/unlink/rename set) staged" + else + cp /repo/tools/cross-alpha/SYSTARTUP_VMS_VENEER_PROOF.COM \ + "$ST/vms/SYS0/SYSCOMMON/SYSMGR/SYSTARTUP_VMS.COM" + echo " JOINT-E2E (VENEER): joint_e2e.exe -> SYS\$SYSEXE; DECC\$SHR + LIBOTS_SHR + full RMS producer graph (LIBVMSRMS/LIBVMS/LIBVMSFS/LIBVMSLNM/LIBVMSPROCESS/LIBVMSSYS\$SHR) -> SYS\$SHARE; VENEER-proof SYSTARTUP (independent DIRECTORY/FULL reader) staged" + fi else cp /repo/tools/cross-alpha/SYSTARTUP_VMS_JOINT_PROOF.COM \ "$ST/vms/SYS0/SYSCOMMON/SYSMGR/SYSTARTUP_VMS.COM" diff --git a/tools/cross-alpha/run-module-gp-activation-alpha.sh b/tools/cross-alpha/run-module-gp-activation-alpha.sh index 26b2aee1c..df674ac9c 100755 --- a/tools/cross-alpha/run-module-gp-activation-alpha.sh +++ b/tools/cross-alpha/run-module-gp-activation-alpha.sh @@ -65,6 +65,7 @@ # tools/cross-alpha/run-module-gp-activation-alpha.sh gate # same, explicit # tools/cross-alpha/run-module-gp-activation-alpha.sh crtl-rms-gate # crtl_rms heap+RMS+stdio -> N=7 (non-veneer control) # tools/cross-alpha/run-module-gp-activation-alpha.sh crtl-rms-veneer-gate # vms-f49 rung 4: veneer write + INDEPENDENT ODS-2 File-ID reader +# tools/cross-alpha/run-module-gp-activation-alpha.sh crtl-rms-fileop-gate # vms-3320: open/creat/unlink/rename/opendir/readdir/closedir veneer + INDEPENDENT DIRECTORY reader # tools/cross-alpha/run-module-gp-activation-alpha.sh mf-gate # multi-.o cross-boundary -> N=5 (vms-bdd) # tools/cross-alpha/run-module-gp-activation-alpha.sh shipped-gate # SHIPPED packaging path -> N=3 (vms-410) # tools/cross-alpha/run-module-gp-activation-alpha.sh selftest # can-fail proof, no boot @@ -364,6 +365,70 @@ assert_veneer() { return 1 } +# assert_fileop -- THE TEETH for the vms-3320 CRTL->RMS FILE-OP +# veneer proof (`crtl-rms-fileop-gate' mode). Extends the vms-f49 veneer proof +# from the stdio family to open/creat/unlink/remove/rename/opendir/readdir/ +# closedir: the port image (crtl_rms3_test.c) creats FOPCRE.DAT, creats+unlinks +# FOPDEL.DAT, creats+renames FOPSRC.DAT->FOPDST.DAT via the VECTOR-SUBSTITUTED +# decc$* file-ops, then the boot's INDEPENDENT reader (DCL DIRECTORY over the +# ACP -- a DIFFERENT accessor) inspects the volume. Pass iff, in the +# INDEPENDENT-reader region: +# (b1) FOPCRE.DAT present WITH a nonzero ODS-2 File ID (creat landed); +# (b2) FOPDST.DAT present WITH a nonzero ODS-2 File ID (rename target landed); +# (b3) FOPDEL.DAT %DIRECT-W-NOFILES (unlink removed it); +# (b4) FOPSRC.DAT %DIRECT-W-NOFILES (rename moved it away); +# AND (c) no activation-LOAD failure. The port program's own sentinel-7 self- +# enumeration is informational only (a post-op cleanup crash cannot undo a +# landing the independent reader already confirmed -- the vms-f49 banked-gate +# discipline). Pure function over the transcript; shared by the boot + selftest. +assert_fileop() { + local log="$1" + [ -f "$log" ] || { echo " FAIL: no console log at $log"; return 1; } + + # (a) informational: the port image's own self-verify (sentinel 7 + OK line). + local port_ok seam mile_hex sentinel="?" + port_ok=$(grep -qaE "OVMX CRTL/RMS3 file-op test: OK" "$log" && echo 1 || echo 0) + seam=$(grep -aoE "OVMX-SEAM: image=JOINT_E2E\.EXE[^\"]*STATUS=0x[0-9A-Fa-f]+" "$log" 2>/dev/null | tail -1) + mile_hex=$(printf '%s' "$seam" | grep -oiE '0x[0-9a-f]+' | tail -1) + if [ -n "$mile_hex" ] && [ "$(( mile_hex ))" -ge "$CEXIT1" ] && [ $(( ( $(( mile_hex )) - CEXIT1) % 8 )) -eq 0 ]; then + sentinel=$(( ( $(( mile_hex )) - CEXIT1) / 8 + 1 )) + fi + + # (b) THE TEETH -- confine to the INDEPENDENT-reader region, then sub-region by + # the per-file "--- ... ---" markers so a token cannot leak across files. + local region cre_reg dst_reg del_reg src_reg + region=$(awk '/FILEOP-PROOF: === INDEPENDENT READER/{f=1} f{print} /FILEOP-PROOF: === END INDEPENDENT READER/{f=0}' "$log") + cre_reg=$(printf '%s\n' "$region" | awk '/created file FOPCRE.DAT/{f=1} f{print} /FILEOP-PROOF: CRE-STATUS/{f=0}') + dst_reg=$(printf '%s\n' "$region" | awk '/renamed target FOPDST.DAT/{f=1} f{print} /FILEOP-PROOF: DST-STATUS/{f=0}') + del_reg=$(printf '%s\n' "$region" | awk '/unlinked file FOPDEL.DAT/{f=1} f{print} /FILEOP-PROOF: DEL-STATUS/{f=0}') + src_reg=$(printf '%s\n' "$region" | awk '/rename source FOPSRC.DAT/{f=1} f{print} /FILEOP-PROOF: SRC-STATUS/{f=0}') + + local cre_fid dst_fid cre_ok=0 dst_ok=0 del_ok=0 src_ok=0 + cre_fid=$(printf '%s' "$cre_reg" | grep -aoE "FOPCRE\.DAT;[0-9]+[^A-Za-z]*File ID:[[:space:]]*\([0-9]+" | grep -oE '\([0-9]+' | tr -d '(' | tail -1) + dst_fid=$(printf '%s' "$dst_reg" | grep -aoE "FOPDST\.DAT;[0-9]+[^A-Za-z]*File ID:[[:space:]]*\([0-9]+" | grep -oE '\([0-9]+' | tr -d '(' | tail -1) + [ -n "$cre_fid" ] && [ "$cre_fid" -gt 0 ] && ! printf '%s' "$cre_reg" | grep -qaE "%DIRECT-W-NOFILES" && cre_ok=1 + [ -n "$dst_fid" ] && [ "$dst_fid" -gt 0 ] && ! printf '%s' "$dst_reg" | grep -qaE "%DIRECT-W-NOFILES" && dst_ok=1 + printf '%s' "$del_reg" | grep -qaE "%DIRECT-W-NOFILES" && del_ok=1 + printf '%s' "$src_reg" | grep -qaE "%DIRECT-W-NOFILES" && src_ok=1 + + # (c) activation-LOAD failure only (a post-landing crash is not fatal here). + local errs err_ok=1 + errs=$(grep -aE "%IMGACT-F|IMGNOTFND|DEVNOTMOUNT" "$log" 2>/dev/null || true) + [ -n "$errs" ] && err_ok=0 + + echo " (a) port self-verify (informational) : port_ok=$port_ok seam=${seam:-} sentinel=$sentinel (7 = full)" + echo " (b) INDEPENDENT ACP reader (DIRECTORY):" + echo " b1 creat FOPCRE.DAT present, fid=${cre_fid:-} ok=$cre_ok" + echo " b2 rename FOPDST.DAT present, fid=${dst_fid:-} ok=$dst_ok" + echo " b3 unlink FOPDEL.DAT GONE (%DIRECT-W-NOFILES) ok=$del_ok" + echo " b4 rnsrc FOPSRC.DAT GONE (%DIRECT-W-NOFILES) ok=$src_ok" + echo " (c) image activated (no load failure) : ok=$err_ok" + [ "$err_ok" -eq 0 ] && echo " offending: $(printf '%s' "$errs" | tr '\n' '|')" + + [ "$cre_ok" -eq 1 ] && [ "$dst_ok" -eq 1 ] && [ "$del_ok" -eq 1 ] && [ "$src_ok" -eq 1 ] && [ "$err_ok" -eq 1 ] && return 0 + return 1 +} + # --------------------------------------------------------------------------- # build_joint_images -- build the N=3 milestone image (joint_main.c -> return 3) # and the SS$_NORMAL control (joint_main_ok.c -> return 0) with the SAME merged @@ -425,6 +490,12 @@ build_joint_images() { || die "veneer build produced no ${_p}\$SHR.EXE in $out_n3 (JOINT_CRTL_RMS_VENEER=1 expected the full producer graph)" cp "$out_n3/${_p}\$SHR.EXE" "$WORK/joint/${_p}\$SHR.EXE" done + # vms-3320: carry the FILE-OP marker (dropped by build-joint-image.sh when + # JOINT_MAIN=crtl_rms3_test.c) into $WORK/joint so build-alpha-bootimage.sh + # stages the FILE-OP independent-reader SYSTARTUP (DIRECTORY of the FOP*.DAT + # set) instead of the stdio VENEER one (which reads PORTTEST.DAT). The + # selective staging above would otherwise drop it. + [ -f "$out_n3/FILEOP_PROOF" ] && cp "$out_n3/FILEOP_PROOF" "$WORK/joint/FILEOP_PROOF" log "step 1: joint images staged into $WORK/joint (VENEER milestone N=$WANT_SENTINEL + control + DECC\$SHR/LIBOTS + full RMS producer graph LIBVMSRMS/LIBVMS/LIBVMSFS/LIBVMSLNM/LIBVMSPROCESS/LIBVMSSYS\$SHR)" else log "step 1: joint images staged into $WORK/joint (milestone N=$WANT_SENTINEL + SS\$_NORMAL control + producers)" @@ -466,7 +537,7 @@ run_boot_a() { # activated image (GETEXIT(SEL_SELF)); the DCL RUN fork path collapses the # POSIX exit, so the seam is the truth for the returned value. timeout "$BT" qemu-system-alpha -M clipper -smp 1 -m 1024 -vga none -nic none \ - -kernel vmlinux-boot -append "console=ttyS0 panic=-1 OVMX_IMGACT_SEAM=1" \ + -kernel vmlinux-boot -append "console=ttyS0 panic=-1 OVMX_IMGACT_SEAM=1 ${BOOT_APPEND_EXTRA:-}" \ -drive file=modgpA.img,format=raw,if=virtio \ -nographic -no-reboot <"$FIFO" > modgpA.raw 2>&1 & QP=$! @@ -876,6 +947,133 @@ EOF tail -60 "$WORK/modgpA.log" 2>/dev/null | sed 's/^/ | /' || true exit 1 ;; + crtl-rms-fileop-gate) + # vms-3320 (parent vms-b4f, blocks vms-fd1): the un-fakeable CRTL->RMS + # FILE-OP veneer proof -- open/creat/unlink/remove/rename/opendir/readdir/ + # closedir beyond the stdio family. Same VENEER path as crtl-rms-veneer-gate + # (JOINT_CRTL_RMS_VENEER=1) but the MILESTONE image is crtl_rms3_test.c: it + # creats FOPCRE.DAT, creats+unlinks FOPDEL.DAT, creats+renames FOPSRC.DAT-> + # FOPDST.DAT via the VECTOR-SUBSTITUTED decc$* file-ops (bound by sv# index + # to the crtl_rms_stdio.c veneer -> sys$create/$erase/$rename -> the ACP), + # leaving FOPCRE.DAT + FOPDST.DAT behind. The proof is an INDEPENDENT reader + # (DCL DIRECTORY over the ACP, a different accessor) seeing FOPCRE.DAT + + # FOPDST.DAT with genuine ODS-2 File IDs and FOPDEL.DAT/FOPSRC.DAT gone. + MILESTONE_MAIN=crtl_rms3_test.c + WANT_SENTINEL=7 + JOINT_CRTL_RMS_VENEER=1 + # Fault-capture: print the user PC of any fatal signal so a crash (e.g. the + # pre-existing veneer-build mallocng crash vms-c5d) can be mapped to a symbol + # (subtract the DECC$SHR +0x2c000 slide: file_off = VA - 0x20000000000 - 0x2c000). + export BOOT_APPEND_EXTRA="ignore_loglevel print-fatal-signals=1 loglevel=8" + + # Prove assert_fileop has teeth before trusting a green boot (mirrors the + # crtl-rms-veneer-gate selftest discipline: a can-fail gate certifies nothing). + _st=$(mktemp -d); _fails=0 + cat > "$_st/pass.log" <<'EOF' +OVMX CRTL/RMS3 file-op test: OK (open+creat+unlink+rename+opendir+readdir+closedir over RMS) argc=1 +OVMX-SEAM: image=JOINT_E2E.EXE stdcall_returned=1 has_exited=1 $STATUS=0x0035a039 +FILEOP-PROOF: === INDEPENDENT READER: DIRECTORY over the ACP (a DIFFERENT accessor) === +FILEOP-PROOF: --- created file FOPCRE.DAT (must be present) --- +FOPCRE.DAT;1 File ID: (21,1,0) +FILEOP-PROOF: CRE-STATUS=%X00000001 SEVERITY=1 +FILEOP-PROOF: --- renamed target FOPDST.DAT (must be present, genuine File ID) --- +FOPDST.DAT;1 File ID: (23,1,0) +FILEOP-PROOF: DST-STATUS=%X00000001 SEVERITY=1 +FILEOP-PROOF: --- unlinked file FOPDEL.DAT (must be GONE) --- +%DIRECT-W-NOFILES, no files found +FILEOP-PROOF: DEL-STATUS=%X00018292 SEVERITY=0 +FILEOP-PROOF: --- rename source FOPSRC.DAT (must be GONE) --- +%DIRECT-W-NOFILES, no files found +FILEOP-PROOF: SRC-STATUS=%X00018292 SEVERITY=0 +FILEOP-PROOF: === END INDEPENDENT READER === +EOF + # NEGATIVE 1: creat did NOT land (independent reader sees FOPCRE.DAT gone). FAIL. + cat > "$_st/nocre.log" <<'EOF' +FILEOP-PROOF: === INDEPENDENT READER: DIRECTORY over the ACP (a DIFFERENT accessor) === +FILEOP-PROOF: --- created file FOPCRE.DAT (must be present) --- +%DIRECT-W-NOFILES, no files found +FILEOP-PROOF: CRE-STATUS=%X00018292 SEVERITY=0 +FILEOP-PROOF: --- renamed target FOPDST.DAT (must be present, genuine File ID) --- +FOPDST.DAT;1 File ID: (23,1,0) +FILEOP-PROOF: DST-STATUS=%X00000001 SEVERITY=1 +FILEOP-PROOF: --- unlinked file FOPDEL.DAT (must be GONE) --- +%DIRECT-W-NOFILES, no files found +FILEOP-PROOF: --- rename source FOPSRC.DAT (must be GONE) --- +%DIRECT-W-NOFILES, no files found +FILEOP-PROOF: === END INDEPENDENT READER === +EOF + # NEGATIVE 2: unlink did NOT remove FOPDEL.DAT (reader still sees it). FAIL. + cat > "$_st/nodel.log" <<'EOF' +FILEOP-PROOF: === INDEPENDENT READER: DIRECTORY over the ACP (a DIFFERENT accessor) === +FILEOP-PROOF: --- created file FOPCRE.DAT (must be present) --- +FOPCRE.DAT;1 File ID: (21,1,0) +FILEOP-PROOF: --- renamed target FOPDST.DAT (must be present, genuine File ID) --- +FOPDST.DAT;1 File ID: (23,1,0) +FILEOP-PROOF: --- unlinked file FOPDEL.DAT (must be GONE) --- +FOPDEL.DAT;1 File ID: (22,1,0) +FILEOP-PROOF: --- rename source FOPSRC.DAT (must be GONE) --- +%DIRECT-W-NOFILES, no files found +FILEOP-PROOF: === END INDEPENDENT READER === +EOF + # NEGATIVE 3: activation load failure -> FAIL even if a stale region parsed. + cat > "$_st/imgact.log" <<'EOF' +%IMGACT-F-IMGNOTFND, image file not found LIBVMSRMS$SHR +FILEOP-PROOF: === INDEPENDENT READER: DIRECTORY over the ACP (a DIFFERENT accessor) === +FILEOP-PROOF: --- created file FOPCRE.DAT (must be present) --- +FOPCRE.DAT;1 File ID: (21,1,0) +FILEOP-PROOF: --- renamed target FOPDST.DAT (must be present, genuine File ID) --- +FOPDST.DAT;1 File ID: (23,1,0) +FILEOP-PROOF: --- unlinked file FOPDEL.DAT (must be GONE) --- +%DIRECT-W-NOFILES, no files found +FILEOP-PROOF: --- rename source FOPSRC.DAT (must be GONE) --- +%DIRECT-W-NOFILES, no files found +FILEOP-PROOF: === END INDEPENDENT READER === +EOF + echo "-- fileop selftest 1/4: clean independent-reader proof must PASS --" + if assert_fileop "$_st/pass.log" >/dev/null 2>&1; then echo " PASS"; else echo " FAIL: clean proof rejected"; _fails=$((_fails+1)); fi + echo "-- fileop selftest 2/4: creat did not land (FOPCRE gone) must FAIL --" + if assert_fileop "$_st/nocre.log" >/dev/null 2>&1; then echo " FAIL: accepted"; _fails=$((_fails+1)); else echo " PASS (rejected)"; fi + echo "-- fileop selftest 3/4: unlink no-op (FOPDEL still present) must FAIL --" + if assert_fileop "$_st/nodel.log" >/dev/null 2>&1; then echo " FAIL: accepted"; _fails=$((_fails+1)); else echo " PASS (rejected)"; fi + echo "-- fileop selftest 4/4: activation load failure must FAIL --" + if assert_fileop "$_st/imgact.log" >/dev/null 2>&1; then echo " FAIL: accepted"; _fails=$((_fails+1)); else echo " PASS (rejected)"; fi + rm -rf "$_st" + [ "$_fails" -eq 0 ] || die "fileop selftest failed -- assert_fileop cannot be trusted; aborting before the boot" + echo "" + + build_joint_images + assemble_boot_image + log "step 3: BOOT A -- activate the FILE-OP veneer image + run the INDEPENDENT DIRECTORY reader on the REAL executive" + run_boot_a + echo "" + echo "========================================================================" + echo "== vms-3320: CRTL->RMS FILE-OP veneer (open/creat/unlink/remove/rename/" + echo "== opendir/readdir/closedir) -> real ODS-2 effects, PROVEN by an INDEPENDENT" + echo "== ACP reader (DIRECTORY) on the real OVMX/Alpha executive (qemu-system-alpha" + echo "== + /dev/vms). Blocks vms-fd1 (the full alpha-dec-vms GCC port)." + echo "========================================================================" + grep -aE "FILEOP-PROOF:|OVMX CRTL/RMS3|OVMX-SEAM:|FOP...\.DAT|File ID:|%DIRECT|%IMGACT|%DCL-" "$WORK/modgpA.log" 2>/dev/null | sed 's/^/ | /' || true + echo "------------------------------------------------------------------------" + if assert_fileop "$WORK/modgpA.log"; then + echo "" + echo "PASS: the FILE-OP veneer-wired port image's decc\$open/creat/unlink/rename/" + echo " opendir/readdir/closedir genuinely reached the real Files-11 ODS-2 volume" + echo " over the ACP -- an INDEPENDENT reader (DCL DIRECTORY, a different accessor" + echo " than the writer's CRTL handle) saw FOPCRE.DAT + FOPDST.DAT with genuine ODS-2" + echo " File IDs and FOPDEL.DAT/FOPSRC.DAT GONE, which a ramfs/POSIX write can never" + echo " produce in the ACP directory. The 8 file-op decc\$ names bind by symbol-vector" + echo " INDEX to the veneer (mk_decc_shr.sh in-place substitution, sv# stable)." + exit 0 + fi + echo "" + echo "FAIL: the file-op veneer did NOT reach the real ODS-2 volume as expected (the" + echo " INDEPENDENT reader disagreed: a created/renamed file missing a File ID, or a" + echo " deleted/renamed-away file still present). Full log: $WORK/modgpA.log" + grep -aE "FILEOP-PROOF:|%IMGACT|%RUN-|%DCL-|IMGNOTFND|NOSUCHFILE|DEVNOTMOUNT|ACCVIO|%DIRECT|SS\\\$_" "$WORK/modgpA.log" 2>/dev/null | sed 's/^/ /' | tail -30 || echo " (none captured)" + echo "--- last 60 console lines ---" + tail -60 "$WORK/modgpA.log" 2>/dev/null | sed 's/^/ | /' || true + exit 1 + ;; shipped-gate) # vms-410: proves the Alpha shareable graph ships as part of the ORDINARY # build-alpha-bootimage.sh packaging path, not as something only THIS