sys.odin 59 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040
  1. //+build linux
  2. package linux
  3. import "core:intrinsics"
  4. /// Read data from file into the buffer
  5. /// Returns the number of bytes successfully read, which may be less than the size
  6. /// of the buffer even if the termination is successfull
  7. ///
  8. /// Available since Linux 1.0
  9. /// Before Linux 3.14, this operation is not atomic (i.e. not thread safe).
  10. read :: proc "contextless" (fd: Fd, buf: []$T) -> (int, Errno) {
  11. ret := syscall(SYS_read, fd, raw_data(buf), len(buf) * size_of(T))
  12. return errno_unwrap(ret, int)
  13. }
  14. /// Write the data from a buffer into the file
  15. /// Returns the number of bytes successfully written, which may be less than the size
  16. /// of the buffer, even if the termination is successfull
  17. /// When using direct I/O, error doesn't mean the write has failed. Partial data may
  18. /// have been written.
  19. /// If .Eintr is returned, the write operation has failed due to interrupt. You'll probably
  20. /// need to restart this syscall
  21. ///
  22. /// Available since Linux 1.0
  23. /// Before Linux 3.14 this operation is not atomic (i.e. not thread safe)
  24. write :: proc "contextless" (fd: Fd, buf: []$T) -> (int, Errno) {
  25. ret := syscall(SYS_write, fd, raw_data(buf), len(buf)*size_of(T))
  26. return errno_unwrap(ret, int)
  27. }
  28. /// Open file, get the file descriptor
  29. /// Available since Linux 1.0
  30. /// On ARM64 available since Linux 2.6.16
  31. open :: proc "contextless" (name: cstring, flags: Open_Flags, mode: Mode = {}) -> (Fd, Errno) {
  32. when ODIN_ARCH == .arm64 {
  33. ret := syscall(SYS_openat, AT_FDCWD, transmute(uintptr) name, transmute(u32) mode)
  34. return errno_unwrap(ret, Fd)
  35. } else {
  36. ret := syscall(SYS_open, transmute(uintptr) name, transmute(u32) mode)
  37. return errno_unwrap(ret, Fd)
  38. }
  39. }
  40. /// Close the file
  41. /// Available since Linux 1.0
  42. close :: proc "contextless" (fd: Fd) -> (Errno) {
  43. ret := syscall(SYS_close, fd)
  44. return Errno(-ret)
  45. }
  46. /// Get file status
  47. ///
  48. /// Returns information about the file in struct pointed to by `stat` parameter.
  49. ///
  50. /// Available since Linux 1.0
  51. /// For 32-bit systems a different syscall is used that became available since 2.4
  52. /// Not available on arm64
  53. stat :: proc "contextless" (filename: cstring, stat: ^Stat) -> (Errno) {
  54. when size_of(int) == 8 {
  55. when ODIN_ARCH == .arm64 {
  56. ret := syscall(SYS_fstatat, AT_FDCWD, cast(rawptr) filename, stat)
  57. return Errno(-ret)
  58. } else {
  59. ret := syscall(SYS_stat, cast(rawptr) filename, stat)
  60. return Errno(-ret)
  61. }
  62. } else {
  63. ret := syscall(SYS_stat64, cast(rawptr) filename, stat)
  64. return Errno(-ret)
  65. }
  66. }
  67. /// Get file status from file descriptor
  68. ///
  69. /// Returns information about the file in struct pointed to by `stat` parameter.
  70. ///
  71. /// Available since Linux 1.0
  72. /// For 32-bit systems a different syscall is used that became available since 2.4
  73. fstat :: proc "contextless" (fd: Fd, stat: ^Stat) -> (Errno) {
  74. when size_of(int) == 8 {
  75. ret := syscall(SYS_fstat, stat)
  76. return Errno(-ret)
  77. } else {
  78. ret := syscall(SYS_fstat64, stat)
  79. return Errno(-ret)
  80. }
  81. }
  82. /// Get information about the file that's potentially a symbolic link
  83. /// The information is returned in a struct pointed to by `stat` parameter.
  84. /// The difference with stat, fstat is that if the file is a symbolic link,
  85. /// stat and fstat will dereference the link. lstat doesn't dereference symlinks
  86. ///
  87. /// Available since Linux 1.0
  88. /// For 32-bit systems a different syscall is used that became available since 2.4
  89. /// Not available on arm64
  90. lstat :: proc "contextless" (filename: cstring, stat: ^Stat) -> (Errno) {
  91. when size_of(int) == 8 {
  92. when ODIN_ARCH == .arm64 {
  93. return fstatat(AT_FDCWD, filename, stat, {.SYMLINK_NOFOLLOW})
  94. } else {
  95. ret := syscall(SYS_lstat, cast(rawptr) filename, stat)
  96. return Errno(-ret)
  97. }
  98. } else {
  99. ret := syscall(SYS_lstat64, cast(rawptr) filename, stat)
  100. return Errno(-ret)
  101. }
  102. }
  103. /// Wait on event on a file descriptor
  104. /// Available since Linux 2.2
  105. poll :: proc "contextless" (fds: []Poll_Fd, timeout: i32) -> (i32, Errno) {
  106. when ODIN_ARCH == .arm64 {
  107. seconds := cast(uint) timeout / 1000
  108. nanoseconds := cast(uint) (timeout % 1000) * 1_000_000
  109. timeout_spec := Time_Spec{seconds, nanoseconds}
  110. ret := syscall(SYS_ppoll, raw_data(fds), len(fds), &timeout_spec, 0, 0)
  111. return errno_unwrap(ret, i32)
  112. } else {
  113. ret := syscall(SYS_poll, raw_data(fds), len(fds), timeout)
  114. return errno_unwrap(ret, i32)
  115. }
  116. }
  117. /// Seek the file stream to specified offset
  118. /// Available since Linux 1.0
  119. /// On 32-bit platforms available since Linux 1.2
  120. lseek :: proc "contextless" (fd: Fd, off: i64, whence: Seek_Whence) -> (Errno) {
  121. when size_of(int) == 8 {
  122. ret := syscall(SYS_lseek, fd, off, whence)
  123. return Errno(-ret)
  124. } else {
  125. ret := syscall(SYS__llseek, fd, compat64_arg_pair(off), whence)
  126. return Errno(-ret)
  127. }
  128. }
  129. /// Map files into memory
  130. /// Available since Linux 1.0
  131. /// On 32-bit platforms since Linux 1.0
  132. mmap :: proc "contextless" (addr: uintptr, size: uint, prot: Mem_Protection, flags: Map_Flags, fd: Fd = Fd(-1), offset: i64 = 0) -> (rawptr, Errno) {
  133. when size_of(int) == 8 {
  134. ret := syscall(SYS_mmap, addr, size, transmute(i32) prot, transmute(i32) flags, fd, offset)
  135. return errno_unwrap(ret, rawptr, uintptr)
  136. } else {
  137. ret := syscall(SYS_mmap2, addr, size, transmute(i32) prot, transmute(i32) flags, fd, cast(uintptr)(offset/4096))
  138. return errno_unwrap(ret, rawptr, uintptr)
  139. }
  140. }
  141. /// Protect memory region
  142. mprotect :: proc "contextless" (addr: rawptr, size: uint, prot: Mem_Protection) -> (Errno) {
  143. ret := syscall(SYS_mprotect, addr, size, transmute(i32) prot)
  144. return Errno(-ret)
  145. }
  146. /// Unmap memory
  147. /// Available since Linux 1.0
  148. munmap :: proc "contextless" (addr: rawptr, size: uint) -> (Errno) {
  149. ret := syscall(SYS_munmap, addr, size)
  150. return Errno(-ret)
  151. }
  152. // TODO(flysand): brk
  153. /// Alter an action taken by a process
  154. rt_sigaction :: proc "contextless" (sig: Signal, sigaction: ^Sig_Action, old_sigaction: ^Sig_Action) -> Errno {
  155. ret := syscall(SYS_rt_sigaction, sig, sigaction, old_sigaction, size_of(Sig_Set))
  156. return Errno(-ret)
  157. }
  158. /// Examime and alter blocked signals
  159. /// Available since Linux 2.2
  160. rt_sigprocmask :: proc "contextless" (mask_kind: Sig_Mask_Kind, new_set: ^Sig_Set, old_set: ^Sig_Set) -> Errno {
  161. ret := syscall(SYS_rt_sigprocmask, mask_kind, new_set, old_set, size_of(Sig_Set))
  162. return Errno(-ret)
  163. }
  164. // TODO(flysand): rt_sigreturn
  165. // TODO(flysand): ioctl
  166. /// Read the file at a specified offset
  167. /// Note, it is not an error to return less bytes than requested
  168. /// Available since Linux 2.2
  169. pread :: proc "contextless" (fd: Fd, buf: []$T, offset: i64) -> (int, Errno) {
  170. ret := syscall(SYS_pread64, fd, raw_data(buf), compat64_arg_pair(len(buf)*size_of(T)))
  171. return errno_unwrap(ret, int)
  172. }
  173. /// Read the file at a specified offset
  174. /// Note, it is not an error to return less bytes than requested
  175. /// Available since Linux 2.2
  176. pwrite :: proc "contextless" (fd: Fd, buf: []$T, offset: i64) -> (int, Errno) {
  177. ret := syscall(SYS_pwrite64, fd, raw_data(buf), compat64_arg_pair(len(buf)*size_of(T)))
  178. return errno_unwrap(ret, int)
  179. }
  180. // TODO(flysand): readv
  181. // TODO(flysand): writev
  182. /// Check user permissions for a file
  183. /// If Mode is F_OK, checks whether the file exists
  184. /// Similarly, X_OK, W_OK, R_OK check if the file is executable, writeable, readable respectively
  185. /// Available since Linux 1.0
  186. /// For ARM64 available since Linux 2.6.16
  187. access :: proc "contextless" (name: cstring, mode: Mode = F_OK) -> (bool, Errno) {
  188. when ODIN_ARCH == .arm64 {
  189. ret := syscall(SYS_faccessat, AT_FDCWD, cast(rawptr) name, transmute(u32) mode)
  190. return errno_unwrap(ret, bool)
  191. } else {
  192. ret := syscall(SYS_access, cast(rawptr) name, transmute(u32) mode)
  193. return errno_unwrap(ret, bool)
  194. }
  195. }
  196. /// Create a pipe
  197. /// Available since Linux 2.6.27
  198. pipe2 :: proc "contextless" (pipes: ^[2]Fd, flags: Open_Flags) -> (Errno) {
  199. ret := syscall(SYS_pipe2, pipes, transmute(u32) flags)
  200. return Errno(-ret)
  201. }
  202. // TODO(flysand): select
  203. // TODO(flysand): sched_yield
  204. // TODO(flysand): add docs here
  205. mremap :: proc "contextless" (old_addr: rawptr, old_size: uint, new_size: uint, flags: MRemap_Flags, new_addr: uintptr = 0) -> (rawptr, Errno) {
  206. if .FIXED in flags {
  207. ret := syscall(SYS_mremap, old_addr, old_size, new_size, transmute(i32) flags, new_addr)
  208. return errno_unwrap(ret, rawptr, rawptr)
  209. } else {
  210. ret := syscall(SYS_mremap, old_addr, old_size, new_size, transmute(i32) flags)
  211. return errno_unwrap(ret, rawptr, rawptr)
  212. }
  213. }
  214. /// Sync file with memory map
  215. /// Available since Linux 2.0
  216. msync :: proc "contextless" (addr: rawptr, size: uint, flags: MSync_Flags) -> (Errno) {
  217. ret := syscall(SYS_msync, addr, size, transmute(i32) flags)
  218. return Errno(-ret)
  219. }
  220. // TODO(flysand): mincore
  221. /// Give advice about use of memory
  222. /// Available since Linux 2.4
  223. madvise :: proc "contextless" (addr: rawptr, size: uint, advice: MAdvice) -> (Errno) {
  224. ret := syscall(SYS_madvise, addr, size, advice)
  225. return Errno(-ret)
  226. }
  227. // TODO(flysand): shmget
  228. // TODO(flysand): shmat
  229. // TODO(flysand): shmctl
  230. /// Allocate a new file descriptor that refers to the same file as the one provided
  231. /// Available since Linux 1.0
  232. dup :: proc "contextless" (fd: Fd) -> (Fd, Errno) {
  233. ret := syscall(SYS_dup, fd)
  234. return errno_unwrap(ret, Fd)
  235. }
  236. /// Adjust an existing file descriptor to point to the same file as `old`
  237. /// Available since Linux 1.0
  238. /// On ARM64 available since Linux 2.6.27
  239. dup2 :: proc "contextless" (old: Fd, new: Fd) -> (Fd, Errno) {
  240. when ODIN_ARCH == .arm64 {
  241. ret := syscall(SYS_dup3, old, new, 0)
  242. return errno_unwrap(ret, Fd)
  243. } else {
  244. ret := syscall(SYS_dup2, old, new)
  245. return errno_unwrap(ret, Fd)
  246. }
  247. }
  248. // TODO(flysand): pause
  249. // TODO(flysand): nanosleep
  250. // TODO(flysand): getitimer
  251. // TODO(flysand): alarm
  252. // TODO(flysand): setitimer
  253. /// Returns the thread group ID of the current process
  254. /// Note that it doesn't return the pid, despite it's name.
  255. /// Available since Linux 1.0
  256. getpid :: proc "contextless" () -> Pid {
  257. return cast(Pid) syscall(SYS_getpid)
  258. }
  259. // TODO(flysand): sendfile
  260. /// Create a socket file descriptor
  261. /// Available since Linux 2.0
  262. socket :: proc "contextless" (domain: Address_Family, socktype: Socket_Type, sockflags: Socket_FD_Flags, protocol: Protocol) -> (Fd, Errno) {
  263. sock_type_flags: int = cast(int) socktype | transmute(int) sockflags
  264. ret := syscall(SYS_socket, domain, sock_type_flags, protocol)
  265. return errno_unwrap(ret, Fd)
  266. }
  267. /// Connect the socket to the address
  268. /// Available since Linux 2.0
  269. connect :: proc "contextless" (sock: Fd, addr: ^$T) -> (Errno)
  270. where
  271. T == Sock_Addr_In ||
  272. T == Sock_Addr_In6 ||
  273. T == Sock_Addr_Any
  274. {
  275. ret := syscall(SYS_connect, sock, addr, size_of(T))
  276. return Errno(-ret)
  277. }
  278. /// Accept a pending connection or block until new connection appears
  279. /// Depends on Sock_FD_Flags of the `sock` parameter.
  280. /// Available since Linux 2.0
  281. accept :: proc "contextless" (sock: Fd, addr: ^$T, sockflags: Socket_FD_Flags = {}) -> (Fd, Errno)
  282. where
  283. T == Sock_Addr_In ||
  284. T == Sock_Addr_In6 ||
  285. T == Sock_Addr_Any
  286. {
  287. addr_len: i32 = size_of(T)
  288. ret := syscall(SYS_accept4, sock, addr, &addr_len, transmute(int) sockflags)
  289. return errno_unwrap(ret, Fd)
  290. }
  291. // TODO(flysand): Rewrite recvfrom and sendto to use default parameters
  292. recvfrom :: proc "contextless" (sock: Fd, buf: []u8, flags: Socket_Msg, addr: ^$T) -> (int, Errno)
  293. where
  294. T == Sock_Addr_In ||
  295. T == Sock_Addr_In6 ||
  296. T == Sock_Addr_Any
  297. {
  298. addr_len: i32 = size_of(T)
  299. ret := syscall(SYS_recvfrom, sock, raw_data(buf), len(buf), transmute(i32) flags, addr, &addr_len)
  300. return errno_unwrap(ret, int)
  301. }
  302. @private
  303. recv_noaddr :: proc "contextless" (sock: Fd, buf: []u8, flags: Socket_Msg) -> (int, Errno) {
  304. ret := syscall(SYS_recvfrom, sock, raw_data(buf), len(buf), transmute(i32) flags, cast(rawptr) nil, cast(uintptr) 0)
  305. return errno_unwrap(ret, int)
  306. }
  307. sendto :: proc "contextless" (sock: Fd, buf: []u8, flags: Socket_Msg, addr: ^$T) -> (int, Errno)
  308. where
  309. T == Sock_Addr_In ||
  310. T == Sock_Addr_In6 ||
  311. T == Sock_Addr_Any
  312. {
  313. ret := syscall(SYS_sendto, sock, raw_data(buf), len(buf), transmute(i32) flags, addr, size_of(T))
  314. return errno_unwrap(ret, int)
  315. }
  316. @private
  317. send_noaddr :: proc "contextless" (sock: Fd, buf: []u8, flags: Socket_Msg) -> (int, Errno) {
  318. ret := syscall(SYS_sendto, sock, raw_data(buf), len(buf), transmute(i32) flags, cast(rawptr) nil, cast(uintptr) 0)
  319. return errno_unwrap(ret, int)
  320. }
  321. /// Receive a message from a socket
  322. /// Available since Linux 2.0
  323. recv :: proc {recvfrom, recv_noaddr}
  324. /// Send a message through a socket
  325. /// Available since Linux 2.0
  326. send :: proc {sendto, send_noaddr}
  327. // TODO(flysand): sendmsg
  328. // TODO(flysand): recvmsg
  329. shutdown :: proc "contextless" (sock: Fd, how: Shutdown_How) -> (Errno) {
  330. ret := syscall(SYS_shutdown, sock, how)
  331. return Errno(-ret)
  332. }
  333. /// Bind a socket to the given local address
  334. /// Available since Linux 2.0
  335. bind :: proc "contextless" (sock: Fd, addr: ^$T) -> (Errno)
  336. where
  337. T == Sock_Addr_In ||
  338. T == Sock_Addr_In6 ||
  339. T == Sock_Addr_Any
  340. {
  341. ret := syscall(SYS_bind, sock, addr, size_of(T))
  342. return Errno(-ret)
  343. }
  344. /// Marks the socket as a socket that listen to connections using accept.2
  345. /// Available since Linux 2.0
  346. listen :: proc "contextless" (sock: Fd, queue_len: i32) -> (Errno) {
  347. ret := syscall(SYS_listen, sock, queue_len)
  348. return Errno(-ret)
  349. }
  350. // TODO(flysand): getsockname
  351. // TODO(flysand): getpeername
  352. // TODO(flysand): socketpair
  353. // TODO(flysand): the parameters are the same, maybe there's a way to make it into a single proc, sacrificing type
  354. // safety slightly
  355. // TODO(flysand): add ability to specify slices
  356. setsockopt_base :: proc "contextless" (sock: Fd, level: int, opt: int, val: $T) -> (Errno)
  357. where
  358. intrinsics.type_is_pointer(T) ||
  359. intrinsics.type_is_multi_pointer(T)
  360. {
  361. val_data := val
  362. val_size := size_of(intrinsics.type_elem_type(T))
  363. ret := syscall(SYS_setsockopt, sock, level, opt, val_data, val_size)
  364. return Errno(-ret)
  365. }
  366. setsockopt_sock :: proc "contextless" (sock: Fd, level: Socket_API_Level_Sock, opt: Socket_Option, val: $T) -> (Errno)
  367. where
  368. intrinsics.type_is_pointer(T) ||
  369. intrinsics.type_is_multi_pointer(T)
  370. {
  371. return setsockopt_base(sock, cast(int) level, cast(int) opt, val)
  372. }
  373. setsockopt_tcp :: proc "contextless" (sock: Fd, level: Socket_API_Level_TCP, opt: Socket_TCP_Option, val: $T) -> (Errno)
  374. where
  375. intrinsics.type_is_pointer(T) ||
  376. intrinsics.type_is_multi_pointer(T)
  377. {
  378. return setsockopt_base(sock, cast(int) level, cast(int) opt, val)
  379. }
  380. setsockopt_udp :: proc "contextless" (sock: Fd, level: Socket_API_Level_UDP, opt: Socket_UDP_Option, val: $T) -> (Errno)
  381. where
  382. intrinsics.type_is_pointer(T) ||
  383. intrinsics.type_is_multi_pointer(T)
  384. {
  385. return setsockopt_base(sock, cast(int) level, cast(int) opt, val)
  386. }
  387. /// Set socket option for a given socket API level
  388. /// Available since Linux 2.0
  389. setsockopt :: proc {
  390. setsockopt_sock,
  391. setsockopt_tcp,
  392. setsockopt_udp,
  393. setsockopt_base,
  394. }
  395. getsockopt_base :: proc "contextless" (sock: Fd, level: int, opt: Socket_Option, val: $T) -> (int, Errno)
  396. where
  397. intrinsics.type_is_pointer(T) ||
  398. intrinsics.type_is_multi_pointer(T)
  399. {
  400. val_data := val
  401. val_size := size_of(T)
  402. ret := syscall(SYS_getsockopt, sock, level, opt, val_data, cast(rawptr) &val_size)
  403. return val_size, Errno(-ret)
  404. }
  405. getsockopt_sock :: proc "contextless" (sock: Fd, level: Socket_API_Level_Sock, opt: Socket_Option, val: ^$T) -> (int, Errno)
  406. where
  407. intrinsics.type_is_pointer(T) ||
  408. intrinsics.type_is_multi_pointer(T)
  409. {
  410. return getsockopt_base(sock, cast(int) level, cast(int) opt, val)
  411. }
  412. getsockopt_tcp :: proc "contextless" (sock: Fd, level: Socket_API_Level_TCP, opt: Socket_TCP_Option, val: ^$T) -> (int, Errno)
  413. where
  414. intrinsics.type_is_pointer(T) ||
  415. intrinsics.type_is_multi_pointer(T)
  416. {
  417. return getsockopt_base(sock, cast(int) level, cast(int) opt, val)
  418. }
  419. getsockopt_udp :: proc "contextless" (sock: Fd, level: Socket_API_Level_UDP, opt: Socket_UDP_Option, val: ^$T) -> (int, Errno)
  420. where
  421. intrinsics.type_is_pointer(T) ||
  422. intrinsics.type_is_multi_pointer(T)
  423. {
  424. return getsockopt_base(sock, cast(int) level, cast(int) opt, val)
  425. }
  426. /// Get socket option for a given socket API level
  427. /// Available since Linux 2.0
  428. getsockopt :: proc {
  429. getsockopt_sock,
  430. getsockopt_tcp,
  431. getsockopt_udp,
  432. getsockopt_base,
  433. }
  434. // TODO(flysand): clone (probably not in this PR, maybe not ever)
  435. /// Creates a copy of the running process
  436. /// Available since Linux 1.0
  437. fork :: proc "contextless" () -> (Pid, Errno) {
  438. when ODIN_ARCH == .arm64 {
  439. // Note(flysand): this syscall is not documented, but the bottom 8 bits of flags
  440. // are for exit signal
  441. ret := syscall(SYS_clone, Signal.SIGCHLD)
  442. return errno_unwrap(ret, Pid)
  443. } else {
  444. ret := syscall(SYS_fork)
  445. return errno_unwrap(ret, Pid)
  446. }
  447. }
  448. // TODO(flysand): vfork
  449. // TODO(flysand): execve
  450. /// Exit the thread with a given exit code
  451. /// Available since Linux 1.0
  452. exit :: proc "contextless" (code: i32) -> ! {
  453. syscall(SYS_exit, code)
  454. unreachable()
  455. }
  456. /// Wait for the process to change state
  457. /// Available since Linux 1.0
  458. wait4 :: proc "contextless" (pid: Pid, status: ^u32, options: Wait_Options) -> (Pid, Errno) {
  459. ret := syscall(SYS_wait4, pid, status, transmute(u32) options)
  460. return errno_unwrap(ret, Pid)
  461. }
  462. /// See wait4
  463. waitpid :: wait4
  464. // TODO(flysand): kill
  465. /// Get system information
  466. /// Available since Linux 1.0
  467. uname :: proc "contextless" (uts_name: ^UTS_Name) -> (Errno) {
  468. ret := syscall(SYS_uname, uts_name)
  469. return Errno(-ret)
  470. }
  471. // TODO(flysand): semget
  472. // TODO(flysand): semop
  473. // TODO(flysand): semctl
  474. // TODO(flysand): shmdt
  475. // TODO(flysand): msgget
  476. // TODO(flysand): msgsnd
  477. // TODO(flysand): msgrcv
  478. // TODO(flysand): msgctl
  479. fcntl_dupfd :: proc "contextless" (fd: Fd, cmd: FCntl_Command_DUPFD, newfd: Fd) -> (Fd, Errno) {
  480. ret := syscall(SYS_fcntl, fd, cmd, newfd)
  481. return errno_unwrap(ret, Fd)
  482. }
  483. fcntl_dupfd_cloexec :: proc "contextless" (fd: Fd, cmd: FCntl_Command_DUPFD_CLOEXEC, newfd: Fd) -> (Fd, Errno) {
  484. ret := syscall(SYS_fcntl, fd, cmd, newfd)
  485. return errno_unwrap(ret, Fd)
  486. }
  487. fcntl_getfd :: proc "contextless" (fd: Fd, cmd: FCntl_Command_GETFD) -> (Fd, Errno) {
  488. ret := syscall(SYS_fcntl, fd, cmd)
  489. return errno_unwrap(ret, Fd)
  490. }
  491. fcntl_setfd :: proc "contextless" (fd: Fd, cmd: FCntl_Command_SETFD, newfd: Fd) -> (Errno) {
  492. ret := syscall(SYS_fcntl, fd, cmd, newfd)
  493. return Errno(-ret)
  494. }
  495. fcntl_getfl :: proc "contextless" (fd: Fd, cmd: FCntl_Command_GETFL) -> (Open_Flags, Errno) {
  496. ret := syscall(SYS_fcntl, fd, cmd)
  497. return errno_unwrap(u32(ret), Open_Flags, Open_Flags)
  498. }
  499. fcntl_setfl :: proc "contextless" (fd: Fd, cmd: FCntl_Command_SETFL, flags: Open_Flags) -> (Errno) {
  500. ret := syscall(SYS_fcntl, fd, cmd, transmute(u32) flags)
  501. return Errno(-ret)
  502. }
  503. fcntl_setlk :: proc "contextless" (fd: Fd, cmd: FCntl_Command_SETLK, lock: ^FLock) -> (Errno) {
  504. when size_of(int) == 4 {
  505. ret := syscall(SYS_fcntl64, fd, cmd, lock)
  506. return Errno(-ret)
  507. } else {
  508. ret := syscall(SYS_fcntl, fd, cmd, lock)
  509. return Errno(-ret)
  510. }
  511. }
  512. fcntl_setlkw :: proc "contextless" (fd: Fd, cmd: FCntl_Command_SETLKW, lock: ^FLock) -> (Errno) {
  513. when size_of(int) == 4 {
  514. ret := syscall(SYS_fcntl64, fd, cmd, lock)
  515. return Errno(-ret)
  516. } else {
  517. ret := syscall(SYS_fcntl, fd, cmd, lock)
  518. return Errno(-ret)
  519. }
  520. }
  521. fcntl_getlk :: proc "contextless" (fd: Fd, cmd: FCntl_Command_GETLK, lock: ^FLock) -> (Errno) {
  522. when size_of(int) == 4 {
  523. ret := syscall(SYS_fcntl64, fd, cmd, lock)
  524. return Errno(-ret)
  525. } else {
  526. ret := syscall(SYS_fcntl, fd, cmd, lock)
  527. return Errno(-ret)
  528. }
  529. }
  530. fcntl_getown_ex :: proc "contextless" (fd: Fd, cmd: FCntl_Command_GETOWN_EX, owner: ^F_Owner) -> (Errno) {
  531. ret := syscall(SYS_fcntl, fd, cmd, owner)
  532. return Errno(-ret)
  533. }
  534. fcntl_setown_ex :: proc "contextless" (fd: Fd, cmd: FCntl_Command_SETOWN_EX, owner: ^F_Owner) -> (Errno) {
  535. ret := syscall(SYS_fcntl, fd, cmd, owner)
  536. return Errno(-ret)
  537. }
  538. fcntl_getsig :: proc "contextless" (fd: Fd, cmd: FCntl_Command_GETSIG) -> (Signal, Errno) {
  539. ret := syscall(SYS_fcntl, fd, cmd)
  540. return errno_unwrap(ret, Signal)
  541. }
  542. fcntl_setsig :: proc "contextless" (fd: Fd, cmd: FCntl_Command_SETSIG, sig: Signal) -> (Errno) {
  543. ret := syscall(SYS_fcntl, fd, cmd, sig)
  544. return Errno(-ret)
  545. }
  546. fcntl_setlease :: proc "contextless" (fd: Fd, cmd: FCntl_Command_SETLEASE, lease: FD_Lease) -> (Errno) {
  547. ret := syscall(SYS_fcntl, fd, cmd, lease)
  548. return Errno(-ret)
  549. }
  550. fcntl_getlease :: proc "contextless" (fd: Fd, cmd: FCntl_Command_GETLEASE) -> (FD_Lease, Errno) {
  551. ret := syscall(SYS_fcntl, fd, cmd)
  552. return errno_unwrap(ret, FD_Lease)
  553. }
  554. fcntl_notify :: proc "contextless" (fd: Fd, cmd: FCntl_Command_NOTIFY, notifications: FD_Notifications) -> (Errno) {
  555. ret := syscall(SYS_fcntl, fd, cmd)
  556. return Errno(-ret)
  557. }
  558. fcntl_setpipe_sz :: proc "contextless" (fd: Fd, cmd: FCntl_Command_SETPIPE_SZ, sz: i32) -> (i32, Errno) {
  559. ret := syscall(SYS_fcntl, fd, cmd, sz)
  560. return errno_unwrap(ret, i32)
  561. }
  562. fcntl_getpipe_sz :: proc "contextless" (fd: Fd, cmd: FCntl_Command_GETPIPE_SZ) -> (i32, Errno) {
  563. ret := syscall(SYS_fcntl, fd, cmd)
  564. return errno_unwrap(ret, i32)
  565. }
  566. fcntl_add_seals :: proc "contextless" (fd: Fd, cmd: FCntl_Command_ADD_SEALS, seal: Seal) -> (Errno) {
  567. ret := syscall(SYS_fcntl, fd, cmd, transmute(i32) seal)
  568. return Errno(-ret)
  569. }
  570. fcntl_get_seals :: proc "contextless" (fd: Fd, cmd: FCntl_Command_GET_SEALS) -> (Seal, Errno) {
  571. ret := syscall(SYS_fcntl, fd, cmd)
  572. return errno_unwrap(i32(ret), Seal, Seal)
  573. }
  574. fcntl_get_rw_hint :: proc "contextless" (fd: Fd, cmd: FCntl_Command_GET_RW_HINT, hint: ^RW_Hint) -> (Errno) {
  575. ret := syscall(SYS_fcntl, fd, cmd, hint)
  576. return Errno(-ret)
  577. }
  578. fcntl_set_rw_hint :: proc "contextless" (fd: Fd, cmd: FCntl_Command_SET_RW_HINT, hint: ^RW_Hint) -> (Errno) {
  579. ret := syscall(SYS_fcntl, fd, cmd, hint)
  580. return Errno(-ret)
  581. }
  582. fcntl_get_file_rw_hint :: proc "contextless" (fd: Fd, cmd: FCntl_Command_GET_FILE_RW_HINT, hint: ^RW_Hint) -> (Errno) {
  583. ret := syscall(SYS_fcntl, fd, cmd, hint)
  584. return Errno(-ret)
  585. }
  586. fcntl_set_file_rw_hint :: proc "contextless" (fd: Fd, cmd: FCntl_Command_SET_FILE_RW_HINT, hint: ^RW_Hint) -> (Errno) {
  587. ret := syscall(SYS_fcntl, fd, cmd, hint)
  588. return Errno(-ret)
  589. }
  590. fcntl :: proc {
  591. fcntl_dupfd,
  592. fcntl_dupfd_cloexec,
  593. fcntl_getfd,
  594. fcntl_setfd,
  595. fcntl_getfl,
  596. fcntl_setfl,
  597. fcntl_setlk,
  598. fcntl_setlkw,
  599. fcntl_getlk,
  600. fcntl_getown_ex,
  601. fcntl_setown_ex,
  602. fcntl_getsig,
  603. fcntl_setsig,
  604. fcntl_setlease,
  605. fcntl_getlease,
  606. fcntl_notify,
  607. fcntl_setpipe_sz,
  608. fcntl_getpipe_sz,
  609. fcntl_add_seals,
  610. fcntl_get_seals,
  611. fcntl_get_rw_hint,
  612. fcntl_set_rw_hint,
  613. fcntl_get_file_rw_hint,
  614. fcntl_set_file_rw_hint,
  615. }
  616. // TODO(flysand): flock
  617. /// Sync state of the file with the storage device
  618. fsync :: proc "contextless" (fd: Fd) -> (Errno) {
  619. ret := syscall(SYS_fsync, fd)
  620. return Errno(-ret)
  621. }
  622. // TODO(flysand): fdatasync
  623. /// Truncate a file to specified length
  624. /// On 32-bit architectures available since Linux 2.4
  625. truncate :: proc "contextless" (name: cstring, length: i64) -> (Errno) {
  626. when size_of(int) == 4 {
  627. ret := syscall(SYS_truncate64, cast(rawptr) name, compat64_arg_pair(length))
  628. return Errno(-ret)
  629. } else {
  630. ret := syscall(SYS_truncate, cast(rawptr) name, compat64_arg_pair(length))
  631. return Errno(-ret)
  632. }
  633. }
  634. /// Truncate a file specified by file descriptor to specified length
  635. /// On 32-bit architectures available since 2.4
  636. ftruncate :: proc "contextless" (fd: Fd, length: i64) -> (Errno) {
  637. when size_of(int) == 4 {
  638. ret := syscall(SYS_ftruncate64, fd, compat64_arg_pair(length))
  639. return Errno(-ret)
  640. } else {
  641. ret := syscall(SYS_truncate, fd, compat64_arg_pair(length))
  642. return Errno(-ret)
  643. }
  644. }
  645. /// Retrieve the contents of the directory specified by dirfd
  646. /// Returns the number of bytes written
  647. /// Available since Linux 2.4
  648. getdents :: proc "contextless" (dirfd: Fd, buf: []u8) -> (int, Errno) {
  649. ret := syscall(SYS_getdents64, dirfd, raw_data(buf), len(buf))
  650. return errno_unwrap(ret, int)
  651. }
  652. /// Get current working directory
  653. /// Available since Linux 1.0
  654. getcwd :: proc "contextless" (buf: []u8) -> (int, Errno) {
  655. ret := syscall(SYS_getcwd, raw_data(buf), len(buf))
  656. return errno_unwrap(ret, int)
  657. }
  658. /// Change working directory to the directory specified by path
  659. /// Available since Linux 1.0
  660. chdir :: proc "contextless" (path: cstring) -> (Errno) {
  661. ret := syscall(SYS_chdir, cast(rawptr) path)
  662. return Errno(-ret)
  663. }
  664. /// Change working directory to the directory specified by dirfd
  665. /// Available since Linux 1.0
  666. fchdir :: proc "contextless" (fd: Fd) -> (Errno) {
  667. ret := syscall(SYS_fchdir, fd)
  668. return Errno(-ret)
  669. }
  670. /// Rename (move) the file
  671. /// Available since Linux 1.0
  672. /// On ARM64 available since Linux 2.6.16
  673. rename :: proc "contextless" (old: cstring, new: cstring) -> (Errno) {
  674. when ODIN_ARCH == .arm64 {
  675. ret := syscall(SYS_renameat, AT_FDCWD, cast(rawptr) old, AT_FDCWD, cast(rawptr) new)
  676. return Errno(-ret)
  677. } else {
  678. ret := syscall(SYS_rename, cast(rawptr) old, cast(rawptr) new)
  679. return Errno(-ret)
  680. }
  681. }
  682. /// Creates a directory
  683. /// Available since Linux 1.0
  684. /// On ARM64 available since Linux 2.6.16
  685. mkdir :: proc "contextless" (name: cstring, mode: Mode) -> (Errno) {
  686. when ODIN_ARCH == .arm64 {
  687. ret := syscall(SYS_mkdirat, AT_FDCWD, cast(rawptr) name, transmute(u32) mode)
  688. return Errno(-ret)
  689. } else {
  690. ret := syscall(SYS_mkdir, cast(rawptr) name, transmute(u32) mode)
  691. return Errno(-ret)
  692. }
  693. }
  694. /// Remove a directory specified by name
  695. /// Available since Linux 1.0
  696. /// On ARM64 available since Linux 2.6.16
  697. rmdir :: proc "contextless" (name: cstring) -> (Errno) {
  698. when ODIN_ARCH == .arm64 {
  699. ret := syscall(SYS_unlinkat, AT_FDCWD, cast(rawptr) name, transmute(i32) FD_Flags{.REMOVEDIR})
  700. return Errno(-ret)
  701. } else {
  702. ret := syscall(SYS_rmdir, cast(rawptr) name)
  703. return Errno(-ret)
  704. }
  705. }
  706. // TODO(flysand): creat
  707. /// Create a hard link on a file
  708. /// Available since Linux 1.0
  709. /// On ARM64 available since Linux 2.6.16
  710. link :: proc "contextless" (target: cstring, linkpath: cstring) -> (Errno) {
  711. when ODIN_ARCH == .arm64 {
  712. ret := syscall(SYS_linkat, AT_FDCWD, cast(rawptr) target, AT_FDCWD, cast(rawptr) linkpath)
  713. return Errno(-ret)
  714. } else {
  715. ret := syscall(SYS_link, cast(rawptr) target, cast(rawptr) linkpath)
  716. return Errno(-ret)
  717. }
  718. }
  719. /// Delete a name, and possible a file it refers to
  720. /// Available since Linux 1.0
  721. /// On ARM64 available since Linux 2.6.16
  722. unlink :: proc "contextless" (name: cstring) -> (Errno) {
  723. when ODIN_ARCH == .arm64 {
  724. ret := syscall(SYS_unlinkat, AT_FDCWD, cast(rawptr) name, 0)
  725. return Errno(-ret)
  726. } else {
  727. ret := syscall(SYS_unlink, cast(rawptr) name)
  728. return Errno(-ret)
  729. }
  730. }
  731. /// Create a symbolic link
  732. /// Available since Linux 1.0
  733. /// On arm64 available since Linux 2.6.16
  734. symlink :: proc "contextless" (target: cstring, linkpath: cstring) -> (Errno) {
  735. when ODIN_ARCH == .arm64 {
  736. ret := syscall(SYS_symlinkat, AT_FDCWD, cast(rawptr) target, cast(rawptr) linkpath)
  737. return Errno(-ret)
  738. } else {
  739. ret := syscall(SYS_symlink, cast(rawptr) target, cast(rawptr) linkpath)
  740. return Errno(-ret)
  741. }
  742. }
  743. /// Read the value of a symbolic link
  744. /// Available since Linux 1.0
  745. /// On arm64 available since Linux 2.6.16
  746. readlink :: proc "contextless" (name: cstring, buf: []u8) -> (int, Errno) {
  747. when ODIN_ARCH == .arm64 {
  748. ret := syscall(SYS_readlinkat, AT_FDCWD, cast(rawptr) name, raw_data(buf), len(buf))
  749. return errno_unwrap(ret, int)
  750. } else {
  751. ret := syscall(SYS_readlink, cast(rawptr) name, raw_data(buf), len(buf))
  752. return errno_unwrap(ret, int)
  753. }
  754. }
  755. /// Change file permissions
  756. /// Available since Linux 1.0
  757. /// On ARM64 available since Linux 2.6.16
  758. chmod :: proc "contextless" (name: cstring, mode: Mode) -> (Errno) {
  759. when ODIN_ARCH == .arm64 {
  760. ret := syscall(SYS_fchmodat, cast(rawptr) name, transmute(u32) mode, 0)
  761. return Errno(-ret)
  762. } else {
  763. ret := syscall(SYS_chmod, cast(rawptr) name, transmute(u32) mode)
  764. return Errno(-ret)
  765. }
  766. }
  767. /// Change file permissions through a file descriptor
  768. /// Available since Linux 1.0
  769. fchmod :: proc "contextless" (fd: Fd, mode: Mode) -> (Errno) {
  770. ret := syscall(SYS_fchmod, fd, transmute(u32) mode)
  771. return Errno(-ret)
  772. }
  773. /// Change ownership of a file
  774. /// Available since Linux 2.2
  775. /// On 32-bit architectures available since Linux 2.4
  776. /// On ARM64 available since Linux 2.6.16
  777. chown :: proc "contextless" (name: cstring, uid: Uid, gid: Gid) -> (Errno) {
  778. when size_of(int) == 4 {
  779. ret := syscall(SYS_chown32, cast(rawptr) name, uid, gid)
  780. return Errno(-ret)
  781. } else when ODIN_ARCH == .arm64 {
  782. ret := syscall(SYS_fchownat, AT_FDCWD, cast(rawptr) name, uid, gid, 0)
  783. return Errno(-ret)
  784. } else {
  785. ret := syscall(SYS_chown, cast(rawptr) name, uid, gid)
  786. return Errno(-ret)
  787. }
  788. }
  789. /// Change ownership of a file by file descriptor
  790. /// Available since Linux 1.0
  791. /// On 32-bit architecvtures available since Linux 2.4
  792. fchown :: proc "contextless" (fd: Fd, uid: Uid, gid: Gid) -> (Errno) {
  793. when size_of(int) == 4 {
  794. ret := syscall(SYS_fchown32, fd, uid, gid)
  795. return Errno(-ret)
  796. } else {
  797. ret := syscall(SYS_fchown, fd, uid, gid)
  798. return Errno(-ret)
  799. }
  800. }
  801. /// Change ownership of a file. Unlike chown, if a file is a symlink dooesn't dereference it
  802. /// Available since Linux 1.0
  803. /// On 32-bit architectures available since Linux 2.4
  804. /// On ARM64 available since Linux 2.6.16
  805. lchown :: proc "contextless" (name: cstring, uid: Uid, gid: Gid) -> (Errno) {
  806. when size_of(int) == 4 {
  807. ret := syscall(SYS_lchown32, cast(rawptr) name, uid, gid)
  808. return Errno(-ret)
  809. } else when ODIN_ARCH == .arm64 {
  810. ret := syscall(SYS_fchownat, AT_FDCWD, cast(rawptr) name, uid, gid, transmute(i32) FD_Flags{.SYMLINK_NOFOLLOW})
  811. return Errno(-ret)
  812. } else {
  813. ret := syscall(SYS_lchown, cast(rawptr) name, uid, gid)
  814. return Errno(-ret)
  815. }
  816. }
  817. // TODO(flysand): umask
  818. // TODO(flysand): gettimeofday
  819. /// Get limits on resources
  820. /// Available since Linux 1.0
  821. getrlimit :: proc "contextless" (kind: RLimit_Kind, resource: ^RLimit) -> (Errno) {
  822. ret := syscall(SYS_getrlimit, kind, resource)
  823. return Errno(-ret)
  824. }
  825. /// Get resource usage
  826. /// Available since Linux 1.0
  827. getrusage :: proc "contextless" (who: RUsage_Who, rusage: ^RUsage) -> (Errno) {
  828. ret := syscall(SYS_getrusage, who, rusage)
  829. return Errno(-ret)
  830. }
  831. /// Get information about the system
  832. sysinfo :: proc "contextless" (sysinfo: ^Sys_Info) -> (Errno) {
  833. ret := syscall(SYS_sysinfo, sysinfo)
  834. return Errno(-ret)
  835. }
  836. /// Get current process times
  837. /// Available since Linux 1.0
  838. times :: proc "contextless" (tms: ^Tms) -> (Errno) {
  839. ret := syscall(SYS_times, cast(rawptr) tms)
  840. return Errno(-ret)
  841. }
  842. // TODO(flysand): ptrace
  843. /// Get real user ID
  844. /// Available since Linux 1.0
  845. /// On 32-bit platforms available since Linux 2.4
  846. getuid :: proc "contextless" () -> Uid {
  847. when size_of(int) == 8 {
  848. return cast(Uid) syscall(SYS_getuid)
  849. } else {
  850. return cast(Uid) syscall(SYS_getuid32)
  851. }
  852. }
  853. // TODO(flysand): syslog
  854. /// Get real group ID
  855. /// Available since Linux 1.0
  856. /// On 32-bit platforms available since Linux 2.4
  857. getgid :: proc "contextless" () -> Gid {
  858. when size_of(int) == 8 {
  859. return cast(Gid) syscall(SYS_getgid)
  860. } else {
  861. return cast(Gid) syscall(SYS_getgid32)
  862. }
  863. }
  864. /// Set effective user id
  865. /// Available since Linux 1.0
  866. /// On 32-bit platforms available since Linux 2.4
  867. @(require_results)
  868. setuid :: proc "contextless" (uid: Uid) -> (Errno) {
  869. when size_of(int) == 8 {
  870. ret := syscall(SYS_setuid, uid)
  871. return Errno(-ret)
  872. } else {
  873. ret := syscall(SYS_setuid32, uid)
  874. return Errno(-ret)
  875. }
  876. }
  877. /// Set effective group id
  878. /// If the process is privileged also sets real group id
  879. /// Available since Linux 1.0
  880. /// On 32-bit platforms available since Linux 2.4
  881. @(require_results)
  882. setgid :: proc "contextless" (gid: Gid) -> (Errno) {
  883. when size_of(int) == 8 {
  884. ret := syscall(SYS_setgid, gid)
  885. return Errno(-ret)
  886. } else {
  887. ret := syscall(SYS_setgid32, gid)
  888. return Errno(-ret)
  889. }
  890. }
  891. /// Get effective user ID
  892. /// Available since Linux 1.0
  893. /// On 32-bit platforms available since Linux 2.4
  894. geteuid :: proc "contextless" () -> Uid {
  895. when size_of(int) == 8 {
  896. return cast(Uid) syscall(SYS_geteuid)
  897. } else {
  898. return cast(Uid) syscall(SYS_geteuid32)
  899. }
  900. }
  901. /// Get effective group ID
  902. /// Available since Linux 1.0
  903. /// On 32-bit platforms available since Linux 2.4
  904. getegid :: proc "contextless" () -> Gid {
  905. when size_of(int) == 8 {
  906. return cast(Gid) syscall(SYS_getegid)
  907. } else {
  908. return cast(Gid) syscall(SYS_getegid32)
  909. }
  910. }
  911. /// Set process group
  912. /// Available since Linux 1.0
  913. setpgid :: proc "contextless" (pid: Pid, pgid: Pid) -> (Errno) {
  914. ret := syscall(SYS_setpgid, pid, pgid)
  915. return Errno(-ret)
  916. }
  917. /// Get the parent process ID
  918. /// Available since Linux 1.0
  919. getppid :: proc "contextless" () -> Pid {
  920. return cast(Pid) syscall(SYS_getppid)
  921. }
  922. /// Get process group
  923. /// Available since Linux 1.0
  924. getpgrp :: proc "contextless" () -> (Pid, Errno) {
  925. when ODIN_ARCH == .arm64 {
  926. ret := syscall(SYS_getpgid, 0)
  927. return errno_unwrap(ret, Pid)
  928. } else {
  929. ret := syscall(SYS_getpgrp)
  930. return errno_unwrap(ret, Pid)
  931. }
  932. }
  933. /// Create a session and set the process group ID
  934. /// Available since Linux 2.0
  935. setsid :: proc "contextless" () -> (Errno) {
  936. ret := syscall(SYS_setsid)
  937. return Errno(-ret)
  938. }
  939. /// Set real and/or effective user id
  940. /// If any of the arguments is -1, the corresponding id is not changed
  941. /// Available since Linux 1.0
  942. /// On 32-bit platforms available since Linux 2.4
  943. @(require_results)
  944. setreuid :: proc "contextless" (real: Uid, effective: Uid) -> (Errno) {
  945. when size_of(int) == 8 {
  946. ret := syscall(SYS_setreuid, real, effective)
  947. return Errno(-ret)
  948. } else {
  949. ret := syscall(SYS_setreuid32, real, effective)
  950. return Errno(-ret)
  951. }
  952. }
  953. /// Set real and/or effective group id
  954. /// If any of the arguments is -1, the corresponding id is not changed
  955. /// Available since Linux 1.0
  956. /// On 32-bit platforms available since Linux 2.4
  957. @(require_results)
  958. setregid :: proc "contextless" (real: Gid, effective: Gid) -> (Errno) {
  959. when size_of(int) == 8 {
  960. ret := syscall(SYS_setregid, real, effective)
  961. return Errno(-ret)
  962. } else {
  963. ret := syscall(SYS_setregid32, real, effective)
  964. return Errno(-ret)
  965. }
  966. }
  967. // TODO(flysand): getgroups
  968. // TODO(flysand): setgroups
  969. /// Set real, effective and/or saved user id
  970. /// If any of the arguments is -1, the corresponding id is not changed
  971. /// Available since Linux 2.2
  972. /// On 32-bit platforms available since Linux 2.4
  973. @(require_results)
  974. setresuid :: proc "contextless" (real: Uid, effective: Uid, saved: Uid) -> (Errno) {
  975. when size_of(int) == 8 {
  976. ret := syscall(SYS_setresuid, real, effective, saved)
  977. return Errno(-ret)
  978. } else {
  979. ret := syscall(SYS_setresuid32, real, effective, saved)
  980. return Errno(-ret)
  981. }
  982. }
  983. /// Get real, effective and saved user id
  984. /// Available since Linux 2.2
  985. /// On 32-bit platforms available since Linux 2.4
  986. getresuid :: proc "contextless" (real: ^Uid, effective: ^Uid, saved: ^Uid) -> (Errno) {
  987. when size_of(int) == 8 {
  988. ret := syscall(SYS_getresuid, cast(rawptr) real, cast(rawptr) effective, cast(rawptr) saved)
  989. return Errno(-ret)
  990. } else {
  991. ret := syscall(SYS_getresuid32, cast(rawptr) real, cast(rawptr) effective, cast(rawptr) saved)
  992. return Errno(-ret)
  993. }
  994. }
  995. /// Set real, effective and/or saved group id
  996. /// If any of the arguments is -1, the corresponding id is not changed
  997. /// Available since Linux 2.2
  998. /// On 32-bit platforms available since Linux 2.4
  999. @(require_results)
  1000. setresgid :: proc "contextless" (real: Gid, effective: Gid, saved: Uid) -> (Errno) {
  1001. when size_of(int) == 8 {
  1002. ret := syscall(SYS_setresgid, real, effective, saved)
  1003. return Errno(-ret)
  1004. } else {
  1005. ret := syscall(SYS_setresgid32, real, effective, saved)
  1006. return Errno(-ret)
  1007. }
  1008. }
  1009. /// Get real, effective and saved group id
  1010. /// Available since Linux 2.2
  1011. /// On 32-bit platforms available since Linux 2.4
  1012. getresgid :: proc "contextless" (real: ^Gid, effective: ^Gid, saved: ^Gid) -> (Errno) {
  1013. when size_of(int) == 8 {
  1014. ret := syscall(SYS_getresgid, cast(rawptr) real, cast(rawptr) effective, cast(rawptr) saved)
  1015. return Errno(-ret)
  1016. } else {
  1017. ret := syscall(SYS_getresgid32, cast(rawptr) real, cast(rawptr) effective, cast(rawptr) saved)
  1018. return Errno(-ret)
  1019. }
  1020. }
  1021. /// Get process group
  1022. /// Available since Linux 1.0
  1023. getpgid :: proc "contextless" (pid: Pid) -> (Pid, Errno) {
  1024. ret := syscall(SYS_getpgid, pid)
  1025. return errno_unwrap(ret, Pid)
  1026. }
  1027. // NOTE(flysand): setfsuid and setfsgid are deprecated
  1028. /// Get session ID of the calling process
  1029. /// Available since Linux 2.0
  1030. getsid :: proc "contextless" (pid: Pid) -> (Pid, Errno) {
  1031. ret := syscall(SYS_getsid, pid)
  1032. return errno_unwrap(ret, Pid)
  1033. }
  1034. // TODO(flysand): capget
  1035. // TODO(flysand): capset
  1036. /// Examine pending signals
  1037. /// Available since Linux 2.2
  1038. rt_sigpending :: proc "contextless" (sigs: ^Sig_Set) -> Errno {
  1039. ret := syscall(SYS_rt_sigpending, sigs, size_of(Sig_Set))
  1040. return Errno(-ret)
  1041. }
  1042. /// Synchronously wait for queued signals
  1043. /// Available since Linux 2.2
  1044. rt_sigtimedwait :: proc "contextless" (sigs: ^Sig_Set, info: ^Sig_Info, time_sus: ^Time_Spec) -> (Signal, Errno) {
  1045. ret := syscall(SYS_rt_sigtimedwait, sigs, info, time_sus, size_of(Sig_Set))
  1046. return errno_unwrap(ret, Signal)
  1047. }
  1048. /// Send signal information to a process
  1049. /// Available since Linux 2.2
  1050. rt_sigqueueinfo :: proc "contextless" (pid: Pid, sig: Signal, si: ^Sig_Info) -> (Errno) {
  1051. ret := syscall(SYS_rt_sigqueueinfo, pid, sig, si)
  1052. return Errno(-ret)
  1053. }
  1054. /// Replace the signal mask for a value with the new mask until a signal is received
  1055. /// Available since Linux 2.2
  1056. rt_sigsuspend :: proc "contextless" (sigset: ^Sig_Set) -> Errno {
  1057. ret := syscall(SYS_rt_sigsuspend, sigset, size_of(Sig_Set))
  1058. return Errno(-ret)
  1059. }
  1060. /// Set or get signal stack context
  1061. /// Available since Linux 2.2
  1062. sigaltstack :: proc "contextless" (stack: ^Sig_Stack, old_stack: ^Sig_Stack) -> (Errno) {
  1063. ret := syscall(SYS_sigaltstack, stack, old_stack)
  1064. return Errno(-ret)
  1065. }
  1066. // TODO(flysand): utime
  1067. /// Create a special or ordinary file
  1068. /// `mode` parameter contains both the the file mode and the type of the node to create
  1069. /// -> Add one of S_IFSOCK, S_IFBLK, S_IFFIFO, S_IFCHR to mode
  1070. /// Available since Linux 1.0
  1071. /// On ARM64 available since Linux 2.6.16
  1072. mknod :: proc "contextless" (name: cstring, mode: Mode, dev: Dev) -> (Errno) {
  1073. when ODIN_ARCH == .arm64 {
  1074. ret := syscall(SYS_mknodat, AT_FDCWD, cast(rawptr) name, transmute(u32) mode, dev)
  1075. return Errno(-ret)
  1076. } else {
  1077. ret := syscall(SYS_mknod, cast(rawptr) name, transmute(u32) mode, dev)
  1078. return Errno(-ret)
  1079. }
  1080. }
  1081. // TODO(flysand): uselib
  1082. /// Set the process execution domain
  1083. /// Available since Linux 1.2
  1084. personality :: proc "contextless" (personality: uint) -> (uint, Errno) {
  1085. ret := syscall(SYS_personality, personality)
  1086. return errno_unwrap(ret, uint)
  1087. }
  1088. // TODO(flysand): ustat
  1089. /// Query information about filesystem
  1090. ///
  1091. /// Available since Linux 1.0
  1092. /// For 32-bit systems a different syscall is used that became available since 2.6
  1093. statfs :: proc "contextless" (path: cstring, statfs: ^Stat_FS) -> (Errno) {
  1094. when size_of(int) == 8 {
  1095. ret := syscall(SYS_statfs, transmute(uintptr) path, statfs)
  1096. return Errno(-ret)
  1097. } else {
  1098. ret := syscall(SYS_statfs64, cast(rawptr) path, size_of(Stat_FS), statfs)
  1099. return Errno(-ret)
  1100. }
  1101. }
  1102. /// Query information about filesystem by file descriptor
  1103. ///
  1104. /// Available since Linux 1.0
  1105. /// For 32-bit systems a different syscall is used that became available since 2.6
  1106. fstatfs :: proc "contextless" (fd: Fd, statfs: ^Stat_FS) -> (Errno) {
  1107. when size_of(int) == 8 {
  1108. ret := syscall(SYS_statfs, fd, statfs)
  1109. return Errno(-ret)
  1110. } else {
  1111. ret := syscall(SYS_statfs64, fd, size_of(Stat_FS), statfs)
  1112. return Errno(-ret)
  1113. }
  1114. }
  1115. // TODO(flysand): sysfs
  1116. /// Get priority on user, process group or process
  1117. /// Available since Linux 1.0
  1118. getpriority :: proc "contextless" (which: Priority_Which, who: i32) -> (i32, Errno) {
  1119. ret := syscall(SYS_getpriority, which, who)
  1120. prio, err := errno_unwrap(ret, i32)
  1121. // NOTE(flysand): getpriority will return `20 - priority` to avoid returning
  1122. // negative priorities as errors
  1123. prio = 20 - prio
  1124. return prio, err
  1125. }
  1126. /// Set priority on user, process group or process
  1127. /// Available since Linux 1.0
  1128. setpriority :: proc "contextless" (which: Priority_Which, who: i32, prio: i32) -> (Errno) {
  1129. ret := syscall(SYS_setpriority, which, who, prio)
  1130. return Errno(-ret)
  1131. }
  1132. // TODO(flysand): sched_setparam
  1133. // TODO(flysand): sched_getparam
  1134. // TODO(flysand): sched_setscheduler
  1135. // TODO(flysand): sched_getscheduler
  1136. // TODO(flysand): sched_get_priority_max
  1137. // TODO(flysand): sched_get_priority_min
  1138. // TODO(flysand): sched_rr_get_interval
  1139. /// Lock and memory
  1140. /// Available since Linux 2.0
  1141. /// If flags specified, available since Linux 4.4
  1142. mlock :: proc "contextless" (addr: rawptr, size: uint, flags: MLock_Flags = {}) -> (Errno) {
  1143. // Pretty darn recent syscall, better call simpler version if we can
  1144. if flags > {} {
  1145. ret := syscall(SYS_mlock2, addr, size, transmute(i32) flags)
  1146. return Errno(-ret)
  1147. } else {
  1148. ret := syscall(SYS_mlock, addr, size)
  1149. return Errno(-ret)
  1150. }
  1151. }
  1152. /// Unlock memory
  1153. /// Available since Linux 2.0
  1154. munlock :: proc "contextless" (addr: rawptr, size: uint) -> (Errno) {
  1155. ret := syscall(SYS_munlock, addr, size)
  1156. return Errno(-ret)
  1157. }
  1158. /// Lock all memory
  1159. mlockall :: proc "contextless" (flags: MLock_Flags = {}) -> (Errno) {
  1160. ret := syscall(SYS_mlockall, transmute(i32) flags)
  1161. return Errno(-ret)
  1162. }
  1163. /// Unlock all memory
  1164. munlockall :: proc "contextless" () -> (Errno) {
  1165. ret := syscall(SYS_munlockall)
  1166. return Errno(-ret)
  1167. }
  1168. // TODO(flysand): vhangup
  1169. // TODO(flysand): modify_ldt
  1170. // TODO(flysand): pivot_root
  1171. // TODO(flysand): _sysctl
  1172. // TODO(flysand): prctl
  1173. // TODO(flysand): arch_prctl
  1174. // TODO(flysand): adj_timex
  1175. /// Set limits on resources
  1176. /// Available since Linux 1.0
  1177. setrlimit :: proc "contextless" (kind: RLimit_Kind, resource: ^RLimit) -> (Errno) {
  1178. ret := syscall(SYS_setrlimit, kind, resource)
  1179. return Errno(-ret)
  1180. }
  1181. // TODO(flysand): sync
  1182. // TODO(flysand): acct
  1183. // TODO(flysand): settimeofday
  1184. // TODO(flysand): mount
  1185. // TODO(flysand): umount2
  1186. // TODO(flysand): swapon
  1187. // TODO(flysand): swapoff
  1188. // TODO(flysand): reboot
  1189. /// Set hostname
  1190. /// Note: to get the host name, use `uname` syscall
  1191. /// Available since Linux 1.0
  1192. sethostname :: proc "contextless" (hostname: string) -> (Errno) {
  1193. ret := syscall(SYS_sethostname, raw_data(hostname), len(hostname))
  1194. return Errno(-ret)
  1195. }
  1196. /// Set domain name
  1197. /// Note: to get the domain name, use `uname` syscall
  1198. /// Available since Linux 2.2
  1199. setdomainname :: proc "contextless" (name: string) -> (Errno) {
  1200. ret := syscall(SYS_setdomainname, raw_data(name), len(name))
  1201. return Errno(-ret)
  1202. }
  1203. // TODO(flysand): iopl
  1204. // TODO(flysand): ioperm
  1205. // TODO(flysand): create_module
  1206. // TODO(flysand): init_module
  1207. // TODO(flysand): delete_module
  1208. // TODO(flysand): get_kernel_syms
  1209. // TODO(flysand): query_module
  1210. // TODO(flysand): quotactl
  1211. // TODO(flysand): nfsservctl
  1212. // TODO(flysand): getpmsg
  1213. // TODO(flysand): putpmsg
  1214. // TODO(flysand): afs_syscall
  1215. // TODO(flysand): tuxcall
  1216. // TODO(flysand): security
  1217. /// Returns the thread ID of the current process
  1218. /// This is what the kernel calls "pid"
  1219. /// Let me insert a tiny rant here, this terminology is confusing:
  1220. /// sometimes pid refers to a thread, and other times it refers
  1221. /// to a thread group (process group?)
  1222. /// Anyway, this syscall is available since Linux 1.0
  1223. gettid :: proc "contextless" () -> Pid {
  1224. return cast(Pid) syscall(SYS_gettid)
  1225. }
  1226. // TODO(flysand): readahead
  1227. // TODO(flysand): setxattr
  1228. // TODO(flysand): lsetxattr
  1229. // TODO(flysand): fsetxattr
  1230. // TODO(flysand): getxattr
  1231. // TODO(flysand): lgetxattr
  1232. // TODO(flysand): fgetxattr
  1233. // TODO(flysand): listxattr
  1234. // TODO(flysand): llistxattr
  1235. // TODO(flysand): flistxattr
  1236. // TODO(flysand): removexattr
  1237. // TODO(flysand): lremovexattr
  1238. // TODO(flysand): fremovexattr
  1239. // TODO(flysand): tkill
  1240. // TODO(flysand): time
  1241. /// Wait on a futex until it's signaled
  1242. futex_wait :: proc "contextless" (futex: ^Futex, op: Futex_Wait_Type, flags: Futex_Flags, val: u32, timeout: ^Time_Spec = nil) -> (Errno) {
  1243. futex_flags := cast(u32) op + transmute(u32) flags
  1244. ret := syscall(SYS_futex, futex, futex_flags, val, timeout)
  1245. return Errno(-ret)
  1246. }
  1247. /// Wake up other threads on a futex
  1248. /// n_wakeup specifies the number of processes to wakeup. Specify max(i32) to wake up all processes waiting
  1249. futex_wake :: proc "contextless" (futex: ^Futex, op: Futex_Wake_Type, flags: Futex_Flags, n_wakeup: i32) -> (int, Errno) {
  1250. futex_flags := cast(u32) op + transmute(u32) flags
  1251. ret := syscall(SYS_futex, futex, futex_flags, n_wakeup)
  1252. return errno_unwrap(ret, int)
  1253. }
  1254. // NOTE(flysand): futex_fd is racy, so not implemented
  1255. /// Requeues processes waiting on futex `futex` to wait on futex `requeue_futex`
  1256. /// `requeue_threshold` specifies the maximum amount of waiters to wake up, the rest of the waiters will be requeued
  1257. /// `requeue_max` specifies the maximum amount of waiters that are required at `requeue_futex`
  1258. /// The operation blocks until the `requeue_max` requirement is satisfied
  1259. /// If the value of the mutex is not equal to `val`, fails with EAGAIN before any further checks
  1260. /// Returns the total number of waiters that have been woken up plus the number of waiters requeued
  1261. futex_cmp_requeue :: proc "contextless" (futex: ^Futex, op: Futex_Cmp_Requeue_Type, flags: Futex_Flags, requeue_threshold: u32,
  1262. requeue_max: i32, requeue_futex: ^Futex, val: i32) -> (int, Errno)
  1263. {
  1264. futex_flags := cast(u32) op + transmute(u32) flags
  1265. ret := syscall(SYS_futex, futex, futex_flags, requeue_threshold, requeue_max, requeue_futex, val)
  1266. return errno_unwrap(ret, int)
  1267. }
  1268. /// See `futex_cmp_requeue`, this function does the same thing but doesn't check the value of the futex
  1269. /// Returns the total number of waiters that have been woken up
  1270. futex_requeue :: proc "contextless" (futex: ^Futex, op: Futex_Requeue_Type, flags: Futex_Flags, requeue_threshold: u32,
  1271. requeue_max: i32, requeue_futex: ^Futex) -> (int, Errno)
  1272. {
  1273. futex_flags := cast(u32) op + transmute(u32) flags
  1274. ret := syscall(SYS_futex, futex, futex_flags, requeue_threshold, requeue_max, requeue_futex)
  1275. return errno_unwrap(ret, int)
  1276. }
  1277. /// Okay, for this one, see the man pages, the description for it is pretty long and very specific. It's sole
  1278. /// purpose is to allow implementing conditional values sync primitive, it seems like
  1279. futex_wake_op :: proc "contextless" (futex: ^Futex, op: Futex_Wake_Op_Type, flags: Futex_Flags, wakeup: i32,
  1280. dst_wakeup, dst: ^Futex, futex_op: u32) -> (int, Errno)
  1281. {
  1282. futex_flags := cast(u32) op + transmute(u32) flags
  1283. ret := syscall(SYS_futex, futex, futex_flags, wakeup, dst_wakeup, dst, futex_op)
  1284. return errno_unwrap(ret, int)
  1285. }
  1286. /// Same as wait, but mask specifies bits that must be equal for the mutex to wake up
  1287. futex_wait_bitset :: proc "contextless" (futex: ^Futex, op: Futex_Wait_Bitset_Type, flags: Futex_Flags, val: u32,
  1288. timeout: ^Time_Spec, mask: u32) -> (int, Errno)
  1289. {
  1290. futex_flags := cast(u32) op + transmute(u32) flags
  1291. ret := syscall(SYS_futex, futex, futex_flags, val, timeout, 0, mask)
  1292. return errno_unwrap(ret, int)
  1293. }
  1294. /// Wake up on bitset
  1295. futex_wake_bitset :: proc "contextless" (futex: ^Futex, op: Futex_Wake_Bitset_Type, flags: Futex_Flags, n_wakeup: u32, mask: u32) -> (int, Errno)
  1296. {
  1297. futex_flags := cast(u32) op + transmute(u32) flags
  1298. ret := syscall(SYS_futex, futex, futex_flags, n_wakeup, 0, 0, mask)
  1299. return errno_unwrap(ret, int)
  1300. }
  1301. // TODO(flysand): Priority inheritance (PI) futicees
  1302. futex :: proc {
  1303. futex_wait,
  1304. futex_wake,
  1305. futex_cmp_requeue,
  1306. futex_requeue,
  1307. futex_wake_op,
  1308. futex_wait_bitset,
  1309. futex_wake_bitset,
  1310. }
  1311. // TODO(flysand): sched_setaffinity
  1312. // TODO(flysand): sched_getaffinity
  1313. // TODO(flysand): set_thread_area
  1314. // TODO(flysand): io_setup
  1315. // TODO(flysand): io_destroy
  1316. // TODO(flysand): io_getevents
  1317. // TODO(flysand): io_submit
  1318. // TODO(flysand): io_cancel
  1319. // TODO(flysand): get_thread_area
  1320. // TODO(flysand): lookup_dcookie
  1321. // TODO(flysand): epoll_create
  1322. // TODO(flysand): epoll_ctl_old
  1323. // TODO(flysand): epoll_wait_old
  1324. // TODO(flysand): remap_file_pages
  1325. /// Set the address of the futex that's gonna be waken when
  1326. /// current thread terminates
  1327. /// Available since Linux 2.6
  1328. set_tid_address :: proc "contextless" (tidptr: ^u32) {
  1329. syscall(SYS_set_tid_address, tidptr)
  1330. }
  1331. // TODO(flysand): restart_syscall
  1332. // TODO(flysand): semtimedop
  1333. // TODO(flysand): fadvise64
  1334. // TODO(flysand): timer_create
  1335. // TODO(flysand): timer_settime
  1336. // TODO(flysand): timer_gettime
  1337. // TODO(flysand): timer_getoverrun
  1338. // TODO(flysand): timer_delete
  1339. // TODO(flysand): clock_settime
  1340. // TODO(flysand): clock_gettime
  1341. // TODO(flysand): clock_getres
  1342. // TODO(flysand): clock_nanosleep
  1343. /// Exit the thread group
  1344. /// Available since Linux 2.6
  1345. exit_group :: proc "contextless" (code: i32) -> ! {
  1346. syscall(SYS_exit_group, code)
  1347. unreachable()
  1348. }
  1349. // TODO(flysand): epoll_wait
  1350. // TODO(flysand): epoll_ctl
  1351. // TODO(flysand): tgkill
  1352. // TODO(flysand): utimes
  1353. // TODO(flysand): vserver
  1354. // TODO(flysand): mbind
  1355. // TODO(flysand): set_mempolicy
  1356. // TODO(flysand): get_mempolicy
  1357. // TODO(flysand): mq_open
  1358. // TODO(flysand): mq_unlink
  1359. // TODO(flysand): mq_timedsend
  1360. // TODO(flysand): mq_timedreceive
  1361. // TODO(flysand): mq_notify
  1362. // TODO(flysand): mq_getsetattr
  1363. // TODO(flysand): kexec_load
  1364. /// Wait on process, process group or pid file descriptor
  1365. /// Available since Linux 2.6.10
  1366. waitid :: proc "contextless" (id_type: Id_Type, id: Id, sig_info: ^Sig_Info, options: Wait_Options) -> (Errno) {
  1367. ret := syscall(SYS_waitid, id_type, id, sig_info, transmute(i32) options)
  1368. return Errno(-ret)
  1369. }
  1370. // TODO(flysand): add_key
  1371. // TODO(flysand): request_key
  1372. // TODO(flysand): keyctl
  1373. // TODO(flysand): ioprio_set
  1374. // TODO(flysand): ioprio_get
  1375. // TODO(flysand): inotify_init
  1376. // TODO(flysand): inotify_add_watch
  1377. // TODO(flysand): inotify_rm_watch
  1378. // TODO(flysand): migrate_pages
  1379. /// Open file at the specified file descriptor
  1380. /// Available since Linux 2.6.16
  1381. openat :: proc "contextless" (fd: Fd, name: cstring, flags: Open_Flags, mode: Mode = {}) -> (Fd, Errno) {
  1382. ret := syscall(SYS_openat, fd, AT_FDCWD, transmute(uintptr) name, transmute(u32) mode)
  1383. return errno_unwrap(ret, Fd)
  1384. }
  1385. /// Create a directory relative to specified dirfd
  1386. /// Available since Linux 2.6.16
  1387. mkdirat :: proc "contextless" (dirfd: Fd, name: cstring, mode: Mode) -> (Errno) {
  1388. ret := syscall(SYS_mkdirat, dirfd, cast(rawptr) name, transmute(u32) mode)
  1389. return Errno(-ret)
  1390. }
  1391. /// Create a special or ordinary file wrt given directory specified by dirfd
  1392. /// Available since Linux 2.6.16
  1393. mknodat :: proc "contextless" (dirfd: Fd, name: cstring, mode: Mode, dev: Dev) -> (Errno) {
  1394. ret := syscall(SYS_mknodat, dirfd, cast(rawptr) name, transmute(u32) mode, dev)
  1395. return Errno(-ret)
  1396. }
  1397. /// Change the ownership of the file specified relative to directory
  1398. /// Available since Linux 2.6.16
  1399. fchownat :: proc "contextless" (dirfd: Fd, name: cstring, uid: Uid, gid: Gid) -> (Errno) {
  1400. ret := syscall(SYS_fchownat, dirfd, cast(rawptr) name, uid, gid)
  1401. return Errno(-ret)
  1402. }
  1403. // TODO(flysand): futimesat
  1404. /// Get information about a file at a specific directory
  1405. /// Available since Linux 2.6.16
  1406. fstatat :: proc "contextless" (dirfd: Fd, name: cstring, stat: ^Stat, flags: FD_Flags) -> (Errno) {
  1407. when size_of(int) == 4 {
  1408. ret := syscall(SYS_fstatat64, dirfd, cast(rawptr) name, stat, transmute(i32) flags)
  1409. return Errno(-ret)
  1410. } else when ODIN_ARCH == .amd64 {
  1411. ret := syscall(SYS_newfstatat, dirfd, cast(rawptr) name, stat, transmute(i32) flags)
  1412. return Errno(-ret)
  1413. } else {
  1414. ret := syscall(SYS_fstatat, dirfd, cast(rawptr) name, stat, transmute(i32) flags)
  1415. return Errno(-ret)
  1416. }
  1417. }
  1418. /// Remove a directory entry relative to a directory file descriptor
  1419. /// Available since Linux 2.6.16
  1420. unlinkat :: proc "contextless" (dirfd: Fd, name: cstring, flags: FD_Flags) -> (Errno) {
  1421. ret := syscall(SYS_unlinkat, dirfd, cast(rawptr) name, transmute(i32) flags)
  1422. return Errno(-ret)
  1423. }
  1424. /// Rename the file with names relative to the specified dirfd's
  1425. /// Available since Linux 2.6.16
  1426. renameat :: proc "contextless" (oldfd: Fd, old: cstring, newfd: Fd, new: cstring) -> (Errno) {
  1427. ret := syscall(SYS_renameat, oldfd, cast(rawptr) old, newfd, cast(rawptr) new)
  1428. return Errno(-ret)
  1429. }
  1430. /// Creates a hard link on a file relative to specified dirfd
  1431. /// Available since Linux 2.6.16
  1432. linkat :: proc "contextless" (target_dirfd: Fd, oldpath: cstring, link_dirfd: Fd, link: cstring, flags: FD_Flags) -> (Errno) {
  1433. ret := syscall(SYS_linkat, target_dirfd, cast(rawptr) oldpath, link_dirfd, cast(rawptr) link, transmute(i32) flags)
  1434. return Errno(-ret)
  1435. }
  1436. /// Create a symbolic link at specified dirfd
  1437. /// Available since Linux 2.6.16
  1438. symlinkat :: proc "contextless" (dirfd: Fd, target: cstring, linkpath: cstring) -> (Errno) {
  1439. ret := syscall(SYS_symlinkat, dirfd, cast(rawptr) target, cast(rawptr) linkpath)
  1440. return Errno(-ret)
  1441. }
  1442. /// Read the value of a symbolic link at given dirfd
  1443. /// Available since Linux 2.6.16
  1444. readlinkat :: proc "contextless" (dirfd: Fd, name: cstring, buf: []u8) -> (int, Errno) {
  1445. ret := syscall(SYS_readlinkat, dirfd, cast(rawptr) name, raw_data(buf), len(buf))
  1446. return errno_unwrap(ret, int)
  1447. }
  1448. /// Change the file mode at a specified file descriptor
  1449. /// Available since Linux 2.6.16
  1450. fchmodat :: proc "contextless" (dirfd: Fd, name: cstring, mode: Mode, flags: FD_Flags) -> (Errno) {
  1451. ret := syscall(SYS_fchmodat, cast(rawptr) name, transmute(u32) mode, transmute(i32) flags)
  1452. return Errno(-ret)
  1453. }
  1454. /// Checks the user permissions for a file at specified dirfd
  1455. /// Available since Linux 2.6.16
  1456. faccessat :: proc "contextless" (dirfd: Fd, name: cstring, mode: Mode = F_OK) -> (bool, Errno) {
  1457. ret := syscall(SYS_faccessat, dirfd, cast(rawptr) name, transmute(u32) mode)
  1458. return errno_unwrap(ret, bool)
  1459. }
  1460. // TODO(flysand): pselect6
  1461. /// Wait for events on a file descriptor
  1462. /// Available since Linux 2.6.16
  1463. ppoll :: proc "contextless" (fds: []Poll_Fd, timeout: ^Time_Spec, sigmask: ^Sig_Set) -> (Errno) {
  1464. when size_of(int) == 8 {
  1465. ret := syscall(SYS_ppoll, raw_data(fds), len(fds), timeout, sigmask, size_of(Sig_Set))
  1466. return Errno(-ret)
  1467. } else {
  1468. ret := syscall(SYS_ppoll_time64, raw_data(fds), len(fds), timeout, sigmask, size_of(Sig_Set))
  1469. return Errno(-ret)
  1470. }
  1471. }
  1472. // TODO(flysand): unshare
  1473. // TODO(flysand): set_robust_list
  1474. // TODO(flysand): get_robust_list
  1475. // TODO(flysand): splice
  1476. // TODO(flysand): tee
  1477. // TODO(flysand): sync_file_range
  1478. // TODO(flysand): vmsplice
  1479. // TODO(flysand): move_pages
  1480. /// Change file timestamps with nanosecond precision
  1481. /// Available since Linux 2.6.22
  1482. utimensat :: proc "contextless" (dirfd: Fd, name: cstring, timespec: ^Time_Spec, flags: FD_Flags) -> (Errno) {
  1483. ret := syscall(SYS_utimensat, dirfd, cast(rawptr) name, timespec, transmute(i32) flags)
  1484. return Errno(-ret)
  1485. }
  1486. // TODO(flysand): epoll_pwait
  1487. // TODO(flysand): signalfd
  1488. // TODO(flysand): timerfd_create
  1489. // TODO(flysand): eventfd
  1490. // TODO(flysand): fallocate
  1491. // TODO(flysand): timerfd_settime
  1492. // TODO(flysand): timerfd_gettime
  1493. // TODO(flysand): accept4
  1494. // TODO(flysand): signalfd4
  1495. // TODO(flysand): eventfd2
  1496. // TODO(flysand): epoll_create1
  1497. /// Adjust an existing file descriptor to point to the same file as `old`
  1498. /// In addition to dup2 allows to pass O_CLOEXEC flag
  1499. /// Available since Linux 2.6.27
  1500. dup3 :: proc "contextless" (old: Fd, new: Fd, flags: Open_Flags) -> (Fd, Errno) {
  1501. ret := syscall(SYS_dup3, old, new, transmute(i32) flags)
  1502. return errno_unwrap(ret, Fd)
  1503. }
  1504. // TODO(flysand): inotify_init1
  1505. // TODO(flysand): preadv
  1506. // TODO(flysand): pwritev
  1507. /// Send signal information to a thread
  1508. /// Available since Linux 2.2
  1509. rt_tgsigqueueinfo :: proc "contextless" (tgid: Pid, pid: Pid, sig: Signal, si: ^Sig_Info) -> (Errno) {
  1510. ret := syscall(SYS_rt_tgsigqueueinfo, tgid, pid, sig, si)
  1511. return Errno(-ret)
  1512. }
  1513. /// Set up performance monitoring
  1514. /// Available since Linux 2.6.31
  1515. perf_event_open :: proc "contextless" (attr: ^Perf_Event_Attr, pid: Pid, cpu: int, group_fd: Fd, flags: Perf_Flags = {}) -> (Fd, Errno) {
  1516. ret := syscall(SYS_perf_event_open, attr, pid, cpu, group_fd, transmute(uint) flags)
  1517. return errno_unwrap(ret, Fd)
  1518. }
  1519. // TODO(flysand): recvmmsg
  1520. // TODO(flysand): fanotify_init
  1521. // TODO(flysand): fanotify_mark
  1522. // TODO(flysand): prlimit64
  1523. // TODO(flysand): name_to_handle_at
  1524. // TODO(flysand): open_by_handle_at
  1525. // TODO(flysand): clock_adjtime
  1526. // TODO(flysand): syncfs
  1527. // TODO(flysand): sendmmsg
  1528. // TODO(flysand): setns
  1529. // TODO(flysand): getcpu
  1530. // TODO(flysand): process_vm_readv
  1531. // TODO(flysand): process_vm_writev
  1532. // TODO(flysand): kcmp
  1533. // TODO(flysand): finit_module
  1534. // TODO(flysand): sched_setattr
  1535. // TODO(flysand): sched_getattr
  1536. /// Rename the file with names relative to the specified dirfd's with other options
  1537. /// Available since Linux 3.15
  1538. renameat2 :: proc "contextless" (oldfd: Fd, old: cstring, newfd: Fd, new: cstring, flags: Rename_Flags) -> (Errno) {
  1539. ret := syscall(SYS_renameat2, oldfd, cast(rawptr) old, newfd, cast(rawptr) new, transmute(u32) flags)
  1540. return Errno(-ret)
  1541. }
  1542. // TODO(flysand): seccomp
  1543. getrandom :: proc "contextless" (buf: []u8, flags: Get_Random_Flags) -> (int, Errno) {
  1544. ret := syscall(SYS_getrandom, raw_data(buf), len(buf), transmute(i32) flags)
  1545. return errno_unwrap(ret, int)
  1546. }
  1547. // TODO(flysand): memfd_create
  1548. // TODO(flysand): kexec_file_load
  1549. // TODO(flysand): bpf
  1550. // TODO(flysand): execveat
  1551. // TODO(flysand): userfaultfd
  1552. // TODO(flysand): membarrier
  1553. // TODO(flysand): mlock2
  1554. // TODO(flysand): copy_file_range
  1555. // TODO(flysand): preadv2
  1556. // TODO(flysand): pwritev2
  1557. // TODO(flysand): pkey_mprotect
  1558. // TODO(flysand): pkey_alloc
  1559. // TODO(flysand): pkey_free
  1560. /// Query extended information about the file
  1561. ///
  1562. /// The file can be specified as:
  1563. /// absolute pathname: `dir` parameter is ignored
  1564. /// relatvie pathname: `dir` parameter specifies the base directory's fd
  1565. /// file descriptor: `AT_EMPTY_PATH` is passed in flags, pathname is empty, `dir` specifies the file descriptor
  1566. ///
  1567. /// Available since Linux 4.11
  1568. statx :: proc "contextless" (dir: Fd, pathname: cstring, flags: FD_Flags, mask: Statx_Mask, statx: ^Statx) -> (Errno) {
  1569. ret := syscall(SYS_statx, dir, transmute(uintptr) pathname, transmute(i32) flags, transmute(u32) mask, statx)
  1570. return Errno(-ret)
  1571. }
  1572. // TODO(flysand): io_pgetevents
  1573. // TODO(flysand): rseq
  1574. // TODO(flysand): pidfd_send_signal
  1575. // TODO(flysand): io_uring_setup
  1576. // TODO(flysand): io_uring_enter
  1577. // TODO(flysand): io_uring_register
  1578. // TODO(flysand): open_tree
  1579. // TODO(flysand): move_mount
  1580. // TODO(flysand): fsopen
  1581. // TODO(flysand): fsconfig
  1582. // TODO(flysand): fsmount
  1583. // TODO(flysand): fspick
  1584. /// Creates a new PID file descriptor
  1585. /// The process identified by `pid` must be a pid group leader
  1586. /// The returned `pidfd` has `CLOEXEC` semantics
  1587. /// Available since Linux 5.3
  1588. pidfd_open :: proc "contextless" (pid: Pid, flags: Pid_FD_Flags) -> (Pid_FD, Errno) {
  1589. ret := syscall(SYS_pidfd_open, pid, transmute(i32) flags)
  1590. return errno_unwrap(ret, Pid_FD)
  1591. }
  1592. // TODO(flysand): clone3 (probably not this PR)
  1593. /// Close the range of files as an atomic operation
  1594. /// The range of file descriptors is inclusive, and may contain invalid file descriptors
  1595. /// Available since Linux 5.9
  1596. close_range :: proc "contextless" (lo: Fd, hi: Fd, flags: Close_Range_Flags) -> (Errno) {
  1597. ret := syscall(SYS_close_range, lo, hi, transmute(u32) flags)
  1598. return Errno(-ret)
  1599. }
  1600. // TODO(flysand): openat2
  1601. /// Get a file descriptor from another process
  1602. /// `fd` refers to a file descriptor number to get
  1603. /// `flags` must be zero
  1604. /// Available since Linux 5.3
  1605. pidfd_getfd :: proc "contextless" (pidfd: Pid_FD, fd: Fd, flags: i32 = 0) -> (Fd, Errno) {
  1606. ret := syscall(SYS_pidfd_getfd, pidfd, fd, flags)
  1607. return errno_unwrap(ret, Fd)
  1608. }
  1609. /// Checks the user permissions for a file at specified dirfd (with flags)
  1610. /// Available since Linux 5.8
  1611. faccessat2 :: proc "contextless" (dirfd: Fd, name: cstring, mode: Mode = F_OK, flags: FD_Flags = FD_Flags{}) -> (bool, Errno) {
  1612. ret := syscall(SYS_faccessat2, dirfd, cast(rawptr) name, transmute(u32) mode, transmute(i32) flags)
  1613. return errno_unwrap(ret, bool)
  1614. }
  1615. // TODO(flysand): process_madvise
  1616. // TODO(flysand): epoll_pwait2
  1617. // TODO(flysand): mount_setattr
  1618. // TODO(flysand): quotactl_fd
  1619. // TODO(flysand): landlock_create_ruleset
  1620. // TODO(flysand): landlock_add_rule
  1621. // TODO(flysand): landlock_restrict_self
  1622. // TODO(flysand): memfd_secret
  1623. // TODO(flysand): process_mrelease
  1624. // TODO(flysand): futex_waitv
  1625. // TODO(flysand): set_mempolicy_home_node
  1626. // TODO(flysand): cachestat
  1627. // TODO(flysand): fchmodat2
  1628. // TODO(flysand): map_shadow_stack