65816-llvm-mos/demos/gnoStatProbe.c
2026-07-07 18:33:48 -05:00

72 lines
2.2 KiB
C

// stat/fstat/isatty regression for the GNO libc file-status surface.
//
// Exercises the three K* status primitives (Kstat/Kfstat 0x2703/0x2803)
// through their POSIX wrappers in libcGno.c, plus isatty() built on
// fstat. The hard part these wrappers get right is struct stat's
// byte-layout: the GNO kernel (kern/gno/stat.c, ORCA/C) writes the buffer
// directly, so if runtime/include/sys/stat.h drifts by even one field the
// S_IF* type bits land in the wrong word and every test below flips.
//
// The program is launched at the gsh prompt with stdout on the console
// TTY, so:
// - fstat(1) succeeds and st_mode is a character special (the TTY).
// - isatty(1) is therefore true.
// - stat(".") on the login cwd is a directory.
// All deterministic (no pids / addresses / times inspected).
//
// Bank-2 absolute uint16 markers (DBR-independent), per the gnoHeapProbe
// convention:
// 0x025000 C0DE reached end (no hang in any stat path)
// 0x025010 0001 fstat(1) returned 0
// 0x025012 0001 S_ISCHR(fstat st_mode) -- stdout is a char device
// 0x025014 0001 isatty(1) == 1
// 0x025016 0001 stat(".") returned 0
// 0x025018 0001 S_ISDIR(stat st_mode) -- cwd is a directory
#include <stdint.h>
#include <sys/stat.h>
extern int isatty(int fd);
#define M(a) (*(volatile uint16_t *)(a))
#define OK 0x0001
#define BAD 0xDEAD
int main(void) {
struct stat sb;
int rc;
M(0x025010UL) = BAD;
M(0x025012UL) = BAD;
M(0x025014UL) = BAD;
M(0x025016UL) = BAD;
M(0x025018UL) = BAD;
// fstat(1): stdout, which the harness leaves on the console TTY.
rc = fstat(1, &sb);
if (rc == 0) {
M(0x025010UL) = OK;
}
if (S_ISCHR(sb.st_mode)) {
M(0x025012UL) = OK;
}
// isatty(1): true because stdout is a character device.
if (isatty(1) == 1) {
M(0x025014UL) = OK;
}
// stat("."): the login cwd, which is a directory.
rc = stat(".", &sb);
if (rc == 0) {
M(0x025016UL) = OK;
}
if (S_ISDIR(sb.st_mode)) {
M(0x025018UL) = OK;
}
M(0x025000UL) = 0xC0DE; // reached end
for (volatile unsigned long j = 0; j < 600000UL; j++) {
}
return 0;
}