aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/os/os2/file.odin150
1 files changed, 145 insertions, 5 deletions
diff --git a/core/os/os2/file.odin b/core/os/os2/file.odin
index 5375258ca..1da37dfa4 100644
--- a/core/os/os2/file.odin
+++ b/core/os/os2/file.odin
@@ -56,6 +56,7 @@ File_Type :: enum {
Character_Device,
}
+// Represents the file flags for a file handle
File_Flags :: distinct bit_set[File_Flag; uint]
File_Flag :: enum {
Read,
@@ -121,6 +122,9 @@ perm :: proc{
perm_number,
}
+/*
+ `perm_number` converts an integer value `perm` to the bit set `Permissions`
+*/
@(require_results)
perm_number :: proc "contextless" (perm: int) -> Permissions {
return transmute(Permissions)u32(perm & 0o777)
@@ -128,16 +132,34 @@ perm_number :: proc "contextless" (perm: int) -> Permissions {
-
+// `stdin` is an open file pointing to the standard input file stream
stdin: ^File = nil // OS-Specific
+
+// `stdout` is an open file pointing to the standard output file stream
stdout: ^File = nil // OS-Specific
+
+// `stderr` is an open file pointing to the standard error file stream
stderr: ^File = nil // OS-Specific
+/*
+ `create` creates or truncates a named file `name`.
+ If the file already exists, it is truncated.
+ If the file does not exist, it is created with the `Permissions_Default_File` permissions.
+ If successful, a `^File` is return which can be used for I/O.
+ And error is returned if any is encountered.
+*/
@(require_results)
create :: proc(name: string) -> (^File, Error) {
- return open(name, {.Read, .Write, .Create}, Permissions_Default)
+ return open(name, {.Read, .Write, .Create, .Trunc}, Permissions_Default_File)
}
+/*
+ `open` is a generalized open call, which defaults to opening for reading.
+ If the file does not exist, and the `{.Create}` flag is passed, it is created with the permissions `perm`,
+ and please note that the containing directory must exist otherwise and an error will be returned.
+ If successful, a `^File` is return which can be used for I/O.
+ And error is returned if any is encountered.
+*/
@(require_results)
open :: proc(name: string, flags := File_Flags{.Read}, perm := Permissions_Default) -> (^File, Error) {
return _open(name, flags, perm)
@@ -151,7 +173,10 @@ open :: proc(name: string, flags := File_Flags{.Read}, perm := Permissions_Defau
// return _open_buffered(name, buffer_size, flags, perm)
// }
-
+/*
+ `new_file` returns a new `^File` with the given file descriptor `handle` and `name`.
+ The return value will only be `nil` IF the `handle` is not a valid file descriptor.
+*/
@(require_results)
new_file :: proc(handle: uintptr, name: string) -> ^File {
file, err := _new_file(handle, name, file_allocator())
@@ -161,16 +186,25 @@ new_file :: proc(handle: uintptr, name: string) -> ^File {
return file
}
+/*
+ `clone` returns a new `^File` based on the passed file `f` with the same underlying file descriptor.
+*/
@(require_results)
clone :: proc(f: ^File) -> (^File, Error) {
return _clone(f)
}
+/*
+ `fd` returns the file descriptor of the file `f` passed. If the file is not valid, an invalid handle will be returned.
+*/
@(require_results)
fd :: proc(f: ^File) -> uintptr {
return _fd(f)
}
+/*
+ `name` returns the name of the file. The lifetime of this string lasts as long as the file handle itself.
+*/
@(require_results)
name :: proc(f: ^File) -> string {
return _name(f)
@@ -189,6 +223,16 @@ close :: proc(f: ^File) -> Error {
return nil
}
+/*
+ seek sets the offsets for the next read or write on a file to a specified `offset`,
+ according to what `whence` is set.
+ `.Start` is relative to the origin of the file.
+ `.Current` is relative to the current offset.
+ `.End` is relative to the end.
+ It returns the new offset and an error, if any is encountered.
+ Prefer `read_at` or `write_at` if the offset does not want to be changed.
+
+*/
seek :: proc(f: ^File, offset: i64, whence: io.Seek_From) -> (ret: i64, err: Error) {
if f != nil {
return io.seek(f.stream, offset, whence)
@@ -196,6 +240,11 @@ seek :: proc(f: ^File, offset: i64, whence: io.Seek_From) -> (ret: i64, err: Err
return 0, .Invalid_File
}
+/*
+ `read` reads up to len(p) bytes from the file `f`, and then stores them in `p`.
+ It returns the number of bytes read and an error, if any is encountered.
+ At the end of a file, it returns `0, io.EOF`.
+*/
read :: proc(f: ^File, p: []byte) -> (n: int, err: Error) {
if f != nil {
return io.read(f.stream, p)
@@ -203,6 +252,12 @@ read :: proc(f: ^File, p: []byte) -> (n: int, err: Error) {
return 0, .Invalid_File
}
+/*
+ `read_at` reads up to len(p) bytes from the file `f` at the byte offset `offset`, and then stores them in `p`.
+ It returns the number of bytes read and an error, if any is encountered.
+ `read_at` always returns a non-nil error when `n < len(p)`.
+ At the end of a file, the error is `io.EOF`.
+*/
read_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: int, err: Error) {
if f != nil {
return io.read_at(f.stream, p, offset)
@@ -210,6 +265,11 @@ read_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: int, err: Error) {
return 0, .Invalid_File
}
+/*
+ `write` writes `len(p)` bytes from `p` to the file `f`. It returns the number of bytes written to
+ and an error, if any is encountered.
+ `write` returns a non-nil error when `n != len(p)`.
+*/
write :: proc(f: ^File, p: []byte) -> (n: int, err: Error) {
if f != nil {
return io.write(f.stream, p)
@@ -217,6 +277,11 @@ write :: proc(f: ^File, p: []byte) -> (n: int, err: Error) {
return 0, .Invalid_File
}
+/*
+ `write_at` writes `len(p)` bytes from `p` to the file `f` starting at byte offset `offset`.
+ It returns the number of bytes written to and an error, if any is encountered.
+ `write_at` returns a non-nil error when `n != len(p)`.
+*/
write_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: int, err: Error) {
if f != nil {
return io.write_at(f.stream, p, offset)
@@ -224,6 +289,9 @@ write_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: int, err: Error) {
return 0, .Invalid_File
}
+/*
+ `file_size` returns the length of the file `f` in bytes and an error, if any is encountered.
+*/
file_size :: proc(f: ^File) -> (n: i64, err: Error) {
if f != nil {
return io.size(f.stream)
@@ -231,6 +299,9 @@ file_size :: proc(f: ^File) -> (n: i64, err: Error) {
return 0, .Invalid_File
}
+/*
+ `flush` flushes a file `f`
+*/
flush :: proc(f: ^File) -> Error {
if f != nil {
return io.flush(f.stream)
@@ -238,31 +309,54 @@ flush :: proc(f: ^File) -> Error {
return nil
}
+/*
+ `sync` commits the current contents of the file `f` to stable storage.
+ This usually means flushing the file system's in-memory copy to disk.
+*/
sync :: proc(f: ^File) -> Error {
return _sync(f)
}
+/*
+ `truncate` changes the size of the file `f` to `size` in bytes.
+ This can be used to shorten or lengthen a file.
+ It does not change the "offset" of the file.
+*/
truncate :: proc(f: ^File, size: i64) -> Error {
return _truncate(f, size)
}
+/*
+ `remove` removes a named file or (empty) directory.
+*/
remove :: proc(name: string) -> Error {
return _remove(name)
}
+/*
+ `rename` renames (moves) `old_path` to `new_path`.
+*/
rename :: proc(old_path, new_path: string) -> Error {
return _rename(old_path, new_path)
}
-
+/*
+ `link` creates a `new_name` as a hard link to the `old_name` file.
+*/
link :: proc(old_name, new_name: string) -> Error {
return _link(old_name, new_name)
}
+/*
+ `symlink` creates a `new_name` as a symbolic link to the `old_name` file.
+*/
symlink :: proc(old_name, new_name: string) -> Error {
return _symlink(old_name, new_name)
}
+/*
+ `read_link` returns the destinction of the named symbolic link `name`.
+*/
read_link :: proc(name: string, allocator: runtime.Allocator) -> (string, Error) {
return _read_link(name,allocator)
}
@@ -270,18 +364,35 @@ read_link :: proc(name: string, allocator: runtime.Allocator) -> (string, Error)
chdir :: change_directory
+/*
+ Changes the current working directory to the named directory.
+*/
change_directory :: proc(name: string) -> Error {
return _chdir(name)
}
chmod :: change_mode
+/*
+ Changes the mode/permissions of the named file to `mode`.
+ If the file is a symbolic link, it changes the mode of the link's target.
+
+ On Windows, only `{.Write_User}` of `mode` is used, and controls whether or not
+ the file has a read-only attribute. Use `{.Read_User}` for a read-only file and
+ `{.Read_User, .Write_User}` for a readable & writable file.
+*/
change_mode :: proc(name: string, mode: Permissions) -> Error {
return _chmod(name, mode)
}
chown :: change_owner
+/*
+ Changes the numeric `uid` and `gid` of a named file. If the file is a symbolic link,
+ it changes the `uid` and `gid` of the link's target.
+
+ On Windows, it always returns an error.
+*/
change_owner :: proc(name: string, uid, gid: int) -> Error {
return _chown(name, uid, gid)
}
@@ -300,6 +411,12 @@ fchange_mode :: proc(f: ^File, mode: Permissions) -> Error {
fchown :: fchange_owner
+/*
+ Changes the numeric `uid` and `gid` of the file `f`. If the file is a symbolic link,
+ it changes the `uid` and `gid` of the link's target.
+
+ On Windows, it always returns an error.
+*/
fchange_owner :: proc(f: ^File, uid, gid: int) -> Error {
return _fchown(f, uid, gid)
}
@@ -307,27 +424,45 @@ fchange_owner :: proc(f: ^File, uid, gid: int) -> Error {
lchown :: change_owner_do_not_follow_links
+/*
+ Changes the numeric `uid` and `gid` of the file `f`. If the file is a symbolic link,
+ it changes the `uid` and `gid` of the lin itself.
+
+ On Windows, it always returns an error.
+*/
change_owner_do_not_follow_links :: proc(name: string, uid, gid: int) -> Error {
return _lchown(name, uid, gid)
}
chtimes :: change_times
+/*
+ Changes the access `atime` and modification `mtime` times of a named file.
+*/
change_times :: proc(name: string, atime, mtime: time.Time) -> Error {
return _chtimes(name, atime, mtime)
}
fchtimes :: fchange_times
+/*
+ Changes the access `atime` and modification `mtime` times of the file `f`.
+*/
fchange_times :: proc(f: ^File, atime, mtime: time.Time) -> Error {
return _fchtimes(f, atime, mtime)
}
+/*
+ `exists` returns whether or not a named file exists.
+*/
@(require_results)
exists :: proc(path: string) -> bool {
return _exists(path)
}
+/*
+ `is_file` returns whether or not the type of a named file is a `File_Type.Regular` file.
+*/
@(require_results)
is_file :: proc(path: string) -> bool {
temp_allocator := TEMP_ALLOCATOR_GUARD({})
@@ -340,6 +475,9 @@ is_file :: proc(path: string) -> bool {
is_dir :: is_directory
+/*
+ Returns whether or not the type of a named file is a `File_Type.Directory` file.
+*/
@(require_results)
is_directory :: proc(path: string) -> bool {
temp_allocator := TEMP_ALLOCATOR_GUARD({})
@@ -350,7 +488,9 @@ is_directory :: proc(path: string) -> bool {
return fi.type == .Directory
}
-
+/*
+ `copy_file` copies a file from `src_path` to `dst_path` and returns an error if any was encountered.
+*/
copy_file :: proc(dst_path, src_path: string) -> Error {
when #defined(_copy_file_native) {
return _copy_file_native(dst_path, src_path)