164 lines
8.2 KiB
C++
164 lines
8.2 KiB
C++
#ifndef FROSTBYTE_FS_H
|
|
#define FROSTBYTE_FS_H
|
|
|
|
#define oReadOnly 0x0
|
|
#define oWriteOnly 0x1
|
|
#define oReadWrite 0x2
|
|
#define oCreate 0x40
|
|
#define oTrunc 0x200
|
|
#define oAppend 0x400
|
|
|
|
#define seekSet 0
|
|
#define seekCur 1
|
|
#define seekEnd 2
|
|
|
|
#define fsTypeFile 1
|
|
#define fsTypeDir 2
|
|
#define fsTypeFifo 3
|
|
|
|
/* Real POSIX permission bits (chmod(2)/open(2)'s access check). This kernel
|
|
now has a real (if minimal) uid AND gid model -- sched.h's Thread.uid/
|
|
Thread.gid, vfs.c's vfsPermitted -- so all three (owner/group/other)
|
|
triads are genuinely stored AND enforced. A mode value like 0750 is
|
|
accepted and echoed back by vfsStat/userStat exactly as given. Enforced
|
|
at exactly two real choke points, both uid+gid-aware via vfsPermitted:
|
|
resolveOpen (vfs.c) refuses to open an existing file for writing without
|
|
the right write bit for the CALLING thread's identity, and
|
|
loadImageByPath/jobctlSpawn (syscall.c/jobctl.c) refuse to exec a file
|
|
without the right exec bit -- both real, both checked at open/spawn time
|
|
only, never re-checked against an fd/process already granted (matching
|
|
real Unix). Deliberately no uid-0-bypasses-everything superuser rule
|
|
like real Unix's root has -- see vfs.c's vfsPermitted doc comment for
|
|
why a from-scratch bypass would have silently broken every permission
|
|
test already relying on chmod denying write even to a file's own
|
|
creator (every boot-time process starts at uid 0). */
|
|
#define fsModeOwnerRead 0400u
|
|
#define fsModeOwnerWrite 0200u
|
|
#define fsModeOwnerExec 0100u
|
|
|
|
/* The "group" triad -- vfsPermitted's middle fallback, consulted once a
|
|
caller's uid fails to match a node's owner uid but its GID (sched.h's
|
|
Thread.gid) matches the node's own group gid (fs.h's FbStat.gid). Each
|
|
bit is its own owner bit shifted right by 3 (real Unix's own rwxrwxrwx
|
|
bit layout: owner at bits 8-6, group at bits 5-3, other at bits 2-0),
|
|
the same derivation fsModeOther* below already used for the next shift
|
|
down -- vfsPermitted computes both from wantOwnerBit rather than storing
|
|
six separate constants per permission. */
|
|
#define fsModeGroupRead 0040u
|
|
#define fsModeGroupWrite 0020u
|
|
#define fsModeGroupExec 0010u
|
|
|
|
/* The "other" (neither owner nor group) triad -- vfsPermitted's final
|
|
fallback once a caller's uid AND gid both fail to match. Numerically each
|
|
is its own owner bit shifted right by 6, matching the 6-bit gap between
|
|
the owner and other triads in a real Unix mode. */
|
|
#define fsModeOtherRead 0004u
|
|
#define fsModeOtherWrite 0002u
|
|
#define fsModeOtherExec 0001u
|
|
|
|
/* Defaults applied at creation time (never retroactive -- an existing
|
|
file's mode never changes on its own, only through chmod). Directory
|
|
mode bits are stored and reported by stat/ls -l but never enforced: this
|
|
kernel's existing per-node `writable` (tmpfs) / dir-emptiness (SFS) gates
|
|
already govern directory mutation, a second, redundant enforcement axis
|
|
was not worth the complexity for a case no test needs. */
|
|
#define fsModeDefaultFile 0644u
|
|
#define fsModeDefaultDir 0755u
|
|
#define fsModeDefaultExec 0755u
|
|
|
|
/* sysMmap's `prot` argument (ulib.h's userMmap) -- POSIX PROT_NONE/READ/
|
|
WRITE/EXEC by shape. mmapProtExec IS real and hardware-enforced
|
|
(mmapFaultHandler, mmap.c, maps every page of a Vma missing this bit
|
|
with paging.h's pageNoExecute): jumping into a mapping that never asked
|
|
for it takes a real, catchable SIGSEGV (isr.c's I/D-bit short-circuit in
|
|
tryResolveUserPageFault), never silently succeeds -- WHEN
|
|
paging.h's pagingNxSupported() is true (boot.S enables IA32_EFER.NXE
|
|
only after confirming CPUID.80000001H:EDX.NX; unsupported hardware
|
|
silently keeps every mapping executable rather than write a reserved PTE
|
|
bit, the same honest best-effort this codebase already applies
|
|
elsewhere). This mechanism is not limited to mmap: elf.c's own loader
|
|
now maps each ELF program header with the same paging.h flags, derived
|
|
from that segment's own p_flags (elfSegmentPagingFlags) -- a binary's
|
|
.text/.rodata comes up read-only+executable, its .data/.bss read-write+
|
|
non-executable (user/user.ld emits them as two separate PT_LOAD
|
|
segments precisely so they can get different flags), and the
|
|
fixed-size stack and brk heap (kmain.c/syscall.c/jobctl.c/sched.c) still
|
|
ask pagingMapUserRangeFlags for pageNoExecute explicitly the same way
|
|
they always have. mmapProtWrite IS also real and enforced
|
|
(mmapFaultHandler, mmap.c): a write fault against a mapping missing this
|
|
bit is refused and turns into a real SIGSEGV (isr.c), never silently
|
|
allowed -- the same real enforcement elf.c's own read-only .text/.rodata
|
|
segments now get too (user/elfwritevictim.c). */
|
|
#define mmapProtNone 0x0
|
|
#define mmapProtRead 0x1
|
|
#define mmapProtWrite 0x2
|
|
#define mmapProtExec 0x4
|
|
|
|
/* sysMmap's `flags` argument -- MAP_ANONYMOUS-equivalent: fd/offset are
|
|
ignored and every page is demand-zero-filled instead of read from a file
|
|
(mmap.c's mmapFaultHandler). There is no MAP_SHARED bit: every mapping
|
|
here behaves like MAP_PRIVATE (a file-backed page's own frame is this
|
|
mapping's alone -- writing to it, when mmapProtWrite allows that, never
|
|
writes back to the underlying file, exactly like a real MAP_PRIVATE
|
|
mapping's own copy-on-write semantics, just without ever actually
|
|
sharing the frame with the file cache to begin with, since this kernel
|
|
has none), so the file-backed default already gets MAP_PRIVATE's own
|
|
behavior without a second flag bit to ask for it. */
|
|
#define mmapAnonymous 0x1
|
|
|
|
#define fsNameMax 64
|
|
|
|
/* Shared cap for a full path string (as opposed to fsNameMax's single
|
|
component): sched.h's Thread.cwd, vfs.h's vfsResolvePath/vfsGetcwd, and
|
|
every syscall.c path-copying stack buffer (sysOpen/sysMkdir/sysChdir/...)
|
|
all use this same constant, so a path that fits one always fits the
|
|
other -- shell.c's own longstanding local pathCapacity used the same 256
|
|
value before this constant existed. */
|
|
#define fsPathMax 256
|
|
|
|
typedef struct FbStat {
|
|
unsigned long size;
|
|
unsigned int type;
|
|
/* Real owner rwx permission bits (see fsModeOwner* above) for a tmpfs
|
|
or SFS node -- a synthetic 0666/0444 derived from `writable` before
|
|
chmod(2) existed, now the actual per-node value. Always 0666 for
|
|
/dev/disk0 (no real per-file mode concept for a raw block device,
|
|
an honest, never-enforced placeholder, unlike the file/dir case). */
|
|
unsigned int mode;
|
|
/* Real owner identity (POSIX uid): the sched.h Thread.uid value that
|
|
was current at creation time for a tmpfs or SFS node -- see vfs.c's
|
|
vfsUid/sfs.h's sfsUidOf, the same accessors vfsPermitted itself reads
|
|
to decide owner-vs-other access. Never retroactive at creation time,
|
|
like mode's own default, and never changed by chmod -- only a real
|
|
vfsChown (root-only, real Unix's _POSIX_CHOWN_RESTRICTED default) can
|
|
reassign it afterward. Always 0 ("root") for /dev/disk0 and the in-memory
|
|
tmpfs root itself, mirroring mtime/ctime's own "0 means never
|
|
tracked" placeholder immediately below for cases with no real
|
|
creation event of their own. */
|
|
unsigned int uid;
|
|
/* Real group identity (POSIX gid): the sched.h Thread.gid value that was
|
|
current at creation time for a tmpfs or SFS node -- see vfs.c's
|
|
vfsGid/sfs.h's sfsGidOf, the same accessors vfsPermitted itself reads
|
|
to decide the group branch of owner-vs-group-vs-other access. Never
|
|
retroactive at creation time, like uid's own default, and never
|
|
changed by chmod -- only vfsChgrp (owner may only set it to their OWN
|
|
current gid, root may set it to anything, see vfs.c's vfsChgrp doc
|
|
comment) can reassign it afterward. Always 0 for /dev/disk0 and the
|
|
in-memory tmpfs root itself, mirroring uid's own placeholder. */
|
|
unsigned int gid;
|
|
/* Real wall-clock timestamps (seconds since the Unix epoch, rtc.h's
|
|
rtcNow()) for an SFS ("/mnt") inode -- see sfs.h's sfsMtimeOf/
|
|
sfsCtimeOf. Always 0 for the in-memory tmpfs tree and /dev/disk0,
|
|
which have never tracked time (documented gap, not a faked value). */
|
|
unsigned long mtime;
|
|
unsigned long ctime;
|
|
} FbStat;
|
|
|
|
typedef struct FbDirent {
|
|
unsigned int type;
|
|
unsigned int nameLength;
|
|
char name[fsNameMax];
|
|
} FbDirent;
|
|
|
|
#endif
|