65816-llvm-mos/runtime/include/sys/stat.h
2026-07-07 18:33:48 -05:00

100 lines
4.1 KiB
C

// sys/stat.h -- file status for the GNO/ME runtime.
//
// struct stat MUST byte-match the layout the GNO kernel's stat.c writes
// (kern/gno/stat.c, compiled by ORCA/C with 16-bit int / 32-bit long).
// Kstat/Kfstat/Klstat (gno/kernel.h) fill this buffer directly, so any
// field-order or size drift silently corrupts every returned field. The
// _Static_assert below pins sizeof to the ORCA/C layout (54 bytes); the
// field offsets all land on even boundaries, so our 2-byte i32 alignment
// (datalayout i32:16) inserts no padding and matches ORCA/C's packing.
// (Verified: sizeof==54, offsetof(st_size)==16, st_mtime==26, st_blocks==42,
// matching the __GNO__ branch of tools/gno/src-repo/include/sys/stat.h.)
//
// Field semantics follow GNO's kernel: st_nlink/st_uid/st_gid/st_rdev are
// always 0, st_ino is a per-call fake, times are Unix epoch seconds, and
// st_mode carries the S_IF* type bits plus ProDOS-derived permission bits.
#ifndef _SYS_STAT_H_
#define _SYS_STAT_H_
#include <sys/types.h>
#include <time.h> // time_t (single source of truth)
#ifdef __cplusplus
extern "C" {
#endif
struct stat {
dev_t st_dev; // device number
ino_t st_ino; // (faked) inode number
unsigned short st_mode; // file type + permission bits
short st_nlink; // link count (always 0 under GNO)
uid_t st_uid; // owner uid (always 0)
gid_t st_gid; // owner gid (always 0)
dev_t st_rdev; // device type (always 0)
off_t st_size; // file size in bytes
time_t st_atime; // last access time (== mod time)
int st_spare1;
time_t st_mtime; // last modification time
int st_spare2;
time_t st_ctime; // creation / status-change time
int st_spare3;
long st_blksize; // preferred I/O block size (512)
long st_blocks; // 512-byte blocks allocated
long st_spare4[2];
};
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
_Static_assert(sizeof(struct stat) == 54, "struct stat must byte-match the GNO kernel layout");
#endif
// File type mask + type values (ProDOS/GS-OS mapped by the kernel).
#define S_IFMT 0170000 // type-of-file mask
#define S_IFIFO 0010000 // named pipe (fifo)
#define S_IFCHR 0020000 // character special (TTY / device)
#define S_IFDIR 0040000 // directory
#define S_IFBLK 0060000 // block special
#define S_IFREG 0100000 // regular file
#define S_IFLNK 0120000 // symbolic link
#define S_IFSOCK 0140000 // socket (GNO reports pipes as this)
// Permission bits.
#define S_ISUID 0004000 // set-user-id on execution
#define S_ISGID 0002000 // set-group-id on execution
#define S_ISVTX 0001000 // sticky bit
#define S_IRWXU 0000700 // RWX mask for owner
#define S_IRUSR 0000400 // R for owner
#define S_IWUSR 0000200 // W for owner
#define S_IXUSR 0000100 // X for owner
#define S_IREAD S_IRUSR
#define S_IWRITE S_IWUSR
#define S_IEXEC S_IXUSR
#define S_IRWXG 0000070 // RWX mask for group
#define S_IRGRP 0000040 // R for group
#define S_IWGRP 0000020 // W for group
#define S_IXGRP 0000010 // X for group
#define S_IRWXO 0000007 // RWX mask for other
#define S_IROTH 0000004 // R for other
#define S_IWOTH 0000002 // W for other
#define S_IXOTH 0000001 // X for other
// File-type test macros.
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
int stat(const char *path, struct stat *sb);
int fstat(int fd, struct stat *sb);
int lstat(const char *path, struct stat *sb);
#ifdef __cplusplus
}
#endif
#endif