feat: POSIX libc surface, native binutils (as/ld/ar run on MontaukOS)
Grow the Montauk libc enough to cross-build binutils 2.43.1 with --host=x86_64-montauk. gas, ld, ar, nm, objcopy, objdump, readelf, ranlib, strip and friends now link as native ET_EXEC Montauk binaries (staged stripped in toolchain/native/, not yet shipped in the image). New libc surface: full Linux errno and signal sets, O_* flags with real O_EXCL/O_APPEND semantics, unlink/rmdir/dup/dup2/getpid/_exit, kill (SYS_KILL), fcntl, fileno/fdopen, putc/getchar/rewind, ctime/asctime, strtoll/strtoull/atoll, bsearch, mkstemp/mktemp, realpath (lexical, drive-prefix aware), mbstowcs/mblen, chmod/fchmod/ umask/utime no-ops (VFS has no modes or settable times), full struct stat with fake inodes, sscanf field widths (bounded conversions), SCN*/PRI* completions, wait/waitpid over SYS_WAITPID, and new headers sys/wait.h, sys/param.h, utime.h, wchar.h, memory.h. fork/exec/pipe are declared but fail with ENOSYS: binutils never spawns, and real process plumbing is the posix_spawn milestone, which needs kernel support (exit status reporting, fd redirection). TCC's montauk_compat.h shims (unlink, chmod, execvp, realpath, fdopen, strtoll, strtoull) are retired in favor of the libc versions. Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
@@ -2,83 +2,20 @@
|
||||
* montauk_compat.h
|
||||
* POSIX compatibility shims for TCC on MontaukOS
|
||||
* Copyright (c) 2026 Daniel Hammer
|
||||
*
|
||||
* Historical note: this header used to carry static fallbacks for
|
||||
* unlink/chmod/execvp/realpath/fdopen before the Montauk libc grew
|
||||
* them (native binutils port). It is now a thin passthrough.
|
||||
*/
|
||||
|
||||
#ifndef MONTAUK_COMPAT_H
|
||||
#define MONTAUK_COMPAT_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* getcwd is provided by libc now */
|
||||
char *getcwd(char *buf, size_t size);
|
||||
|
||||
/* chmod - no-op on MontaukOS */
|
||||
static inline int chmod(const char *path, unsigned int mode) {
|
||||
(void)path; (void)mode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* close (provided by libc) */
|
||||
int close(int fd);
|
||||
|
||||
/* lseek - provided by libc, tracks fd positions */
|
||||
long lseek(int fd, long offset, int whence);
|
||||
|
||||
/* realpath - just return a copy of the path */
|
||||
static inline char *realpath(const char *path, char *resolved) {
|
||||
if (path == NULL) return NULL;
|
||||
if (resolved == NULL) {
|
||||
size_t len = 0;
|
||||
const char *p = path;
|
||||
while (*p++) len++;
|
||||
resolved = (char*)malloc(len + 1);
|
||||
if (!resolved) return NULL;
|
||||
}
|
||||
{
|
||||
const char *s = path;
|
||||
char *d = resolved;
|
||||
while ((*d++ = *s++));
|
||||
}
|
||||
return resolved;
|
||||
}
|
||||
|
||||
/* dlfcn stubs not needed -- TCC_IS_NATIVE is disabled for MontaukOS */
|
||||
|
||||
/* ====================================================================
|
||||
ssize_t (used in tccelf.c)
|
||||
==================================================================== */
|
||||
|
||||
#ifndef _SSIZE_T_DEFINED
|
||||
#define _SSIZE_T_DEFINED
|
||||
typedef long ssize_t;
|
||||
#endif
|
||||
|
||||
/* ====================================================================
|
||||
POSIX I/O (provided by libc)
|
||||
==================================================================== */
|
||||
|
||||
int read(int fd, void *buf, size_t count);
|
||||
int write(int fd, const void *buf, size_t count);
|
||||
|
||||
/* unlink = remove */
|
||||
static inline int unlink(const char *path) {
|
||||
return remove(path);
|
||||
}
|
||||
|
||||
/* fdopen - MontaukOS doesn't have fd-to-FILE conversion.
|
||||
TCC uses fdopen after creating a file with open().
|
||||
We return NULL and let TCC fall back to error path,
|
||||
or we can use a workaround. */
|
||||
FILE *fdopen(int fd, const char *mode);
|
||||
|
||||
/* ====================================================================
|
||||
Process stubs
|
||||
==================================================================== */
|
||||
|
||||
static inline int execvp(const char *file, char *const argv[]) {
|
||||
(void)file; (void)argv;
|
||||
return -1;
|
||||
}
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#endif /* MONTAUK_COMPAT_H */
|
||||
|
||||
@@ -40,40 +40,8 @@ static inline long _sys2(long nr, long a1, long a2) {
|
||||
#define SYS_GETSIZE 8
|
||||
#define SYS_GETARGS 25
|
||||
|
||||
/* ====================================================================
|
||||
fdopen - wrap a raw fd in a FILE (needed by tccelf.c)
|
||||
==================================================================== */
|
||||
|
||||
FILE *fdopen(int fd, const char *mode) {
|
||||
(void)mode;
|
||||
if (fd < 0) return NULL;
|
||||
|
||||
unsigned long fileSize = (unsigned long)_sys1(SYS_GETSIZE, (long)fd);
|
||||
|
||||
FILE *f = (FILE *)malloc(sizeof(FILE));
|
||||
if (f == NULL) return NULL;
|
||||
|
||||
f->handle = fd;
|
||||
f->pos = 0;
|
||||
f->size = fileSize;
|
||||
f->eof = 0;
|
||||
f->error = 0;
|
||||
f->is_std = 0;
|
||||
f->ungetc_buf = -1;
|
||||
return f;
|
||||
}
|
||||
|
||||
/* ====================================================================
|
||||
strtoll / strtoull (needed by TCC, not in MontaukOS libc)
|
||||
==================================================================== */
|
||||
|
||||
long long strtoll(const char *nptr, char **endptr, int base) {
|
||||
return (long long)strtol(nptr, endptr, base);
|
||||
}
|
||||
|
||||
unsigned long long strtoull(const char *nptr, char **endptr, int base) {
|
||||
return (unsigned long long)strtoul(nptr, endptr, base);
|
||||
}
|
||||
/* fdopen, strtoll and strtoull used to be defined here; they moved
|
||||
into the Montauk libc with the native binutils port. */
|
||||
|
||||
/* ====================================================================
|
||||
_start entry point
|
||||
|
||||
Reference in New Issue
Block a user