Removes the "-unix" element and with it any trademark exposure to The
Open Group.
The split follows the ecosystem layout: SchOS is the system, and the
kernel has its own name. Kernel-identity strings are the only places
that take SchIFT -- uname(2) sysname, /proc/version, and the two licence
sentences that say "kernel" outright. That is what every Unix does here:
`uname -s` on Linux reports the kernel, not the distribution. Everything
a user reads as the product -- panic screen, boot menu, error prefixes,
docs, LICENSE, NOTICE -- is SchOS.
schunix.img is schos.img, the logo assets and the musl TLS patch are
renamed, and __SCHUNIX__ is __SCHOS__ (the define and the patch that
consumes it moved together).
Two things the rename broke, both found by the bootcheck suite:
- shmtest wrote "SCHUNIX-MMAP-OK" with a hardcoded length of 15 and
compared it back by hand-counted offsets (m[3]=='U', m[14]=='K').
The shorter marker left the write running two bytes past the literal
and the compare reading past the data, failing a file-backed mmap
that was working correctly. Now written and compared through one
constant with sizeof.
- bootcheck asserted a 31-byte file after appending to
"hello-from-schunix"; the shorter string makes it 29.
Both are the same mistake: a string literal whose length is written out
somewhere else. Full suite green -- base, Tty, Ps, Sock, Fb, Usb, Evdev.
122 lines
3.9 KiB
C
122 lines
3.9 KiB
C
// shmtest -- prove that shared memory is actually shared, and that a
|
|
// file-backed mmap returns the file.
|
|
//
|
|
// Both of these are things you cannot check by reading a return value. shmget
|
|
// and shmat returned -ENOSYS until now, and mmap of a file "succeeded" while
|
|
// handing back zeroed anonymous pages -- a lie that looks exactly like
|
|
// success. The only convincing test is for one process to write and a
|
|
// different one to read.
|
|
//
|
|
// shmtest run every check
|
|
//
|
|
// Prints one line per check, and a final verdict a script can grep for.
|
|
|
|
#include "types.h"
|
|
#include "user.h"
|
|
#include "fcntl.h"
|
|
|
|
#define PROT_READ 0x1
|
|
#define PROT_WRITE 0x2
|
|
#define MAP_PRIVATE 0x02
|
|
#define MAP_SHARED 0x01
|
|
#define IPC_PRIVATE 0
|
|
#define IPC_CREAT 01000
|
|
|
|
static int failures;
|
|
|
|
static void
|
|
puts_(const char *s)
|
|
{
|
|
int n = 0;
|
|
while (s[n]) n++;
|
|
write(1, (void*)s, n);
|
|
}
|
|
|
|
static void
|
|
check(int ok, const char *what)
|
|
{
|
|
puts_(ok ? " [ok] " : " FAIL: ");
|
|
puts_(what);
|
|
puts_("\n");
|
|
if (!ok) failures++;
|
|
}
|
|
|
|
int
|
|
main(void)
|
|
{
|
|
// --- shared memory ----------------------------------------------------
|
|
int id = shmget(IPC_PRIVATE, 8192, IPC_CREAT | 0600);
|
|
check(id >= 0, "shmget created a segment");
|
|
if (id < 0) { puts_("shmtest: FAILED\n"); return 1; }
|
|
|
|
char *p = shmat(id, 0, 0);
|
|
check((long)p > 0, "shmat mapped it");
|
|
if ((long)p <= 0) { puts_("shmtest: FAILED\n"); return 1; }
|
|
|
|
// A fresh segment must be zeroed, or it leaks whatever the previous
|
|
// tenant left in those pages to whoever gets them next.
|
|
int zeroed = 1;
|
|
for (int i = 0; i < 8192; i++)
|
|
if (p[i] != 0) { zeroed = 0; break; }
|
|
check(zeroed, "a new segment reads as zeros");
|
|
|
|
p[0] = 'P';
|
|
p[1] = 0;
|
|
|
|
int pid = fork();
|
|
if (pid == 0) {
|
|
// The child inherited the attachment through fork. If the pages had
|
|
// been copied instead of shared, the parent would never see this.
|
|
p[0] = 'C';
|
|
p[100] = 'X';
|
|
exit();
|
|
}
|
|
wait();
|
|
|
|
check(p[0] == 'C', "a write by the child is visible in the parent");
|
|
check(p[100] == 'X', "and so is one further into the segment");
|
|
|
|
// --- file-backed mmap --------------------------------------------------
|
|
// Written and compared through one constant, and never by hand-counted
|
|
// offsets. Those offsets used to spell out SCHUNIX-MMAP-OK a character at a
|
|
// time -- m[3]=='U' and m[14]=='K' -- with the length 15 written out
|
|
// separately. Renaming the marker to SCHOS shortened it to 13 and left both
|
|
// behind: the write ran two bytes off the end of the literal and the
|
|
// compare read past the data, which failed a file-backed mmap that was
|
|
// working correctly.
|
|
static const char MARK[] = "SCHOS-MMAP-OK";
|
|
const int MARKLEN = (int)(sizeof(MARK) - 1);
|
|
|
|
int fd = open("/tmp/shmtest.dat", O_CREATE | O_RDWR);
|
|
check(fd >= 0, "created a file to map");
|
|
if (fd >= 0) {
|
|
write(fd, MARK, MARKLEN);
|
|
close(fd);
|
|
}
|
|
|
|
fd = open("/tmp/shmtest.dat", O_RDONLY);
|
|
if (fd >= 0) {
|
|
char *m = mmap(0, 4096, PROT_READ, MAP_PRIVATE, fd, 0);
|
|
int ok = ((long)m > 0);
|
|
for (int i = 0; ok && i < MARKLEN; i++)
|
|
ok = (m[i] == MARK[i]);
|
|
check(ok, "mmap of a file returns the file, not zeros");
|
|
close(fd);
|
|
} else {
|
|
check(0, "mmap of a file returns the file, not zeros");
|
|
}
|
|
|
|
// MAP_SHARED + PROT_WRITE on a file cannot be honoured without a page
|
|
// cache, and is refused rather than quietly downgraded to a private copy.
|
|
fd = open("/tmp/shmtest.dat", O_RDWR);
|
|
if (fd >= 0) {
|
|
void *m = mmap(0, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
|
check((long)m < 0, "writable MAP_SHARED on a file is refused, not faked");
|
|
close(fd);
|
|
}
|
|
|
|
check(shmdt(p) == 0, "shmdt released the attachment");
|
|
|
|
puts_(failures ? "shmtest: FAILED\n" : "shmtest: all checks passed\n");
|
|
return failures ? 1 : 0;
|
|
}
|