os_essence.odin 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. package os
  2. OS :: "essence";
  3. foreign import api "system:api"
  4. Handle :: distinct int;
  5. Errno :: distinct int;
  6. O_RDONLY :: 0x00001;
  7. O_WRONLY :: 0x00002;
  8. O_RDWR :: 0x00003;
  9. O_CREATE :: 0x00040;
  10. O_EXCL :: 0x00080;
  11. O_TRUNC :: 0x00200;
  12. O_APPEND :: 0x00400;
  13. ERROR_NONE :: Errno(-1);
  14. ERROR_UNKNOWN_OPERATION_FAILURE :: Errno(-7);
  15. ERROR_PATH_NOT_WITHIN_MOUNTED_VOLUME :: Errno(-14);
  16. ERROR_PATH_NOT_FOUND :: Errno(-15);
  17. ERROR_FILE_EXISTS :: Errno(-19);
  18. ERROR_FILE_NOT_FOUND :: Errno(-20);
  19. ERROR_DRIVE_ERROR_FILE_DAMAGED :: Errno(-21);
  20. ERROR_ACCESS_NOT_WITHIN_FILE_BOUNDS :: Errno(-22);
  21. ERROR_ACCESS_DENIED :: Errno(-23);
  22. ERROR_FILE_IN_EXCLUSIVE_USE :: Errno(-24);
  23. ERROR_FILE_CANNOT_GET_EXCLUSIVE_USE :: Errno(-25);
  24. ERROR_INCORRECT_NODE_TYPE :: Errno(-26);
  25. ERROR_EVENT_NOT_SET :: Errno(-27);
  26. ERROR_TIMEOUT_REACHED :: Errno(-29);
  27. ERROR_REQUEST_CLOSED_BEFORE_COMPLETE :: Errno(-30);
  28. ERROR_NO_CHARACTER_AT_COORDINATE :: Errno(-31);
  29. ERROR_FILE_ON_READ_ONLY_VOLUME :: Errno(-32);
  30. ERROR_USER_CANCELED_IO :: Errno(-33);
  31. ERROR_DRIVE_CONTROLLER_REPORTED :: Errno(-35);
  32. ERROR_COULD_NOT_ISSUE_PACKET :: Errno(-36);
  33. ERROR_NOT_IMPLEMENTED :: Errno(1);
  34. OS_Node_Type :: enum i32 {
  35. File = 0,
  36. Directory = 1,
  37. }
  38. OS_Node_Information :: struct {
  39. handle: Handle,
  40. id: [16]byte,
  41. ntype: OS_Node_Type,
  42. size: i64,
  43. // Our additions..
  44. position: i64,
  45. }
  46. foreign api {
  47. @(link_name="OSPrintDirect") OSPrintDirect :: proc(str: ^u8, length: int) ---;
  48. @(link_name="malloc") OSMalloc :: proc(bytes: int) -> rawptr ---;
  49. @(link_name="free") OSFree :: proc(address: rawptr) ---;
  50. @(link_name="OSOpenNode") OSOpenNode :: proc(path: ^u8, path_length: int, flags: u64, information: ^OS_Node_Information) -> Errno ---;
  51. @(link_name="OSResizeFile") OSResizeFile :: proc(handle: Handle, new_size: u64) -> Errno ---;
  52. @(link_name="OSCloseHandle") OSCloseHandle :: proc(handle: Handle) ---;
  53. @(link_name="OSWriteFileSync") OSWriteFileSync :: proc(handle: Handle, offset: i64, size: i64, buffer: rawptr) -> i64 ---;
  54. @(link_name="OSReadFileSync") OSReadFileSync :: proc(handle: Handle, offset: i64, size: i64, buffer: rawptr) -> i64 ---;
  55. @(link_name="realloc") OSRealloc :: proc(address: rawptr, size: int) -> rawptr ---;
  56. @(link_name="OSGetThreadID") OSGetThreadID :: proc(handle: Handle) -> int ---;
  57. @(link_name="OSRefreshNodeInformation") OSRefreshNodeInformation :: proc(information: ^OS_Node_Information) ---;
  58. }
  59. stdin := Handle(-1); // Not implemented
  60. stdout := Handle(0);
  61. stderr := Handle(0);
  62. is_path_separator :: proc(r: rune) -> bool {
  63. return r == '/';
  64. }
  65. current_thread_id :: proc "contextless" () -> int {
  66. return OSGetThreadID(Handle(0x1000));
  67. }
  68. heap_alloc :: proc(size: int) -> rawptr {
  69. return OSMalloc(size);
  70. }
  71. heap_free :: proc(address: rawptr) {
  72. OSFree(address);
  73. }
  74. heap_resize :: proc(address: rawptr, new_size: int) -> rawptr {
  75. return OSRealloc(address, new_size);
  76. }
  77. open :: proc(path: string, mode: int = O_RDONLY, perm: u32 = 0) -> (Handle, Errno) {
  78. flags : u64 = 0;
  79. if mode & O_CREATE == O_CREATE {
  80. flags = flags | 0x9000; // Fail if found and create directories leading to the file if they don't exist
  81. } else {
  82. flags = flags | 0x2000; // Fail if not found
  83. }
  84. if mode & O_EXCL == O_EXCL {
  85. flags = flags | 0x111; // Block opening the node for any reason
  86. }
  87. if mode & O_RDONLY == O_RDONLY {
  88. flags = flags | 0x2; // Read access
  89. }
  90. if mode & O_WRONLY == O_WRONLY {
  91. flags = flags | 0x220; // Write and resize access
  92. }
  93. if mode & O_TRUNC == O_TRUNC {
  94. flags = flags | 0x200; // Resize access
  95. }
  96. information := new(OS_Node_Information);
  97. error := OSOpenNode(&path[0], len(path), flags, information);
  98. if error < ERROR_NONE {
  99. free(information);
  100. return 0, error;
  101. }
  102. if mode & O_TRUNC == O_TRUNC {
  103. error := OSResizeFile(information.handle, 0);
  104. if error < ERROR_NONE do return 0, ERROR_UNKNOWN_OPERATION_FAILURE;
  105. }
  106. if mode & O_APPEND == O_APPEND {
  107. information.position = information.size;
  108. } else {
  109. information.position = 0;
  110. }
  111. return Handle(uintptr(information)), ERROR_NONE;
  112. }
  113. close :: proc(fd: Handle) {
  114. information := (^OS_Node_Information)(uintptr(fd));
  115. OSCloseHandle(information.handle);
  116. free(information);
  117. }
  118. file_size :: proc(fd: Handle) -> (i64, Errno) {
  119. x: OS_Node_Information;
  120. OSRefreshNodeInformation(&x);
  121. return x.size, ERROR_NONE;
  122. }
  123. write :: proc(fd: Handle, data: []byte) -> (int, Errno) {
  124. if fd == 0 {
  125. OSPrintDirect(&data[0], len(data));
  126. return len(data), ERROR_NONE;
  127. } else if fd == 1 {
  128. assert(false);
  129. return 0, ERROR_NOT_IMPLEMENTED;
  130. }
  131. information := (^OS_Node_Information)(uintptr(fd));
  132. count := OSWriteFileSync(information.handle, information.position, i64(len(data)), &data[0]);
  133. if count < 0 do return 0, 1;
  134. information.position += count;
  135. return int(count), 0;
  136. }
  137. read :: proc(fd: Handle, data: []byte) -> (int, Errno) {
  138. if (fd == 0 || fd == 1) {
  139. assert(false);
  140. return 0, ERROR_NOT_IMPLEMENTED;
  141. }
  142. information := (^OS_Node_Information)(uintptr(fd));
  143. count := OSReadFileSync(information.handle, information.position, i64(len(data)), &data[0]);
  144. if count < 0 do return 0, ERROR_UNKNOWN_OPERATION_FAILURE;
  145. information.position += count;
  146. return int(count), ERROR_NONE;
  147. }