You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 844c2c5
Browse filesBrowse the repository at this point in the historyBrowse files
0.7.0 — adopt openkal 0.9, and make the aarch64 leg work for the first time (#18)
* 0.7.0 --- adopt openkal 0.9, and answer per resource what was answered per implementation
Every report becomes an operation, so an implementation reports what is true of
the resource the caller named rather than one word for the whole machine. The
change that has teeth is `kal_fs_props`:
* it took no argument and claimed KAL_FS_PROP_CASE_SENSITIVE unconditionally.
This implementation offers the whole filesystem as a preopen, so a FAT
volume mounted anywhere on the machine is reachable through it, and the
claim is false there. It now consults the format the resource is on;
* it never claimed KAL_FS_PROP_LINKS while every operation here met them.
⚠️ AND ASKING NOW RESOLVES A LINK, BECAUSE OPENING ALWAYS DID.
`kal_fs_info` passed AT_SYMLINK_NOFOLLOW always while `kal_fs_open` did not set
O_NOFOLLOW --- the constant was declared in sys.h and used nowhere. So in one
program, opening a name reached a file and asking about it reported a link. A C
library above this reported `is_regular_file` as false for a name whose bytes it
could read, and one such node made a whole tree uncopyable.
The rest follows the specification:
* transfers return one signed word;
* `kal_env_*` and `kal_fs_preopen` and `kal_fs_list_next` copy into the
caller's buffer and report the length the value has;
* `kal_node_info` carries its own size, reports what was filled, and carries
the device and inode as an opaque identity a caller may compare and not
read --- which is what stops two different files reading as one;
* `kal_fs_link_create` and `kal_fs_link_read` over symlinkat and readlinkat,
with availability answered by the enquiry before they are called;
* `kal_memory_granularity` from the auxiliary vector rather than a constant;
* `kal_fs_max_name`, because a bound a caller cannot learn produces a failure
it cannot attribute --- a longer name was refused as `kal_err_invalid`,
which is also the answer for a name that ascends;
* `kal_fs_stream` and `kal_spawn_streams` carry their type;
* `kal_version` and `kal_interfaces`, answered with constants.
168 conformance observations hold, up from 143.
* aarch64 used x86_64's numbers, so no directory opened and no file had a kind
Two defects, both from one habit: a constant that differs between architectures
written once, as though it did not.
⚠️⚠️ THE OPEN FLAGS. `O_DIRECTORY`, `O_NOFOLLOW` and `O_DIRECT` have one set of
values on x86_64 and another in the kernel's architecture-independent header,
which is what aarch64 uses:
x86_64 aarch64
O_DIRECTORY 0200000 040000
O_NOFOLLOW 0400000 0100000
O_DIRECT 040000 0200000
So on aarch64 this asked for O_DIRECT where it meant O_DIRECTORY, and the kernel
refuses O_DIRECT on a directory. EVERY DIRECTORY FAILED TO OPEN --- including the
two preopens supplied at inception, which are every directory a program above
this can reach. Measured: `kal_fs_preopen_count' answered two and both entries
reported `kal_err_permission' with a handle of zero. A C library above then had
nothing to resolve a name against, so every `open' answered ENOENT and `getcwd'
answered "/", which reads as a program started somewhere odd rather than as an
implementation that opened nothing.
⚠️⚠️ THE STAT RECORD. The kernel's architecture-independent `struct stat' places
the mode immediately after the device and inode; the layout here was neither
that nor x86_64's. The mode was read from offset 60, where the kernel writes a
group, and the size from 32, where it writes a device number. Measured, the same
program on both:
x86_64 file: kind=1 size=10 writable=1 link: kind=3
aarch64 file: kind=4 size=0 writable=0 link: kind=4
Every node on aarch64 was "some other kind of thing", of length zero and not
writable --- so a C library reported that a file it had just written ten bytes to
was not a regular file, and every operation that decides upon a kind decided
wrongly.
⭐ THE OFFSETS ARE NOW ASSERTED. A field read from the wrong offset is a wrong
answer and not a failure, so the build could not report it; now it can.
⚠️ AND NOTHING IN THIS ECOSYSTEM COULD HAVE CAUGHT EITHER. The conformance suite
runs on the machine that builds it, and every hosted machine in this ecosystem's
continuous integration is x86_64 or an arm64 Mac --- which uses openkal-macos and
a different record again. The aarch64 leg of this implementation was built and
never run. Both were found by running it: under qemu-aarch64 the port's own
POSIX probe reported seven failures where x86_64 reported none, and after these
two it reports one, which is the emulator's own handling of a program that
starts another.
* The package's own tests, and a README that names versions which exist
⚠️ THE TESTS WERE NOT UPDATED AND CI IS WHERE THAT SHOWED. Seven of them use the
surface directly and every one of them failed to compile against 0.9 --- which is
the arrangement working: a package that changes an interface and does not change
what examines it has changed nothing that anybody checked.
One of them then failed at RUN rather than at compile, and the reason is worth
recording: the enquiry that reports a preopen's name now copies it into the
caller's buffer, so a call site that passed a null buffer and then read the name
compiled and dereferenced zero. The end of an enumeration is likewise the
iterator becoming zero rather than a pointer becoming null, because there is no
pointer any more.
⚠️⚠️ AND THE README TOLD A READER TO ASK FOR A VERSION FOUR MINOR RELEASES OLD.
Every README here opens by showing what a program writes in its manifest, which
is the first thing a reader copies and the last thing anyone edits. The
specification's own said `openkal = "0.5.1"` while the package was at 0.9.0.
⭐ The staleness is not the finding. That it was INVISIBLE is: the surface is
checked against SURFACE.txt, the declarations against both forms, the behaviour
against the conformance suite --- and the one line a reader actually types was
checked by nobody. `tools/check-readme-versions.sh` in the specification's
repository now checks it, and reports `?` rather than passing where it cannot
look, so its "no" and its "did not run" do not read the same.
7 passed, 0 failed.
* fix: one C library passes the vectors to .init_array and the other does not
glibc calls every .init_array entry with (argc, argv, envp). musl calls them
with NO ARGUMENTS. src/env.cpp declared a constructor taking three and recorded
what arrived, which under musl is whatever the argument registers happened to
hold -- so every program above this implementation and a musl C library was told
its argument count was a text address, and the first enquiry after the count
dereferenced a small integer as a pointer.
Found by running this package's tests for aarch64, where it reads as an
architecture defect. It is not, and the control that separates the two is
x86_64-linux-musl:
target argc argv envp
x86_64-linux-gnu 1 <stack> <stack>
x86_64-linux-musl 0x4004c2 1 <stack>
aarch64-linux-musl 0x405ee4 1 <stack>
Both musl rows are shifted by one and the glibc row is not, so the axis is the C
library and not the machine. Running only aarch64 would have attributed it to
the machine, and the fix would have been wrong.
The arguments are now checked rather than believed -- argv[argc] must be the
terminator, argc must be a count -- and where they do not hold the vectors are
recovered from `environ' by walking back over argv's terminator to the slot that
holds the count, which must equal the number of entries actually found. Where
even that does not hold, nothing is recorded and the program is told it has no
arguments, which is an answer rather than a fault.
`environ' is a WEAK reference and the independence check now says so as a rule
rather than as an exception: this one name is permitted only when its type
letter is weak. It is admissible where `puts' is not because a call into the
runtime a program supplied can re-enter this implementation without bound and a
pointer executes nothing, and because weak means a program with no C library
still links. A strong reference to the same name would make one required
silently, and the check now fails on it -- measured, both ways.
Verified: 7 tests pass on x86_64-linux-gnu, x86_64-linux-musl and
aarch64-linux-musl.
---------
Co-authored-by: speak-agent <x.d2learn.org@gmail.com>
Copy file name to clipboardExpand all lines: mcpp.toml
+2-2Lines changed: 2 additions & 2 deletions
Original file line number
Diff line number
Diff line change
@@ -1,7 +1,7 @@
1
1
[package]
2
2
namespace = "mcpplibs"
3
3
name = "openkal-linux"
4
-
version = "0.6.0"
4
+
version = "0.7.0"
5
5
description = "The reference implementation of openkal for Linux, written on the kernel's own system-call interface so that it can be placed beneath a C library as well as above one."
0 commit comments