// 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 #include 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; }