File: //opt/alt/luajit/share/lua/syscall/linux/ffi.lua
-- ffi definitions of Linux types
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 abi = require "syscall.abi"
local ffi = require "ffi"
require "syscall.ffitypes"
local arch = require("syscall.linux." .. abi.arch .. ".ffi") -- architecture specific definitions
local defs = {}
local function append(str) defs[#defs + 1] = str end
append [[
typedef uint32_t mode_t;
typedef unsigned short int sa_family_t;
typedef uint64_t rlim64_t;
typedef unsigned long nlink_t;
typedef unsigned long ino_t;
typedef long time_t;
typedef int32_t daddr_t;
typedef long blkcnt_t;
typedef long blksize_t;
typedef int32_t clockid_t;
typedef long clock_t;
typedef uint32_t off32_t; /* only used for eg mmap2 on Linux */
typedef uint32_t le32; /* this is little endian - not really using it yet */
typedef uint32_t id_t;
typedef unsigned int tcflag_t;
typedef unsigned int speed_t;
typedef int timer_t;
typedef uint64_t fsblkcnt_t;
typedef uint64_t fsfilcnt_t;
/* despite glibc, Linux uses 32 bit dev_t */
typedef uint32_t dev_t;
typedef unsigned long aio_context_t;
typedef unsigned long nfds_t;
// should be a word, but we use 32 bits as bitops are signed 32 bit in LuaJIT at the moment
typedef int32_t fd_mask;
// again should be a long, and we have wrapped in a struct
// TODO ok to wrap Lua types but not syscall? https://github.com/justincormack/ljsyscall/issues/36
// TODO is this size right? check
struct cpu_set_t {
int32_t val[1024 / (8 * sizeof (int32_t))];
};
typedef int mqd_t;
typedef int idtype_t; /* defined as enum */
struct timespec {
time_t tv_sec;
long tv_nsec;
};
// misc
typedef void (*sighandler_t) (int);
// structs
struct timeval {
long tv_sec; /* seconds */
long tv_usec; /* microseconds */
};
struct itimerspec {
struct timespec it_interval;
struct timespec it_value;
};
struct itimerval {
struct timeval it_interval;
struct timeval it_value;
};
typedef struct __fsid_t {
int __val[2];
} fsid_t;
//static const int UTSNAME_LENGTH = 65;
struct utsname {
char sysname[65];
char nodename[65];
char release[65];
char version[65];
char machine[65];
char domainname[65];
};
struct pollfd {
int fd;
short int events;
short int revents;
};
typedef struct { /* based on Linux FD_SETSIZE = 1024, the kernel can do more, so can increase */
fd_mask fds_bits[1024 / (sizeof (fd_mask) * 8)];
} fd_set;
struct ucred {
pid_t pid;
uid_t uid;
gid_t gid;
};
struct rlimit64 {
rlim64_t rlim_cur;
rlim64_t rlim_max;
};
struct sysinfo {
long uptime;
unsigned long loads[3];
unsigned long totalram;
unsigned long freeram;
unsigned long sharedram;
unsigned long bufferram;
unsigned long totalswap;
unsigned long freeswap;
unsigned short procs;
unsigned short pad;
unsigned long totalhigh;
unsigned long freehigh;
unsigned int mem_unit;
char _f[20-2*sizeof(long)-sizeof(int)]; /* TODO ugh, remove calculation */
};
struct timex {
unsigned int modes;
long int offset;
long int freq;
long int maxerror;
long int esterror;
int status;
long int constant;
long int precision;
long int tolerance;
struct timeval time;
long int tick;
long int ppsfreq;
long int jitter;
int shift;
long int stabil;
long int jitcnt;
long int calcnt;
long int errcnt;
long int stbcnt;
int tai;
int :32; int :32; int :32; int :32;
int :32; int :32; int :32; int :32;
int :32; int :32; int :32;
};
typedef union sigval {
int sival_int;
void *sival_ptr;
} sigval_t;
struct cmsghdr {
size_t cmsg_len;
int cmsg_level;
int cmsg_type;
char cmsg_data[?];
};
struct msghdr {
void *msg_name;
socklen_t msg_namelen;
struct iovec *msg_iov;
size_t msg_iovlen;
void *msg_control;
size_t msg_controllen;
int msg_flags;
};
struct mmsghdr {
struct msghdr msg_hdr;
unsigned int msg_len;
};
struct sockaddr {
sa_family_t sa_family;
char sa_data[14];
};
struct sockaddr_storage {
sa_family_t ss_family;
unsigned long int __ss_align;
char __ss_padding[128 - 2 * sizeof(unsigned long int)]; /* total length 128 TODO no calculations */
};
struct sockaddr_in {
sa_family_t sin_family;
in_port_t sin_port;
struct in_addr sin_addr;
unsigned char sin_zero[8];
};
struct sockaddr_in6 {
sa_family_t sin6_family;
in_port_t sin6_port;
uint32_t sin6_flowinfo;
struct in6_addr sin6_addr;
uint32_t sin6_scope_id;
};
struct sockaddr_un {
sa_family_t sun_family;
char sun_path[108];
};
struct sockaddr_nl {
sa_family_t nl_family;
unsigned short nl_pad;
uint32_t nl_pid;
uint32_t nl_groups;
};
struct sockaddr_ll {
unsigned short sll_family;
unsigned short sll_protocol; /* __be16 */
int sll_ifindex;
unsigned short sll_hatype;
unsigned char sll_pkttype;
unsigned char sll_halen;
unsigned char sll_addr[8];
};
struct nlmsghdr {
uint32_t nlmsg_len;
uint16_t nlmsg_type;
uint16_t nlmsg_flags;
uint32_t nlmsg_seq;
uint32_t nlmsg_pid;
};
struct rtgenmsg {
unsigned char rtgen_family;
};
struct ifinfomsg {
unsigned char ifi_family;
unsigned char __ifi_pad;
unsigned short ifi_type;
int ifi_index;
unsigned ifi_flags;
unsigned ifi_change;
};
struct rtattr {
unsigned short rta_len;
unsigned short rta_type;
};
struct nlmsgerr {
int error;
struct nlmsghdr msg;
};
struct rtmsg {
unsigned char rtm_family;
unsigned char rtm_dst_len;
unsigned char rtm_src_len;
unsigned char rtm_tos;
unsigned char rtm_table;
unsigned char rtm_protocol;
unsigned char rtm_scope;
unsigned char rtm_type;
unsigned int rtm_flags;
};
static const int IFNAMSIZ = 16;
struct ifmap {
unsigned long mem_start;
unsigned long mem_end;
unsigned short base_addr;
unsigned char irq;
unsigned char dma;
unsigned char port;
};
struct rtnl_link_stats {
uint32_t rx_packets;
uint32_t tx_packets;
uint32_t rx_bytes;
uint32_t tx_bytes;
uint32_t rx_errors;
uint32_t tx_errors;
uint32_t rx_dropped;
uint32_t tx_dropped;
uint32_t multicast;
uint32_t collisions;
uint32_t rx_length_errors;
uint32_t rx_over_errors;
uint32_t rx_crc_errors;
uint32_t rx_frame_errors;
uint32_t rx_fifo_errors;
uint32_t rx_missed_errors;
uint32_t tx_aborted_errors;
uint32_t tx_carrier_errors;
uint32_t tx_fifo_errors;
uint32_t tx_heartbeat_errors;
uint32_t tx_window_errors;
uint32_t rx_compressed;
uint32_t tx_compressed;
};
struct ndmsg {
uint8_t ndm_family;
uint8_t ndm_pad1;
uint16_t ndm_pad2;
int32_t ndm_ifindex;
uint16_t ndm_state;
uint8_t ndm_flags;
uint8_t ndm_type;
};
struct nda_cacheinfo {
uint32_t ndm_confirmed;
uint32_t ndm_used;
uint32_t ndm_updated;
uint32_t ndm_refcnt;
};
struct ndt_stats {
uint64_t ndts_allocs;
uint64_t ndts_destroys;
uint64_t ndts_hash_grows;
uint64_t ndts_res_failed;
uint64_t ndts_lookups;
uint64_t ndts_hits;
uint64_t ndts_rcv_probes_mcast;
uint64_t ndts_rcv_probes_ucast;
uint64_t ndts_periodic_gc_runs;
uint64_t ndts_forced_gc_runs;
};
struct ndtmsg {
uint8_t ndtm_family;
uint8_t ndtm_pad1;
uint16_t ndtm_pad2;
};
struct ndt_config {
uint16_t ndtc_key_len;
uint16_t ndtc_entry_size;
uint32_t ndtc_entries;
uint32_t ndtc_last_flush;
uint32_t ndtc_last_rand;
uint32_t ndtc_hash_rnd;
uint32_t ndtc_hash_mask;
uint32_t ndtc_hash_chain_gc;
uint32_t ndtc_proxy_qlen;
};
typedef struct {
unsigned int clock_rate;
unsigned int clock_type;
unsigned short loopback;
} sync_serial_settings;
typedef struct {
unsigned int clock_rate;
unsigned int clock_type;
unsigned short loopback;
unsigned int slot_map;
} te1_settings;
typedef struct {
unsigned short encoding;
unsigned short parity;
} raw_hdlc_proto;
typedef struct {
unsigned int t391;
unsigned int t392;
unsigned int n391;
unsigned int n392;
unsigned int n393;
unsigned short lmi;
unsigned short dce;
} fr_proto;
typedef struct {
unsigned int dlci;
} fr_proto_pvc;
typedef struct {
unsigned int dlci;
char master[IFNAMSIZ];
} fr_proto_pvc_info;
typedef struct {
unsigned int interval;
unsigned int timeout;
} cisco_proto;
struct if_settings {
unsigned int type;
unsigned int size;
union {
raw_hdlc_proto *raw_hdlc;
cisco_proto *cisco;
fr_proto *fr;
fr_proto_pvc *fr_pvc;
fr_proto_pvc_info *fr_pvc_info;
sync_serial_settings *sync;
te1_settings *te1;
} ifs_ifsu;
};
struct ifreq {
union {
char ifrn_name[IFNAMSIZ];
} ifr_ifrn;
union {
struct sockaddr ifru_addr;
struct sockaddr ifru_dstaddr;
struct sockaddr ifru_broadaddr;
struct sockaddr ifru_netmask;
struct sockaddr ifru_hwaddr;
short ifru_flags;
int ifru_ivalue;
int ifru_mtu;
struct ifmap ifru_map;
char ifru_slave[IFNAMSIZ];
char ifru_newname[IFNAMSIZ];
void * ifru_data;
struct if_settings ifru_settings;
} ifr_ifru;
};
struct ifaddrmsg {
uint8_t ifa_family;
uint8_t ifa_prefixlen;
uint8_t ifa_flags;
uint8_t ifa_scope;
uint32_t ifa_index;
};
struct ifa_cacheinfo {
uint32_t ifa_prefered;
uint32_t ifa_valid;
uint32_t cstamp;
uint32_t tstamp;
};
struct rta_cacheinfo {
uint32_t rta_clntref;
uint32_t rta_lastuse;
uint32_t rta_expires;
uint32_t rta_error;
uint32_t rta_used;
uint32_t rta_id;
uint32_t rta_ts;
uint32_t rta_tsage;
};
struct fdb_entry {
uint8_t mac_addr[6];
uint8_t port_no;
uint8_t is_local;
uint32_t ageing_timer_value;
uint8_t port_hi;
uint8_t pad0;
uint16_t unused;
};
struct inotify_event {
int wd;
uint32_t mask;
uint32_t cookie;
uint32_t len;
char name[?];
};
struct linux_dirent64 {
uint64_t d_ino;
int64_t d_off;
unsigned short d_reclen;
unsigned char d_type;
char d_name[0];
};
struct flock64 {
short int l_type;
short int l_whence;
off_t l_start;
off_t l_len;
pid_t l_pid;
};
typedef union epoll_data {
void *ptr;
int fd;
uint32_t u32;
uint64_t u64;
} epoll_data_t;
struct signalfd_siginfo {
uint32_t ssi_signo;
int32_t ssi_errno;
int32_t ssi_code;
uint32_t ssi_pid;
uint32_t ssi_uid;
int32_t ssi_fd;
uint32_t ssi_tid;
uint32_t ssi_band;
uint32_t ssi_overrun;
uint32_t ssi_trapno;
int32_t ssi_status;
int32_t ssi_int;
uint64_t ssi_ptr;
uint64_t ssi_utime;
uint64_t ssi_stime;
uint64_t ssi_addr;
uint8_t __pad[48];
};
struct io_event {
uint64_t data;
uint64_t obj;
int64_t res;
int64_t res2;
};
struct seccomp_data {
int nr;
uint32_t arch;
uint64_t instruction_pointer;
uint64_t args[6];
};
struct sock_filter {
uint16_t code;
uint8_t jt;
uint8_t jf;
uint32_t k;
};
struct bpf_insn {
uint8_t code; /* opcode */
uint8_t dst_reg:4; /* dest register */
uint8_t src_reg:4; /* source register */
uint16_t off; /* signed offset */
uint32_t imm; /* signed immediate constant */
};
struct sock_fprog {
unsigned short len;
struct sock_filter *filter;
};
union bpf_attr {
struct {
uint32_t map_type;
uint32_t key_size;
uint32_t value_size;
uint32_t max_entries;
};
struct {
uint32_t map_fd;
uint64_t key __attribute__((aligned(8)));
union {
uint64_t value __attribute__((aligned(8)));
uint64_t next_key __attribute__((aligned(8)));
};
uint64_t flags;
};
struct {
uint32_t prog_type;
uint32_t insn_cnt;
uint64_t insns __attribute__((aligned(8)));
uint64_t license __attribute__((aligned(8)));
uint32_t log_level;
uint32_t log_size;
uint64_t log_buf __attribute__((aligned(8)));
uint32_t kern_version;
};
struct {
uint64_t pathname __attribute__((aligned(8)));
uint32_t bpf_fd;
};
} __attribute__((aligned(8)));
struct perf_event_attr {
uint32_t pe_type;
uint32_t size;
uint64_t pe_config;
union {
uint64_t sample_period;
uint64_t sample_freq;
};
uint64_t pe_sample_type;
uint64_t read_format;
uint32_t disabled:1,
inherit:1,
pinned:1,
exclusive:1,
exclude_user:1,
exclude_kernel:1,
exclude_hv:1,
exclude_idle:1,
mmap:1,
comm:1,
freq:1,
inherit_stat:1,
enable_on_exec:1,
task:1,
watermark:1,
precise_ip:2,
mmap_data:1,
sample_id_all:1,
exclude_host:1,
exclude_guest:1,
exclude_callchain_kernel:1,
exclude_callchain_user:1,
mmap2:1,
comm_exec:1,
use_clockid:1,
__reserved_1a:6;
uint32_t __reserved_1b;
union {
uint32_t wakeup_events;
uint32_t wakeup_watermark;
};
uint32_t bp_type;
union {
uint64_t bp_addr;
uint64_t config1;
};
union {
uint64_t bp_len;
uint64_t config2;
};
uint64_t branch_sample_type;
uint64_t sample_regs_user;
uint32_t sample_stack_user;
int32_t clockid;
uint64_t sample_regs_intr;
uint32_t aux_watermark;
uint32_t __reserved_2;
};
struct perf_event_mmap_page {
uint32_t version;
uint32_t compat_version;
uint32_t lock;
uint32_t index;
int64_t offset;
uint64_t time_enabled;
uint64_t time_running;
union {
uint64_t capabilities;
struct {
uint32_t cap_bit0 : 1,
cap_bit0_is_deprecated : 1,
cap_user_rdpmc : 1,
cap_user_time : 1,
cap_user_time_zero : 1;
};
};
uint16_t pmc_width;
uint16_t time_shift;
uint32_t time_mult;
uint64_t time_offset;
uint64_t __reserved[120];
volatile uint64_t data_head;
volatile uint64_t data_tail;
volatile uint64_t data_offset;
volatile uint64_t data_size;
uint64_t aux_head;
uint64_t aux_tail;
uint64_t aux_offset;
uint64_t aux_size;
};
struct perf_event_header {
uint32_t type;
uint16_t misc;
uint16_t size;
};
struct mq_attr {
long mq_flags, mq_maxmsg, mq_msgsize, mq_curmsgs, __unused[4];
};
struct termios2 {
tcflag_t c_iflag;
tcflag_t c_oflag;
tcflag_t c_cflag;
tcflag_t c_lflag;
cc_t c_line;
cc_t c_cc[19];
speed_t c_ispeed;
speed_t c_ospeed;
};
struct input_event {
struct timeval time;
uint16_t type;
uint16_t code;
int32_t value;
};
struct input_id {
uint16_t bustype;
uint16_t vendor;
uint16_t product;
uint16_t version;
};
struct input_absinfo {
int32_t value;
int32_t minimum;
int32_t maximum;
int32_t fuzz;
int32_t flat;
int32_t resolution;
};
struct input_keymap_entry {
uint8_t flags;
uint8_t len;
uint16_t index;
uint32_t keycode;
uint8_t scancode[32];
};
struct ff_replay {
uint16_t length;
uint16_t delay;
};
struct ff_trigger {
uint16_t button;
uint16_t interval;
};
struct ff_envelope {
uint16_t attack_length;
uint16_t attack_level;
uint16_t fade_length;
uint16_t fade_level;
};
struct ff_constant_effect {
int16_t level;
struct ff_envelope envelope;
};
struct ff_ramp_effect {
int16_t start_level;
int16_t end_level;
struct ff_envelope envelope;
};
struct ff_condition_effect {
uint16_t right_saturation;
uint16_t left_saturation;
int16_t right_coeff;
int16_t left_coeff;
uint16_t deadband;
int16_t center;
};
struct ff_periodic_effect {
uint16_t waveform;
uint16_t period;
int16_t magnitude;
int16_t offset;
uint16_t phase;
struct ff_envelope envelope;
uint32_t custom_len;
int16_t *custom_data;
};
struct ff_rumble_effect {
uint16_t strong_magnitude;
uint16_t weak_magnitude;
};
struct ff_effect {
uint16_t type;
int16_t id;
uint16_t direction;
struct ff_trigger trigger;
struct ff_replay replay;
union {
struct ff_constant_effect constant;
struct ff_ramp_effect ramp;
struct ff_periodic_effect periodic;
struct ff_condition_effect condition[2];
struct ff_rumble_effect rumble;
} u;
};
typedef struct {
int val[2];
} kernel_fsid_t;
/* we define the underlying structs not the pointer typedefs for capabilities */
struct user_cap_header {
uint32_t version;
int pid;
};
struct user_cap_data {
uint32_t effective;
uint32_t permitted;
uint32_t inheritable;
};
/* this are overall capabilities structs to put metatables on */
struct cap {
uint32_t cap[2];
};
struct capabilities {
uint32_t version;
int pid;
struct cap effective;
struct cap permitted;
struct cap inheritable;
};
struct xt_get_revision {
char name[29];
uint8_t revision;
};
struct vfs_cap_data {
le32 magic_etc;
struct {
le32 permitted; /* Little endian */
le32 inheritable; /* Little endian */
} data[2];
};
typedef struct {
void *ss_sp;
int ss_flags;
size_t ss_size;
} stack_t;
struct sched_param {
int sched_priority;
/* unused after here */
int sched_ss_low_priority;
struct timespec sched_ss_repl_period;
struct timespec sched_ss_init_budget;
int sched_ss_max_repl;
};
struct tun_filter {
uint16_t flags;
uint16_t count;
uint8_t addr[0][6];
};
struct tun_pi {
uint16_t flags;
uint16_t proto; /* __be16 */
};
struct vhost_vring_state {
unsigned int index;
unsigned int num;
};
struct vhost_vring_file {
unsigned int index;
int fd;
};
struct vhost_vring_addr {
unsigned int index;
unsigned int flags;
uint64_t desc_user_addr;
uint64_t used_user_addr;
uint64_t avail_user_addr;
uint64_t log_guest_addr;
};
struct vhost_memory_region {
uint64_t guest_phys_addr;
uint64_t memory_size;
uint64_t userspace_addr;
uint64_t flags_padding;
};
struct vhost_memory {
uint32_t nregions;
uint32_t padding;
struct vhost_memory_region regions[0];
};
struct rusage {
struct timeval ru_utime;
struct timeval ru_stime;
long ru_maxrss;
long ru_ixrss;
long ru_idrss;
long ru_isrss;
long ru_minflt;
long ru_majflt;
long ru_nswap;
long ru_inblock;
long ru_oublock;
long ru_msgsnd;
long ru_msgrcv;
long ru_nsignals;
long ru_nvcsw;
long ru_nivcsw;
};
]]
append(arch.nsig or [[
static const int _NSIG = 64;
]]
)
append(arch.sigset or [[
// again, should be a long
static const int _NSIG_BPW = 32;
typedef struct {
int32_t sig[_NSIG / _NSIG_BPW];
} sigset_t;
]]
)
-- both Glibc and Musl have larger termios at least for some architectures; I believe this is correct for kernel
append(arch.termios or [[
struct termios {
tcflag_t c_iflag;
tcflag_t c_oflag;
tcflag_t c_cflag;
tcflag_t c_lflag;
cc_t c_line;
cc_t c_cc[19];
};
]]
)
-- Linux struct siginfo padding depends on architecture
if abi.abi64 then
append [[
static const int SI_MAX_SIZE = 128;
static const int SI_PAD_SIZE = (SI_MAX_SIZE / sizeof (int)) - 4;
]]
else
append [[
static const int SI_MAX_SIZE = 128;
static const int SI_PAD_SIZE = (SI_MAX_SIZE / sizeof (int)) - 3;
]]
end
append(arch.siginfo or [[
typedef struct siginfo {
int si_signo;
int si_errno;
int si_code;
union {
int _pad[SI_PAD_SIZE];
struct {
pid_t si_pid;
uid_t si_uid;
} kill;
struct {
int si_tid;
int si_overrun;
sigval_t si_sigval;
} timer;
struct {
pid_t si_pid;
uid_t si_uid;
sigval_t si_sigval;
} rt;
struct {
pid_t si_pid;
uid_t si_uid;
int si_status;
clock_t si_utime;
clock_t si_stime;
} sigchld;
struct {
void *si_addr;
} sigfault;
struct {
long int si_band;
int si_fd;
} sigpoll;
} _sifields;
} siginfo_t;
]]
)
-- this is the type used by the rt_sigaction syscall NB have renamed the fields to sa_
append(arch.sigaction or [[
struct k_sigaction {
void (*sa_handler)(int);
unsigned long sa_flags;
void (*sa_restorer)(void);
unsigned sa_mask[2];
};
]]
)
-- these could vary be arch but do not yet
append [[
static const int sigev_preamble_size = sizeof(int) * 2 + sizeof(sigval_t);
static const int sigev_max_size = 64;
static const int sigev_pad_size = (sigev_max_size - sigev_preamble_size) / sizeof(int);
typedef struct sigevent {
sigval_t sigev_value;
int sigev_signo;
int sigev_notify;
union {
int _pad[sigev_pad_size];
int _tid;
struct {
void (*_function)(sigval_t);
void *_attribute;
} _sigev_thread;
} _sigev_un;
} sigevent_t;
]]
append(arch.ucontext) -- there is no default for ucontext and related types as very machine specific
if arch.statfs then append(arch.statfs)
else
-- Linux struct statfs/statfs64 depends on 64/32 bit
if abi.abi64 then
append [[
typedef long statfs_word;
]]
else
append [[
typedef uint32_t statfs_word;
]]
end
append [[
struct statfs64 {
statfs_word f_type;
statfs_word f_bsize;
uint64_t f_blocks;
uint64_t f_bfree;
uint64_t f_bavail;
uint64_t f_files;
uint64_t f_ffree;
kernel_fsid_t f_fsid;
statfs_word f_namelen;
statfs_word f_frsize;
statfs_word f_flags;
statfs_word f_spare[4];
};
]]
end
append(arch.stat)
-- epoll packed on x86_64 only (so same as x86)
append(arch.epoll or [[
struct epoll_event {
uint32_t events;
epoll_data_t data;
};
]]
)
-- endian dependent
if abi.le then
append [[
struct iocb {
uint64_t aio_data;
uint32_t aio_key, aio_reserved1;
uint16_t aio_lio_opcode;
int16_t aio_reqprio;
uint32_t aio_fildes;
uint64_t aio_buf;
uint64_t aio_nbytes;
int64_t aio_offset;
uint64_t aio_reserved2;
uint32_t aio_flags;
uint32_t aio_resfd;
};
]]
else
append [[
struct iocb {
uint64_t aio_data;
uint32_t aio_reserved1, aio_key;
uint16_t aio_lio_opcode;
int16_t aio_reqprio;
uint32_t aio_fildes;
uint64_t aio_buf;
uint64_t aio_nbytes;
int64_t aio_offset;
uint64_t aio_reserved2;
uint32_t aio_flags;
uint32_t aio_resfd;
};
]]
end
-- functions, minimal for Linux as mainly use syscall
append [[
long syscall(int number, ...);
int gettimeofday(struct timeval *tv, void *tz);
int clock_gettime(clockid_t clk_id, struct timespec *tp);
void exit(int status);
]]
ffi.cdef(table.concat(defs, ""))