ffi/libc: implement chdir, errno, strerror
Smallest Phase 0 module per CLAUDE.md §4 implementation order.
M.chdir(path) returns (true) or (false, errmsg) — errmsg via
strerror(__errno_location()[0]). Glibc errno is thread-local
behind __errno_location() rather than a plain global, hence the
indirect access.
Verified against PHASE0.md §7 expectation: a libc.chdir() persists
across subsequent io.popen() calls (popen's child inherits the
parent's wd), which is the property executor.lua relies on for `cd`
interception. Smoke:
libc.chdir("/tmp"); io.popen("pwd"):read("*l") --> /tmp
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+18
-3
@@ -1,18 +1,33 @@
|
||||
-- ffi/libc.lua — shared libc bindings: errno, signal, write, read, chdir.
|
||||
-- ffi/libc.lua — shared libc bindings: chdir, errno, strerror.
|
||||
-- Phase 0: just enough to make `cd` interception work in executor.lua.
|
||||
-- See docs/PHASE0.md §7.
|
||||
|
||||
local ffi = require("ffi")
|
||||
|
||||
ffi.cdef[[
|
||||
int chdir(const char *path);
|
||||
int errno;
|
||||
int *__errno_location(void);
|
||||
char *strerror(int errnum);
|
||||
]]
|
||||
|
||||
local C = ffi.C
|
||||
|
||||
local M = {}
|
||||
|
||||
-- Apply chdir per PHASE0.md §7 (intercepts `cd` so wd persists across popen).
|
||||
-- Returns: true on success; false, errmsg on failure.
|
||||
function M.chdir(path)
|
||||
error("libc.chdir: not implemented (Phase 0 pending)")
|
||||
local rc = C.chdir(path)
|
||||
if rc == 0 then return true end
|
||||
return false, ffi.string(C.strerror(C.__errno_location()[0]))
|
||||
end
|
||||
|
||||
function M.errno()
|
||||
return C.__errno_location()[0]
|
||||
end
|
||||
|
||||
function M.strerror(en)
|
||||
return ffi.string(C.strerror(en))
|
||||
end
|
||||
|
||||
return M
|
||||
|
||||
Reference in New Issue
Block a user