file.odin 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. package os2
  2. import "core:io"
  3. import "core:time"
  4. import "base:runtime"
  5. File :: struct {
  6. impl: _File,
  7. stream: io.Stream,
  8. user_fstat: Fstat_Callback,
  9. }
  10. File_Mode :: distinct u32
  11. File_Mode_Dir :: File_Mode(1<<16)
  12. File_Mode_Named_Pipe :: File_Mode(1<<17)
  13. File_Mode_Device :: File_Mode(1<<18)
  14. File_Mode_Char_Device :: File_Mode(1<<19)
  15. File_Mode_Sym_Link :: File_Mode(1<<20)
  16. File_Mode_Perm :: File_Mode(0o777) // Unix permision bits
  17. File_Flags :: distinct bit_set[File_Flag; uint]
  18. File_Flag :: enum {
  19. Read,
  20. Write,
  21. Append,
  22. Create,
  23. Excl,
  24. Sync,
  25. Trunc,
  26. Sparse,
  27. Close_On_Exec,
  28. Unbuffered_IO,
  29. }
  30. O_RDONLY :: File_Flags{.Read}
  31. O_WRONLY :: File_Flags{.Write}
  32. O_RDWR :: File_Flags{.Read, .Write}
  33. O_APPEND :: File_Flags{.Append}
  34. O_CREATE :: File_Flags{.Create}
  35. O_EXCL :: File_Flags{.Excl}
  36. O_SYNC :: File_Flags{.Sync}
  37. O_TRUNC :: File_Flags{.Trunc}
  38. O_SPARSE :: File_Flags{.Sparse}
  39. O_CLOEXEC :: File_Flags{.Close_On_Exec}
  40. stdin: ^File = nil // OS-Specific
  41. stdout: ^File = nil // OS-Specific
  42. stderr: ^File = nil // OS-Specific
  43. @(require_results)
  44. create :: proc(name: string) -> (^File, Error) {
  45. return open(name, {.Read, .Write, .Create}, File_Mode(0o777))
  46. }
  47. @(require_results)
  48. open :: proc(name: string, flags := File_Flags{.Read}, perm := File_Mode(0o777)) -> (^File, Error) {
  49. return _open(name, flags, perm)
  50. }
  51. @(require_results)
  52. new_file :: proc(handle: uintptr, name: string) -> ^File {
  53. return _new_file(handle, name)
  54. }
  55. @(require_results)
  56. fd :: proc(f: ^File) -> uintptr {
  57. return _fd(f)
  58. }
  59. @(require_results)
  60. name :: proc(f: ^File) -> string {
  61. return _name(f)
  62. }
  63. close :: proc(f: ^File) -> Error {
  64. if f != nil {
  65. return io.close(f.stream)
  66. }
  67. return nil
  68. }
  69. seek :: proc(f: ^File, offset: i64, whence: io.Seek_From) -> (ret: i64, err: Error) {
  70. if f != nil {
  71. return io.seek(f.stream, offset, whence)
  72. }
  73. return 0, .Invalid_File
  74. }
  75. read :: proc(f: ^File, p: []byte) -> (n: int, err: Error) {
  76. if f != nil {
  77. return io.read(f.stream, p)
  78. }
  79. return 0, .Invalid_File
  80. }
  81. read_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: int, err: Error) {
  82. if f != nil {
  83. return io.read_at(f.stream, p, offset)
  84. }
  85. return 0, .Invalid_File
  86. }
  87. write :: proc(f: ^File, p: []byte) -> (n: int, err: Error) {
  88. if f != nil {
  89. return io.write(f.stream, p)
  90. }
  91. return 0, .Invalid_File
  92. }
  93. write_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: int, err: Error) {
  94. if f != nil {
  95. return io.write_at(f.stream, p, offset)
  96. }
  97. return 0, .Invalid_File
  98. }
  99. file_size :: proc(f: ^File) -> (n: i64, err: Error) {
  100. if f != nil {
  101. return io.size(f.stream)
  102. }
  103. return 0, .Invalid_File
  104. }
  105. flush :: proc(f: ^File) -> Error {
  106. if f != nil {
  107. return io.flush(f.stream)
  108. }
  109. return nil
  110. }
  111. sync :: proc(f: ^File) -> Error {
  112. return _sync(f)
  113. }
  114. truncate :: proc(f: ^File, size: i64) -> Error {
  115. return _truncate(f, size)
  116. }
  117. remove :: proc(name: string) -> Error {
  118. return _remove(name)
  119. }
  120. rename :: proc(old_path, new_path: string) -> Error {
  121. return _rename(old_path, new_path)
  122. }
  123. link :: proc(old_name, new_name: string) -> Error {
  124. return _link(old_name, new_name)
  125. }
  126. symlink :: proc(old_name, new_name: string) -> Error {
  127. return _symlink(old_name, new_name)
  128. }
  129. read_link :: proc(name: string, allocator: runtime.Allocator) -> (string, Error) {
  130. return _read_link(name,allocator)
  131. }
  132. chdir :: change_directory
  133. change_directory :: proc(name: string) -> Error {
  134. return _chdir(name)
  135. }
  136. chmod :: change_mode
  137. change_mode :: proc(name: string, mode: File_Mode) -> Error {
  138. return _chmod(name, mode)
  139. }
  140. chown :: change_owner
  141. change_owner :: proc(name: string, uid, gid: int) -> Error {
  142. return _chown(name, uid, gid)
  143. }
  144. fchdir :: fchange_directory
  145. fchange_directory :: proc(f: ^File) -> Error {
  146. return _fchdir(f)
  147. }
  148. fchmod :: fchange_mode
  149. fchange_mode :: proc(f: ^File, mode: File_Mode) -> Error {
  150. return _fchmod(f, mode)
  151. }
  152. fchown :: fchange_owner
  153. fchange_owner :: proc(f: ^File, uid, gid: int) -> Error {
  154. return _fchown(f, uid, gid)
  155. }
  156. lchown :: change_owner_do_not_follow_links
  157. change_owner_do_not_follow_links :: proc(name: string, uid, gid: int) -> Error {
  158. return _lchown(name, uid, gid)
  159. }
  160. chtimes :: change_times
  161. change_times :: proc(name: string, atime, mtime: time.Time) -> Error {
  162. return _chtimes(name, atime, mtime)
  163. }
  164. fchtimes :: fchange_times
  165. fchange_times :: proc(f: ^File, atime, mtime: time.Time) -> Error {
  166. return _fchtimes(f, atime, mtime)
  167. }
  168. @(require_results)
  169. exists :: proc(path: string) -> bool {
  170. return _exists(path)
  171. }
  172. @(require_results)
  173. is_file :: proc(path: string) -> bool {
  174. return _is_file(path)
  175. }
  176. is_dir :: is_directory
  177. @(require_results)
  178. is_directory :: proc(path: string) -> bool {
  179. return _is_dir(path)
  180. }
  181. copy_file :: proc(dst_path, src_path: string) -> Error {
  182. src := open(src_path) or_return
  183. defer close(src)
  184. info := fstat(src, file_allocator()) or_return
  185. defer file_info_delete(info, file_allocator())
  186. if info.is_directory {
  187. return .Invalid_File
  188. }
  189. dst := open(dst_path, {.Read, .Write, .Create, .Trunc}, info.mode & File_Mode_Perm) or_return
  190. defer close(dst)
  191. _, err := io.copy(to_writer(dst), to_reader(src))
  192. return err
  193. }