1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286
|
-- This mirrors syscall.lua, but some differences
local require, error, assert, tonumber, tostring,
setmetatable, pairs, ipairs, unpack, rawget, rawset,
pcall, type, table, string =
require, error, assert, tonumber, tostring,
setmetatable, pairs, ipairs, unpack, rawget, rawset,
pcall, type, table, string
local ffi = require "ffi"
local abi = require "syscall.abi"
abi.rump = true
local modules = {
rump = ffi.load("rump", true),
rumpuser = ffi.load("rumpuser", true),
}
_G[{}] = modules -- if you unload rump kernel crashes are likely, so hang on to them
local unchanged = {
char = true,
int = true,
long = true,
unsigned = true,
["unsigned char"] = true,
["unsigned int"] = true,
["unsigned long"] = true,
int8_t = true,
int16_t = true,
int32_t = true,
int64_t = true,
intptr_t = true,
uint8_t = true,
uint16_t = true,
uint32_t = true,
uint64_t = true,
uintptr_t = true,
-- same in all OSs at present
in_port_t = true,
uid_t = true,
gid_t = true,
pid_t = true,
off_t = true,
size_t = true,
ssize_t = true,
socklen_t = true,
["struct in_addr"] = true,
["struct in6_addr"] = true,
["struct iovec"] = true,
["struct iphdr"] = true,
["struct udphdr"] = true,
["struct ethhdr"] = true,
["struct winsize"] = true,
["struct {int count; struct iovec iov[?];}"] = true,
}
local function rumpfn(tp)
if unchanged[tp] then return tp end
if tp == "void (*)(int, siginfo_t *, void *)" then return "void (*)(int, _netbsd_siginfo_t *, void *)" end
if tp == "struct {dev_t dev;}" then return "struct {_netbsd_dev_t dev;}" end
if tp == "struct {timer_t timerid[1];}" then return "struct {_netbsd_timer_t timerid[1];}" end
if tp == "union sigval" then return "union _netbsd_sigval" end
if tp == "struct {int count; struct mmsghdr msg[?];}" then return "struct {int count; struct _netbsd_mmsghdr msg[?];}" end
if string.find(tp, "struct") then
return (string.gsub(tp, "struct (%a)", "struct _netbsd_%1"))
end
return "_netbsd_" .. tp
end
local S
if abi.types == "linux" then -- load Linux compat module
modules.rumpvfs = ffi.load("rumpvfs", true)
modules.rumpnet = ffi.load("rumpnet", true)
modules.rumpnetnet = ffi.load("rumpnet_net", true)
modules.rumpcompat = ffi.load("rumpkern_sys_linux", true)
end
abi.rumpfn = nil
if abi.host == "netbsd" and abi.types == "netbsd" then -- running native (NetBSD on NetBSD)
local SS = require "syscall"
local C = require "syscall.rump.c"
S = require "syscall.syscalls".init(C, SS.c, SS.types)
S.abi, S.c, S.types, S.t = abi, SS.c, SS.types, SS.types.t
S = require "syscall.compat".init(S)
S = require "syscall.methods".init(S)
S.util = require "syscall.util".init(S)
elseif abi.types == "linux" then -- running Linux types, just need to use rump C which it will do if abi.rump set
S = require "syscall"
-- TODO lots of syscalls simply don't exist, so make some do ENOSYS
local function nosys()
ffi.errno(S.c.E.NOSYS)
return -1
end
local C = require "syscall.rump.c"
local nolist = {"io_setup"} -- TODO can add more here
for _, sys in ipairs(nolist) do C[sys] = nosys end
-- add a few netbsd types so can use mount
-- TODO ideally we would require netbsd.ffitypes but this is somewhat complex now
ffi.cdef [[
typedef uint32_t _netbsd_mode_t;
typedef uint64_t _netbsd_ino_t;
struct _netbsd_ufs_args {
char *fspec;
};
struct _netbsd_tmpfs_args {
int ta_version;
_netbsd_ino_t ta_nodes_max;
off_t ta_size_max;
uid_t ta_root_uid;
gid_t ta_root_gid;
_netbsd_mode_t ta_root_mode;
};
struct _netbsd_ptyfs_args {
int version;
gid_t gid;
_netbsd_mode_t mode;
int flags;
};
]]
local addtype = require "syscall.helpers".addtype
local addstructs = {
ufs_args = "struct _netbsd_ufs_args",
tmpfs_args = "struct _netbsd_tmpfs_args",
ptyfs_args = "struct _netbsd_ptyfs_args",
}
for k, v in pairs(addstructs) do addtype(S.types, k, v, {}) end
elseif abi.types == "netbsd" then -- run NetBSD types on another OS
abi.rumpfn = rumpfn -- mangle NetBSD type names to avoid collisions
S = require "syscall"
else
error "unsupported ABI"
end
require "syscall.rump.ffirump"
local t, pt = S.types.t, S.types.pt
local modinfo = ffi.typeof("struct modinfo")
-- TODO make this explcitly refer to NetBSD error codes
local function retbool(ret)
if ret == -1 then return nil, t.error() end
return true
end
local function retnum(ret) -- return Lua number where double precision ok, eg file ops etc
ret = tonumber(ret)
if ret == -1 then return nil, t.error() end
return ret
end
S.rump = {}
local h = require "syscall.helpers"
local octal, multiflags, charflags, swapflags, strflag, atflag, modeflags
= h.octal, h.multiflags, h.charflags, h.swapflags, h.strflag, h.atflag, h.modeflags
local c = {}
c.ETFS = strflag {
REG = 0,
BLK = 1,
CHR = 2,
DIR = 3,
DIR_SUBDIRS = 4,
}
c.RUMPUIO = strflag {
READ = 0,
WRITE = 1,
}
c.SIGMODEL = strflag {
PANIC = 0,
IGNORE = 1,
HOST = 2,
RAISE = 3,
RECORD = 4,
};
c.RF = strflag {
NONE = 0x00, -- not named, see issue https://github.com/anttikantee/buildrump.sh/issues/19
FDG = 0x01,
CFDG = 0x02,
}
c.CN_FREECRED = 0x02
c.ETFS_SIZE_ENDOFF = h.uint64_max
S.rump.c = c
-- We could also use rump_pub_module_init if loading later
function S.rump.module(s)
s = "rump" .. string.gsub(s, "%.", "_")
local mod = ffi.load(s, true)
modules[s] = mod
end
local function loadmodules(ms)
local len = #ms
local remains = #ms
local succeeded = true
while remains > 0 do
succeeded = false
for i = 1, #ms do
local v = ms[i]
if v then
v = "rump" .. string.gsub(v, "%.", "_")
local ok, mod = pcall(ffi.load, v, true)
if ok then
modules[v] = mod
ms[i] = nil
succeeded = true
remains = remains - 1
end
end
end
if not succeeded then break end
end
if not succeeded then error "cannot load rump modules" end
end
function S.rump.init(ms, ...) -- you must load the factions here eg dev, vfs, net, plus modules
if type(ms) == "string" then ms = {ms, ...} end
if ms then loadmodules(ms) end
local ok = ffi.C.rump_init()
if ok == -1 then return nil, t.error() end
S.abi = abi
return S
end
function S.rump.boot_gethowto() return retnum(ffi.C.rump_boot_gethowto()) end
function S.rump.boot_sethowto(how) ffi.C.rump_boot_sethowto(how) end
function S.rump.boot_setsigmodel(model) ffi.C.rump_boot_etsigmodel(model) end
function S.rump.schedule() ffi.C.rump_schedule() end
function S.rump.unschedule() ffi.C.rump_unschedule() end
function S.rump.printevcnts() ffi.C.rump_printevcnts() end
function S.rump.daemonize_begin() return retbool(ffi.C.rump_daemonize_begin()) end
function S.rump.daemonize_done(err) return retbool(ffi.C.rump_daemonize_done(err)) end
function S.rump.init_server(url) return retbool(ffi.C.rump_init_server(url)) end
function S.rump.i_know_what_i_am_doing_sysent_usenative()
ffi.C.rump_i_know_what_i_am_doing_with_sysents = 1
ffi.C.rump_pub_lwproc_sysent_usenative();
end
function S.rump.getversion() return ffi.C.rump_pub_getversion() end
-- etfs functions
function S.rump.etfs_register(key, hostpath, ftype, begin, size)
local ret
ftype = S.rump.c.ETFS[ftype]
if begin then
ret = ffi.C.rump_pub_etfs_register_withsize(key, hostpath, ftype, begin, size);
else
ret = ffi.C.rump_pub_etfs_register(key, hostpath, ftype);
end
return retbool(ret)
end
function S.rump.etfs_remove(key)
return retbool(ffi.C.rump_pub_etfs_remove(key))
end
-- threading
function S.rump.rfork(flags) return retbool(ffi.C.rump_pub_lwproc_rfork(S.rump.c.RF[flags])) end
function S.rump.newlwp(pid) return retbool(ffi.C.rump_pub_lwproc_newlwp(pid)) end
function S.rump.switchlwp(lwp) ffi.C.rump_pub_lwproc_switch(lwp) end
function S.rump.releaselwp() ffi.C.rump_pub_lwproc_releaselwp() end
function S.rump.curlwp() return ffi.C.rump_pub_lwproc_curlwp() end
-- revert so can load non rump again
abi.rump = false
abi.os = abi.host
S.__rump = true
return S.rump
|