xnu_system_call_helpers.odin 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. package darwin
  2. import "core:c"
  3. import "base:runtime"
  4. // this package uses the sys prefix for the proc names to indicate that these aren't native syscalls but directly call such
  5. sys_write_string :: proc (fd: c.int, message: string) -> bool {
  6. return syscall_write(fd, raw_data(message), cast(u64)len(message))
  7. }
  8. Offset_From :: enum c.int {
  9. SEEK_SET = 0, // the offset is set to offset bytes.
  10. SEEK_CUR = 1, // the offset is set to its current location plus offset bytes.
  11. SEEK_END = 2, // the offset is set to the size of the file plus offset bytes.
  12. SEEK_HOLE = 3, // the offset is set to the start of the next hole greater than or equal to the supplied offset.
  13. SEEK_DATA = 4, // the offset is set to the start of the next non-hole file region greater than or equal to the supplied offset.
  14. }
  15. Open_Flags_Enum :: enum u8 {
  16. RDONLY, /* open for reading only */
  17. WRONLY, /* open for writing only */
  18. RDWR, /* open for reading and writing */
  19. NONBLOCK, /* no delay */
  20. APPEND, /* set append mode */
  21. CREAT, /* create if nonexistant */
  22. TRUNC, /* truncate to zero length */
  23. EXCL, /* error if already exists */
  24. SHLOCK, /* open with shared file lock */
  25. EXLOCK, /* open with exclusive file lock */
  26. DIRECTORY, /* restrict open to only directories */
  27. NOFOLLOW, /* don't follow symlinks */
  28. SYMLINK, /* allow open of a symlink */
  29. EVTONLY, /* descriptor requested for event notifications only */
  30. CLOEXEC, /* causes the descriptor to be closed if you use any of the exec like functions */
  31. NOFOLLOW_ANY, /* no symlinks allowed in path */
  32. }
  33. Open_Flags :: bit_set[Open_Flags_Enum; u16]
  34. Permission_Enum :: enum u8 {
  35. /* For owner */
  36. PERMISSION_OWNER_READ, /* R for owner */
  37. PERMISSION_OWNER_WRITE, /* W for owner */
  38. PERMISSION_OWNER_EXECUTE, /* X for owner */
  39. //IRWXU, /* RWX mask for owner */
  40. /* For group */
  41. PERMISSION_GROUP_READ, /* R for group */
  42. PERMISSION_GROUP_WRITE, /* W for group */
  43. PERMISSION_GROUP_EXECUTE, /* X for group */
  44. //IRWXG, /* RWX mask for group */
  45. /* For other */
  46. PERMISSION_OTHER_READ, /* R for other */
  47. PERMISSION_OTHER_WRITE, /* W for other */
  48. PERMISSION_OTHER_EXECUTE, /* X for other */
  49. //IRWXO, /* RWX mask for other */
  50. /* Special */
  51. PERMISSION_SET_USER_ON_EXECUTION, /* set user id on execution */
  52. PERMISSION_SET_GROUP_ON_EXECUTION, /* set group id on execution */
  53. /* ?? */
  54. PERMISSION_ISVTX, /* save swapped text even after use */
  55. }
  56. Permission :: bit_set[Permission_Enum; u16]
  57. PERMISSION_NONE_NONE :: Permission{}
  58. PERMISSION_OWNER_ALL :: Permission{.PERMISSION_OWNER_READ, .PERMISSION_OWNER_WRITE, .PERMISSION_OWNER_EXECUTE}
  59. PERMISSION_GROUP_ALL :: Permission{.PERMISSION_GROUP_READ, .PERMISSION_GROUP_WRITE, .PERMISSION_GROUP_EXECUTE}
  60. PERMISSION_OTHER_ALL :: Permission{.PERMISSION_OTHER_READ, .PERMISSION_OTHER_WRITE, .PERMISSION_OTHER_EXECUTE}
  61. PERMISSION_ALL_ALL :: PERMISSION_OWNER_ALL | PERMISSION_GROUP_ALL | PERMISSION_OTHER_ALL
  62. _sys_permission_mode :: #force_inline proc (mode: Permission) -> u32 {
  63. cflags: u32 = 0
  64. cflags |= PERMISSION_MASK_IRUSR * u32(Permission.PERMISSION_OWNER_READ in mode)
  65. cflags |= PERMISSION_MASK_IWUSR * u32(Permission.PERMISSION_OWNER_WRITE in mode)
  66. cflags |= PERMISSION_MASK_IXUSR * u32(Permission.PERMISSION_OWNER_WRITE in mode)
  67. cflags |= PERMISSION_MASK_IRGRP * u32(Permission.PERMISSION_GROUP_READ in mode)
  68. cflags |= PERMISSION_MASK_IWGRP * u32(Permission.PERMISSION_GROUP_WRITE in mode)
  69. cflags |= PERMISSION_MASK_IXGRP * u32(Permission.PERMISSION_GROUP_WRITE in mode)
  70. cflags |= PERMISSION_MASK_IROTH * u32(Permission.PERMISSION_OTHER_READ in mode)
  71. cflags |= PERMISSION_MASK_IWOTH * u32(Permission.PERMISSION_OTHER_WRITE in mode)
  72. cflags |= PERMISSION_MASK_IXOTH * u32(Permission.PERMISSION_OTHER_WRITE in mode)
  73. return cflags
  74. }
  75. @(private)
  76. clone_to_cstring :: proc(s: string, allocator: runtime.Allocator, loc := #caller_location) -> cstring {
  77. c := make([]byte, len(s)+1, allocator, loc)
  78. copy(c, s)
  79. c[len(s)] = 0
  80. return cstring(&c[0])
  81. }
  82. sys_open :: proc(path: string, oflag: Open_Flags, mode: Permission) -> (c.int, bool) {
  83. runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
  84. cmode: u32 = 0
  85. cflags: u32 = 0
  86. cpath: cstring = clone_to_cstring(path, context.temp_allocator)
  87. cflags = _sys_permission_mode(mode)
  88. cmode |= OPEN_FLAG_RDONLY * u32(Open_Flags.RDONLY in oflag)
  89. cmode |= OPEN_FLAG_WRONLY * u32(Open_Flags.WRONLY in oflag)
  90. cmode |= OPEN_FLAG_RDWR * u32(Open_Flags.RDWR in oflag)
  91. cmode |= OPEN_FLAG_NONBLOCK * u32(Open_Flags.NONBLOCK in oflag)
  92. cmode |= OPEN_FLAG_CREAT * u32(Open_Flags.CREAT in oflag)
  93. cmode |= OPEN_FLAG_APPEND * u32(Open_Flags.APPEND in oflag)
  94. cmode |= OPEN_FLAG_TRUNC * u32(Open_Flags.TRUNC in oflag)
  95. cmode |= OPEN_FLAG_EXCL * u32(Open_Flags.EXCL in oflag)
  96. cmode |= OPEN_FLAG_SHLOCK * u32(Open_Flags.SHLOCK in oflag)
  97. cmode |= OPEN_FLAG_EXLOCK * u32(Open_Flags.EXLOCK in oflag)
  98. cmode |= OPEN_FLAG_DIRECTORY * u32(Open_Flags.DIRECTORY in oflag)
  99. cmode |= OPEN_FLAG_NOFOLLOW * u32(Open_Flags.NOFOLLOW in oflag)
  100. cmode |= OPEN_FLAG_SYMLINK * u32(Open_Flags.SYMLINK in oflag)
  101. cmode |= OPEN_FLAG_EVTONLY * u32(Open_Flags.EVTONLY in oflag)
  102. cmode |= OPEN_FLAG_CLOEXEC * u32(Open_Flags.CLOEXEC in oflag)
  103. cmode |= OPEN_FLAG_NOFOLLOW_ANY * u32(Open_Flags.NOFOLLOW_ANY in oflag)
  104. result := syscall_open(cpath, cmode, cflags)
  105. state := result != -1
  106. if state && cflags != 0 {
  107. state = (syscall_fchmod(result, cflags) != -1)
  108. }
  109. return result * cast(c.int)state, state
  110. }
  111. sys_mkdir :: proc(path: string, mode: Permission) -> bool {
  112. runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
  113. cpath: cstring = clone_to_cstring(path, context.temp_allocator)
  114. cflags := _sys_permission_mode(mode)
  115. return syscall_mkdir(cpath, cflags) != -1
  116. }
  117. sys_mkdir_at :: proc(fd: c.int, path: string, mode: Permission) -> bool {
  118. runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
  119. cpath: cstring = clone_to_cstring(path, context.temp_allocator)
  120. cflags := _sys_permission_mode(mode)
  121. return syscall_mkdir_at(fd, cpath, cflags) != -1
  122. }
  123. sys_rmdir :: proc(path: string, mode: Permission) -> bool {
  124. runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
  125. cpath: cstring = clone_to_cstring(path, context.temp_allocator)
  126. cflags := _sys_permission_mode(mode)
  127. return syscall_rmdir(cpath, cflags) != -1
  128. }
  129. sys_rename :: proc(path: string, new_path: string) -> bool {
  130. runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
  131. cpath: cstring = clone_to_cstring(path, context.temp_allocator)
  132. cnpath: cstring = clone_to_cstring(new_path, context.temp_allocator)
  133. return syscall_rename(cpath, cnpath) != -1
  134. }
  135. sys_rename_at :: proc(fd: c.int, path: string, to_fd: c.int, new_path: string) -> bool {
  136. runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
  137. cpath: cstring = clone_to_cstring(path, context.temp_allocator)
  138. cnpath: cstring = clone_to_cstring(new_path, context.temp_allocator)
  139. return syscall_rename_at(fd, cpath, to_fd, cnpath) != -1
  140. }
  141. sys_lseek :: proc(fd: c.int, offset: i64, whence: Offset_From) -> i64 {
  142. return syscall_lseek(fd, offset, cast(c.int)whence)
  143. }
  144. sys_chmod :: proc(path: string, mode: Permission) -> bool {
  145. runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
  146. cpath: cstring = clone_to_cstring(path, context.temp_allocator)
  147. cmode := _sys_permission_mode(mode)
  148. return syscall_chmod(cpath, cmode) != -1
  149. }
  150. sys_lstat :: proc(path: string, status: ^stat) -> bool {
  151. runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
  152. cpath: cstring = clone_to_cstring(path, context.temp_allocator)
  153. return syscall_lstat(cpath, status) != -1
  154. }