fcntl.odin 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. #+build linux, darwin, openbsd, freebsd, netbsd
  2. package posix
  3. import "core:c"
  4. when ODIN_OS == .Darwin {
  5. foreign import lib "system:System.framework"
  6. } else {
  7. foreign import lib "system:c"
  8. }
  9. // fcntl.h - file control options
  10. foreign lib {
  11. /*
  12. Implemented as `return open(path, O_WRONLY|O_CREAT|O_TRUNC, mode);`
  13. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/creat.html ]]
  14. */
  15. creat :: proc(path: cstring, mode: mode_t) -> FD ---
  16. /*
  17. Perform the operations on open files.
  18. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/fcntl.html ]]
  19. */
  20. fcntl :: proc(fd: FD, cmd: FCNTL_Cmd, #c_vararg args: ..any) -> c.int ---
  21. /*
  22. Establish the connection between a file and a file descriptor.
  23. It shall create an open file description that refers to a file and a file descriptor that
  24. refers to that open file description. The file descriptor is used by other I/O functions to
  25. refer to that file.
  26. The path argument points to a pathname naming the file
  27. Returns: -1 on failure (setting errno), a file descriptor on success.
  28. Example:
  29. // The following example opens the file /tmp/file, either by creating it (if it does not already exist),
  30. // or by truncating its length to 0 (if it does exist). In the former case, if the call creates a new file,
  31. // the access permission bits in the file mode of the file are set to permit reading and writing by the owner,
  32. // and to permit reading only by group members and others.
  33. fd := posix.open("/tmp/file", { .WRONLY, .CREAT, .TRUNC }, { .IRUSR, .IWUSR, .IRGRP, .IROTH })
  34. // The following example uses the open() function to try to create the LOCKFILE file and open it for writing.
  35. // Since the open() function specifies the O_EXCL flag, the call fails if the file already exists.
  36. // In that case, the program assumes that someone else is updating the password file and exits.
  37. fd := posix.open("/etc/ptmp", { .WRONLY, .CREAT, .EXCL }, { .IRUSR, .IWUSR, .IRGRP, .IROTH })
  38. if fd == -1 {
  39. fmt.println("cannot open /etc/ptmp")
  40. }
  41. // The following example opens a file for writing, creating the file if it does not already exist.
  42. // If the file does exist, the system truncates the file to zero bytes.
  43. fd := posix.open("/etc/ptmp", { .WRONLY, .CREAT, .TRUNC }, { .IRUSR, .IWUSR, .IRGRP, .IROTH })
  44. if fd == -1 {
  45. fmt.println("cannot open output file")
  46. }
  47. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html ]]
  48. */
  49. open :: proc(path: cstring, flags: O_Flags, #c_vararg mode: ..mode_t) -> FD ---
  50. /*
  51. Equivalent to the open() function except in the case where path specifies a relative path.
  52. In this case the file to be opened is determined relative to the directory associated with the
  53. file descriptor fd instead of the current working directory.
  54. Returns: -1 on failure (setting errno), a file descriptor on success.
  55. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html ]]
  56. */
  57. openat :: proc(fd: FD, path: cstring, flags: O_Flags, mode: mode_t = {}) -> FD ---
  58. }
  59. FCNTL_Cmd :: enum c.int {
  60. DUPFD = F_DUPFD,
  61. DUPFD_CLOEXEC = F_DUPFD_CLOEXEC,
  62. GETFD = F_GETFD,
  63. SETFD = F_SETFD,
  64. GETFL = F_GETFL,
  65. SETFL = F_SETFL,
  66. GETLK = F_GETLK,
  67. SETLK = F_SETLK,
  68. SETLKW = F_SETLKW,
  69. GETOWN = F_GETOWN,
  70. SETOWN = F_SETOWN,
  71. }
  72. Lock_Type :: enum c.short {
  73. RDLCK = F_RDLCK,
  74. UNLCK = F_UNLCK,
  75. WRLCK = F_WRLCK,
  76. }
  77. O_Flag_Bits :: enum c.int {
  78. // Sets FD_CLOEXEC on the file descriptor.
  79. CLOEXEC = log2(O_CLOEXEC),
  80. // If not exists, combined with DIRECTORY will cause creation of a directory, otherwise a regular file.
  81. CREAT = log2(O_CREAT),
  82. // Fails if the opened descriptor would not be a directory.
  83. DIRECTORY = log2(O_DIRECTORY),
  84. // If combined with CREAT, causes a failure if the file already exists.
  85. EXCL = log2(O_EXCL),
  86. // If terminal device, do not make it the controlling terminal for the process.
  87. NOCTTY = log2(O_NOCTTY),
  88. // Don't follow symbolic links, fail with errno ELOOP.
  89. NOFOLLOW = log2(O_NOFOLLOW),
  90. // If exists and regular, truncate the length to 0.
  91. TRUNC = log2(O_TRUNC),
  92. // NOTE: use with `posix.O_TTY_INIT + { .OTHER_FLAG, .OTHER_FLAG }`, unfortunately can't be in
  93. // this bit set enum because it is 0 on some platforms and a value on others.
  94. // TTY_INIT = O_TTY_INIT,
  95. // Set file offset to end of file prior to each write.
  96. APPEND = log2(O_APPEND),
  97. // Write I/O shall complete as defined by synchronized I/O data integrity completion.
  98. DSYNC = log2(O_DSYNC),
  99. // Causes nonblocking behaviour in various situations.
  100. NONBLOCK = log2(O_NONBLOCK),
  101. // Write I/O shall complete as defined by synchronized I/O file integrity completion.
  102. SYNC = log2(O_SYNC),
  103. // NOTE: use with `posix.O_RSYNC + { .OTHER_FLAG, .OTHER_FLAG }`, unfortunately can't be in
  104. // this bit set enum because it is 0 on some platforms and a value on others.
  105. // RSYNC = O_RSYNC,
  106. // Execute only.
  107. EXEC = log2(O_EXEC),
  108. // Reading and writing.
  109. RDWR = log2(O_RDWR),
  110. // Writing only.
  111. WRONLY = log2(O_WRONLY),
  112. // Reading only.
  113. // RDONLY = 0, // Default
  114. }
  115. O_Flags :: bit_set[O_Flag_Bits; c.int]
  116. O_ACCMODE :: O_Flags{ .EXEC, .RDWR, .WRONLY }
  117. AT_Flag_Bits :: enum c.int {
  118. EACCESS = log2(AT_EACCESS),
  119. SYMLINK_NOFOLLOW = log2(AT_SYMLINK_NOFOLLOW),
  120. SYMLINK_FOLLOW = log2(AT_SYMLINK_FOLLOW),
  121. REMOVEDIR = log2(AT_REMOVEDIR),
  122. }
  123. AT_Flags :: bit_set[AT_Flag_Bits; c.int]
  124. when ODIN_OS == .Darwin {
  125. off_t :: distinct c.int64_t
  126. pid_t :: distinct c.int32_t
  127. F_DUPFD :: 0
  128. F_DUPFD_CLOEXEC :: 67
  129. F_GETFD :: 1
  130. F_SETFD :: 2
  131. F_GETFL :: 3
  132. F_SETFL :: 4
  133. F_GETLK :: 7
  134. F_SETLK :: 8
  135. F_SETLKW :: 9
  136. F_GETOWN :: 5
  137. F_SETOWN :: 6
  138. FD_CLOEXEC :: 1
  139. F_RDLCK :: 1
  140. F_UNLCK :: 2
  141. F_WRLCK :: 3
  142. O_CLOEXEC :: 0x01000000
  143. O_CREAT :: 0x00000200
  144. O_DIRECTORY :: 0x00100000
  145. O_EXCL :: 0x00000800
  146. O_NOCTTY :: 0x00020000
  147. O_NOFOLLOW :: 0x00000100
  148. O_TRUNC :: 0x00000400
  149. _O_TTY_INIT :: 0
  150. O_TTY_INIT :: O_Flags{}
  151. O_APPEND :: 0x00000008
  152. O_DSYNC :: 0x00400000
  153. O_NONBLOCK :: 0x00000004
  154. O_SYNC :: 0x0080
  155. _O_RSYNC :: 0
  156. O_RSYNC :: O_Flags{}
  157. O_EXEC :: 0x40000000
  158. O_RDONLY :: 0
  159. O_RDWR :: 0x0002
  160. O_WRONLY :: 0x0001
  161. _O_SEARCH :: O_EXEC | O_DIRECTORY
  162. O_SEARCH :: O_Flags{.EXEC, .DIRECTORY}
  163. AT_FDCWD: FD: -2
  164. AT_EACCESS :: 0x0010
  165. AT_SYMLINK_NOFOLLOW :: 0x0020
  166. AT_SYMLINK_FOLLOW :: 0x0040
  167. AT_REMOVEDIR :: 0x0080
  168. flock :: struct {
  169. l_start: off_t, /* [PSX] relative offset in bytes */
  170. l_len: off_t, /* [PSX] size; if 0 then until EOF */
  171. l_pid: pid_t, /* [PSX] process ID of the process holding the lock */
  172. l_type: Lock_Type, /* [PSX] type of lock */
  173. l_whence: c.short, /* [PSX] flag (Whence) of starting offset */
  174. }
  175. } else when ODIN_OS == .FreeBSD {
  176. off_t :: distinct c.int64_t
  177. pid_t :: distinct c.int32_t
  178. F_DUPFD :: 0
  179. F_DUPFD_CLOEXEC :: 17
  180. F_GETFD :: 1
  181. F_SETFD :: 2
  182. F_GETFL :: 3
  183. F_SETFL :: 4
  184. F_GETLK :: 7
  185. F_SETLK :: 8
  186. F_SETLKW :: 9
  187. F_GETOWN :: 5
  188. F_SETOWN :: 6
  189. FD_CLOEXEC :: 1
  190. F_RDLCK :: 1
  191. F_UNLCK :: 2
  192. F_WRLCK :: 3
  193. O_CLOEXEC :: 0x00100000
  194. O_CREAT :: 0x0200
  195. O_DIRECTORY :: 0x00020000
  196. O_EXCL :: 0x0800
  197. O_NOCTTY :: 0x8000
  198. O_NOFOLLOW :: 0x0100
  199. O_TRUNC :: 0x0400
  200. _O_TTY_INIT :: 0x00080000
  201. O_TTY_INIT :: O_Flags{O_Flag_Bits(log2(_O_TTY_INIT))}
  202. O_APPEND :: 0x0008
  203. O_DSYNC :: 0x01000000
  204. O_NONBLOCK :: 0x0004
  205. O_SYNC :: 0x0080
  206. _O_RSYNC :: 0
  207. O_RSYNC :: O_Flags{} // NOTE: not defined in headers
  208. O_EXEC :: 0x00040000
  209. O_RDONLY :: 0
  210. O_RDWR :: 0x0002
  211. O_WRONLY :: 0x0001
  212. _O_SEARCH :: O_EXEC
  213. O_SEARCH :: O_Flags{ .EXEC }
  214. AT_FDCWD: FD: -100
  215. AT_EACCESS :: 0x0100
  216. AT_SYMLINK_NOFOLLOW :: 0x0200
  217. AT_SYMLINK_FOLLOW :: 0x0400
  218. AT_REMOVEDIR :: 0x0800
  219. flock :: struct {
  220. l_start: off_t, /* [PSX] relative offset in bytes */
  221. l_len: off_t, /* [PSX] size; if 0 then until EOF */
  222. l_pid: pid_t, /* [PSX] process ID of the process holding the lock */
  223. l_type: Lock_Type, /* [PSX] type of lock */
  224. l_whence: c.short, /* [PSX] flag (Whence) of starting offset */
  225. l_sysid: c.int,
  226. }
  227. } else when ODIN_OS == .NetBSD {
  228. off_t :: distinct c.int64_t
  229. pid_t :: distinct c.int32_t
  230. F_DUPFD :: 0
  231. F_DUPFD_CLOEXEC :: 12
  232. F_GETFD :: 1
  233. F_SETFD :: 2
  234. F_GETFL :: 3
  235. F_SETFL :: 4
  236. F_GETLK :: 7
  237. F_SETLK :: 8
  238. F_SETLKW :: 9
  239. F_GETOWN :: 5
  240. F_SETOWN :: 6
  241. FD_CLOEXEC :: 1
  242. F_RDLCK :: 1
  243. F_UNLCK :: 2
  244. F_WRLCK :: 3
  245. O_CLOEXEC :: 0x00400000
  246. O_CREAT :: 0x0200
  247. O_DIRECTORY :: 0x0020000
  248. O_EXCL :: 0x0800
  249. O_NOCTTY :: 0x8000
  250. O_NOFOLLOW :: 0x0100
  251. O_TRUNC :: 0x0400
  252. _O_TTY_INIT :: 0
  253. O_TTY_INIT :: O_Flags{} // NOTE: not defined in the headers
  254. O_APPEND :: 0x0008
  255. O_DSYNC :: 0x010000
  256. O_NONBLOCK :: 0x0004
  257. O_SYNC :: 0x0080
  258. _O_RSYNC :: 0x0002
  259. O_RSYNC :: O_Flags{O_Flag_Bits(log2(_O_RSYNC))}
  260. O_EXEC :: 0x04000000
  261. O_RDONLY :: 0
  262. O_RDWR :: 0x0002
  263. O_WRONLY :: 0x0001
  264. _O_SEARCH :: 0x00800000
  265. O_SEARCH :: O_Flags{O_Flag_Bits(log2(_O_SEARCH))}
  266. AT_FDCWD: FD: -100
  267. AT_EACCESS :: 0x100
  268. AT_SYMLINK_NOFOLLOW :: 0x200
  269. AT_SYMLINK_FOLLOW :: 0x400
  270. AT_REMOVEDIR :: 0x800
  271. flock :: struct {
  272. l_start: off_t, /* [PSX] relative offset in bytes */
  273. l_len: off_t, /* [PSX] size; if 0 then until EOF */
  274. l_pid: pid_t, /* [PSX] process ID of the process holding the lock */
  275. l_type: Lock_Type, /* [PSX] type of lock */
  276. l_whence: c.short, /* [PSX] flag (Whence) of starting offset */
  277. }
  278. } else when ODIN_OS == .OpenBSD {
  279. off_t :: distinct c.int64_t
  280. pid_t :: distinct c.int32_t
  281. F_DUPFD :: 0
  282. F_DUPFD_CLOEXEC :: 10
  283. F_GETFD :: 1
  284. F_SETFD :: 2
  285. F_GETFL :: 3
  286. F_SETFL :: 4
  287. F_GETLK :: 7
  288. F_SETLK :: 8
  289. F_SETLKW :: 9
  290. F_GETOWN :: 5
  291. F_SETOWN :: 6
  292. FD_CLOEXEC :: 1
  293. F_RDLCK :: 1
  294. F_UNLCK :: 2
  295. F_WRLCK :: 3
  296. O_CLOEXEC :: 0x10000
  297. O_CREAT :: 0x0200
  298. O_DIRECTORY :: 0x20000
  299. O_EXCL :: 0x0800
  300. O_NOCTTY :: 0x8000
  301. O_NOFOLLOW :: 0x0100
  302. O_TRUNC :: 0x0400
  303. _O_TTY_INIT :: 0
  304. O_TTY_INIT :: O_Flags{} // NOTE: not defined in the headers
  305. O_APPEND :: 0x0008
  306. O_DSYNC :: 0x010000
  307. O_NONBLOCK :: 0x0004
  308. O_SYNC :: 0x0080
  309. _O_RSYNC :: O_SYNC
  310. O_RSYNC :: O_Flags{.SYNC}
  311. O_EXEC :: 0x04000000 // NOTE: not defined in the headers
  312. O_RDONLY :: 0
  313. O_RDWR :: 0x0002
  314. O_WRONLY :: 0x0001
  315. _O_SEARCH :: 0
  316. O_SEARCH :: O_Flags{} // NOTE: not defined in the headers
  317. AT_FDCWD: FD: -100
  318. AT_EACCESS :: 0x01
  319. AT_SYMLINK_NOFOLLOW :: 0x02
  320. AT_SYMLINK_FOLLOW :: 0x04
  321. AT_REMOVEDIR :: 0x08
  322. flock :: struct {
  323. l_start: off_t, /* [PSX] relative offset in bytes */
  324. l_len: off_t, /* [PSX] size; if 0 then until EOF */
  325. l_pid: pid_t, /* [PSX] process ID of the process holding the lock */
  326. l_type: Lock_Type, /* [PSX] type of lock */
  327. l_whence: c.short, /* [PSX] flag (Whence) of starting offset */
  328. }
  329. } else when ODIN_OS == .Linux {
  330. off_t :: distinct c.int64_t
  331. pid_t :: distinct c.int
  332. F_DUPFD :: 0
  333. F_GETFD :: 1
  334. F_SETFD :: 2
  335. F_GETFL :: 3
  336. F_SETFL :: 4
  337. F_GETLK :: 5
  338. F_SETLK :: 6
  339. F_SETLKW :: 7
  340. F_SETOWN :: 8
  341. F_GETOWN :: 9
  342. F_RDLCK :: 0
  343. F_UNLCK :: 2
  344. F_WRLCK :: 1
  345. F_DUPFD_CLOEXEC :: 1030
  346. FD_CLOEXEC :: 1
  347. O_CREAT :: 0o0_000_100
  348. O_EXCL :: 0o0_000_200
  349. O_NOCTTY :: 0o0_000_400
  350. O_TRUNC :: 0o0_001_000
  351. O_DIRECTORY :: 0o0_200_000
  352. O_NOFOLLOW :: 0o0_400_000
  353. O_CLOEXEC :: 0o2_000_000
  354. _O_TTY_INIT :: 0
  355. O_TTY_INIT :: O_Flags{}
  356. O_APPEND :: 0o0_002_000
  357. O_NONBLOCK :: 0o0_004_000
  358. O_DSYNC :: 0o0_010_000
  359. O_SYNC :: 0o4_010_000
  360. _O_RSYNC :: 0
  361. O_RSYNC :: O_Flags{}
  362. O_EXEC :: 0x04000000 // NOTE: not defined in the headers
  363. O_RDONLY :: 0
  364. O_WRONLY :: 0o1
  365. O_RDWR :: 0o2
  366. _O_SEARCH :: 0
  367. O_SEARCH :: O_Flags{}
  368. AT_FDCWD: FD: -100
  369. AT_EACCESS :: 0x200
  370. AT_SYMLINK_NOFOLLOW :: 0x100
  371. AT_SYMLINK_FOLLOW :: 0x400
  372. AT_REMOVEDIR :: 0x200
  373. flock :: struct {
  374. l_type: Lock_Type, /* [PSX] type of lock. */
  375. l_whence: c.short, /* [PSX] flag (Whence) of starting offset. */
  376. l_start: off_t, /* [PSX] relative offset in bytes. */
  377. l_len: off_t, /* [PSX] size; if 0 then until EOF. */
  378. l_pid: pid_t, /* [PSX] process ID of the process holding the lock. */
  379. }
  380. }