pipe_posix.odin 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. #+private
  2. #+build darwin, netbsd, freebsd, openbsd
  3. package os2
  4. import "core:sys/posix"
  5. import "core:strings"
  6. _pipe :: proc() -> (r, w: ^File, err: Error) {
  7. fds: [2]posix.FD
  8. if posix.pipe(&fds) != .OK {
  9. err = _get_platform_error()
  10. return
  11. }
  12. if posix.fcntl(fds[0], .SETFD, i32(posix.FD_CLOEXEC)) == -1 {
  13. err = _get_platform_error()
  14. return
  15. }
  16. if posix.fcntl(fds[1], .SETFD, i32(posix.FD_CLOEXEC)) == -1 {
  17. err = _get_platform_error()
  18. return
  19. }
  20. r = __new_file(fds[0])
  21. ri := (^File_Impl)(r.impl)
  22. rname := strings.builder_make(file_allocator())
  23. // TODO(laytan): is this on all the posix targets?
  24. strings.write_string(&rname, "/dev/fd/")
  25. strings.write_int(&rname, int(fds[0]))
  26. ri.name = strings.to_string(rname)
  27. ri.cname = strings.to_cstring(&rname)
  28. w = __new_file(fds[1])
  29. wi := (^File_Impl)(w.impl)
  30. wname := strings.builder_make(file_allocator())
  31. // TODO(laytan): is this on all the posix targets?
  32. strings.write_string(&wname, "/dev/fd/")
  33. strings.write_int(&wname, int(fds[1]))
  34. wi.name = strings.to_string(wname)
  35. wi.cname = strings.to_cstring(&wname)
  36. return
  37. }
  38. @(require_results)
  39. _pipe_has_data :: proc(r: ^File) -> (ok: bool, err: Error) {
  40. if r == nil || r.impl == nil {
  41. return false, nil
  42. }
  43. fd := __fd(r)
  44. poll_fds := []posix.pollfd {
  45. posix.pollfd {
  46. fd = fd,
  47. events = {.IN, .HUP},
  48. },
  49. }
  50. n := posix.poll(raw_data(poll_fds), u32(len(poll_fds)), 0)
  51. if n < 0 {
  52. return false, _get_platform_error()
  53. } else if n != 1 {
  54. return false, nil
  55. }
  56. pipe_events := poll_fds[0].revents
  57. if pipe_events >= {.IN} {
  58. return true, nil
  59. }
  60. if pipe_events >= {.HUP} {
  61. return false, .Broken_Pipe
  62. }
  63. return false, nil
  64. }