file.odin 4.8 KB

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