|
@@ -7,13 +7,14 @@ import "base:runtime"
|
|
|
import "core:sys/linux"
|
|
|
|
|
|
_File :: struct {
|
|
|
+ using file: File,
|
|
|
name: string,
|
|
|
fd: linux.Fd,
|
|
|
allocator: runtime.Allocator,
|
|
|
}
|
|
|
|
|
|
-_stdin : File = {
|
|
|
- impl = {
|
|
|
+_stdin := File{
|
|
|
+ impl = &_File{
|
|
|
name = "/proc/self/fd/0",
|
|
|
fd = 0,
|
|
|
allocator = _file_allocator(),
|
|
@@ -21,9 +22,10 @@ _stdin : File = {
|
|
|
stream = {
|
|
|
procedure = _file_stream_proc,
|
|
|
},
|
|
|
+ fstat = _fstat,
|
|
|
}
|
|
|
-_stdout : File = {
|
|
|
- impl = {
|
|
|
+_stdout := File{
|
|
|
+ impl = &_File{
|
|
|
name = "/proc/self/fd/1",
|
|
|
fd = 1,
|
|
|
allocator = _file_allocator(),
|
|
@@ -31,9 +33,10 @@ _stdout : File = {
|
|
|
stream = {
|
|
|
procedure = _file_stream_proc,
|
|
|
},
|
|
|
+ fstat = _fstat,
|
|
|
}
|
|
|
-_stderr : File = {
|
|
|
- impl = {
|
|
|
+_stderr := File{
|
|
|
+ impl = &_File{
|
|
|
name = "/proc/self/fd/2",
|
|
|
fd = 2,
|
|
|
allocator = _file_allocator(),
|
|
@@ -41,6 +44,7 @@ _stderr : File = {
|
|
|
stream = {
|
|
|
procedure = _file_stream_proc,
|
|
|
},
|
|
|
+ fstat = _fstat,
|
|
|
}
|
|
|
|
|
|
@init
|
|
@@ -89,35 +93,35 @@ _open :: proc(name: string, flags: File_Flags, perm: File_Mode) -> (f: ^File, er
|
|
|
}
|
|
|
|
|
|
_new_file :: proc(fd: uintptr, _: string = "") -> ^File {
|
|
|
- file := new(File, file_allocator())
|
|
|
- file.impl = {
|
|
|
- fd = linux.Fd(fd),
|
|
|
- allocator = file_allocator(),
|
|
|
- name = _get_full_path(file.impl.fd, file.impl.allocator),
|
|
|
- }
|
|
|
- file.stream = {
|
|
|
- data = file,
|
|
|
+ impl := new(_File, file_allocator())
|
|
|
+ impl.fd = linux.Fd(fd)
|
|
|
+ impl.allocator = file_allocator()
|
|
|
+ impl.name = _get_full_path(impl.fd, impl.allocator)
|
|
|
+ impl.file.stream = {
|
|
|
+ data = &impl.file,
|
|
|
procedure = _file_stream_proc,
|
|
|
}
|
|
|
- file.fstat = _fstat
|
|
|
- return file
|
|
|
+ impl.fstat = _fstat
|
|
|
+ return impl
|
|
|
}
|
|
|
|
|
|
_destroy :: proc(f: ^File) -> Error {
|
|
|
- if f == nil {
|
|
|
+ if f == nil || f.impl == nil {
|
|
|
return nil
|
|
|
}
|
|
|
- delete(f.impl.name, f.impl.allocator)
|
|
|
- free(f, f.impl.allocator)
|
|
|
+ impl := (^_File)(f.impl)
|
|
|
+ delete(impl.name, impl.allocator)
|
|
|
+ free(f, impl.allocator)
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
|
|
|
_close :: proc(f: ^File) -> Error {
|
|
|
- if f == nil {
|
|
|
+ if f == nil || f.impl == nil {
|
|
|
return nil
|
|
|
}
|
|
|
- errno := linux.close(f.impl.fd)
|
|
|
+ impl := (^_File)(f.impl)
|
|
|
+ errno := linux.close(impl.fd)
|
|
|
if errno == .EBADF { // avoid possible double free
|
|
|
return _get_platform_error(errno)
|
|
|
}
|
|
@@ -126,18 +130,20 @@ _close :: proc(f: ^File) -> Error {
|
|
|
}
|
|
|
|
|
|
_fd :: proc(f: ^File) -> uintptr {
|
|
|
- if f == nil {
|
|
|
+ if f == nil || f.impl == nil {
|
|
|
return ~uintptr(0)
|
|
|
}
|
|
|
- return uintptr(f.impl.fd)
|
|
|
+ impl := (^_File)(f.impl)
|
|
|
+ return uintptr(impl.fd)
|
|
|
}
|
|
|
|
|
|
_name :: proc(f: ^File) -> string {
|
|
|
- return f.impl.name if f != nil else ""
|
|
|
+ return (^_File)(f.impl).name if f != nil && f.impl != nil else ""
|
|
|
}
|
|
|
|
|
|
_seek :: proc(f: ^File, offset: i64, whence: io.Seek_From) -> (ret: i64, err: Error) {
|
|
|
- n, errno := linux.lseek(f.impl.fd, offset, linux.Seek_Whence(whence))
|
|
|
+ impl := (^_File)(f.impl)
|
|
|
+ n, errno := linux.lseek(impl.fd, offset, linux.Seek_Whence(whence))
|
|
|
if errno != .NONE {
|
|
|
return -1, _get_platform_error(errno)
|
|
|
}
|
|
@@ -148,7 +154,8 @@ _read :: proc(f: ^File, p: []byte) -> (i64, Error) {
|
|
|
if len(p) == 0 {
|
|
|
return 0, nil
|
|
|
}
|
|
|
- n, errno := linux.read(f.impl.fd, p[:])
|
|
|
+ impl := (^_File)(f.impl)
|
|
|
+ n, errno := linux.read(impl.fd, p[:])
|
|
|
if errno != .NONE {
|
|
|
return -1, _get_platform_error(errno)
|
|
|
}
|
|
@@ -159,8 +166,8 @@ _read_at :: proc(f: ^File, p: []byte, offset: i64) -> (i64, Error) {
|
|
|
if offset < 0 {
|
|
|
return 0, .Invalid_Offset
|
|
|
}
|
|
|
-
|
|
|
- n, errno := linux.pread(f.impl.fd, p[:], offset)
|
|
|
+ impl := (^_File)(f.impl)
|
|
|
+ n, errno := linux.pread(impl.fd, p[:], offset)
|
|
|
if errno != .NONE {
|
|
|
return -1, _get_platform_error(errno)
|
|
|
}
|
|
@@ -174,7 +181,8 @@ _write :: proc(f: ^File, p: []byte) -> (i64, Error) {
|
|
|
if len(p) == 0 {
|
|
|
return 0, nil
|
|
|
}
|
|
|
- n, errno := linux.write(f.impl.fd, p[:])
|
|
|
+ impl := (^_File)(f.impl)
|
|
|
+ n, errno := linux.write(impl.fd, p[:])
|
|
|
if errno != .NONE {
|
|
|
return -1, _get_platform_error(errno)
|
|
|
}
|
|
@@ -186,7 +194,8 @@ _write_at :: proc(f: ^File, p: []byte, offset: i64) -> (i64, Error) {
|
|
|
return 0, .Invalid_Offset
|
|
|
}
|
|
|
|
|
|
- n, errno := linux.pwrite(f.impl.fd, p[:], offset)
|
|
|
+ impl := (^_File)(f.impl)
|
|
|
+ n, errno := linux.pwrite(impl.fd, p[:], offset)
|
|
|
if errno != .NONE {
|
|
|
return -1, _get_platform_error(errno)
|
|
|
}
|
|
@@ -195,7 +204,8 @@ _write_at :: proc(f: ^File, p: []byte, offset: i64) -> (i64, Error) {
|
|
|
|
|
|
_file_size :: proc(f: ^File) -> (n: i64, err: Error) {
|
|
|
s: linux.Stat = ---
|
|
|
- errno := linux.fstat(f.impl.fd, &s)
|
|
|
+ impl := (^_File)(f.impl)
|
|
|
+ errno := linux.fstat(impl.fd, &s)
|
|
|
if errno != .NONE {
|
|
|
return -1, _get_platform_error(errno)
|
|
|
}
|
|
@@ -203,15 +213,18 @@ _file_size :: proc(f: ^File) -> (n: i64, err: Error) {
|
|
|
}
|
|
|
|
|
|
_sync :: proc(f: ^File) -> Error {
|
|
|
- return _get_platform_error(linux.fsync(f.impl.fd))
|
|
|
+ impl := (^_File)(f.impl)
|
|
|
+ return _get_platform_error(linux.fsync(impl.fd))
|
|
|
}
|
|
|
|
|
|
_flush :: proc(f: ^File) -> Error {
|
|
|
- return _get_platform_error(linux.fsync(f.impl.fd))
|
|
|
+ impl := (^_File)(f.impl)
|
|
|
+ return _get_platform_error(linux.fsync(impl.fd))
|
|
|
}
|
|
|
|
|
|
_truncate :: proc(f: ^File, size: i64) -> Error {
|
|
|
- return _get_platform_error(linux.ftruncate(f.impl.fd, size))
|
|
|
+ impl := (^_File)(f.impl)
|
|
|
+ return _get_platform_error(linux.ftruncate(impl.fd, size))
|
|
|
}
|
|
|
|
|
|
_remove :: proc(name: string) -> Error {
|
|
@@ -287,7 +300,8 @@ _chdir :: proc(name: string) -> Error {
|
|
|
}
|
|
|
|
|
|
_fchdir :: proc(f: ^File) -> Error {
|
|
|
- return _get_platform_error(linux.fchdir(f.impl.fd))
|
|
|
+ impl := (^_File)(f.impl)
|
|
|
+ return _get_platform_error(linux.fchdir(impl.fd))
|
|
|
}
|
|
|
|
|
|
_chmod :: proc(name: string, mode: File_Mode) -> Error {
|
|
@@ -297,7 +311,8 @@ _chmod :: proc(name: string, mode: File_Mode) -> Error {
|
|
|
}
|
|
|
|
|
|
_fchmod :: proc(f: ^File, mode: File_Mode) -> Error {
|
|
|
- return _get_platform_error(linux.fchmod(f.impl.fd, transmute(linux.Mode)(u32(mode))))
|
|
|
+ impl := (^_File)(f.impl)
|
|
|
+ return _get_platform_error(linux.fchmod(impl.fd, transmute(linux.Mode)(u32(mode))))
|
|
|
}
|
|
|
|
|
|
// NOTE: will throw error without super user priviledges
|
|
@@ -316,7 +331,8 @@ _lchown :: proc(name: string, uid, gid: int) -> Error {
|
|
|
|
|
|
// NOTE: will throw error without super user priviledges
|
|
|
_fchown :: proc(f: ^File, uid, gid: int) -> Error {
|
|
|
- return _get_platform_error(linux.fchown(f.impl.fd, linux.Uid(uid), linux.Gid(gid)))
|
|
|
+ impl := (^_File)(f.impl)
|
|
|
+ return _get_platform_error(linux.fchown(impl.fd, linux.Uid(uid), linux.Gid(gid)))
|
|
|
}
|
|
|
|
|
|
_chtimes :: proc(name: string, atime, mtime: time.Time) -> Error {
|
|
@@ -346,7 +362,8 @@ _fchtimes :: proc(f: ^File, atime, mtime: time.Time) -> Error {
|
|
|
uint(mtime._nsec) % uint(time.Second),
|
|
|
},
|
|
|
}
|
|
|
- return _get_platform_error(linux.utimensat(f.impl.fd, nil, ×[0], nil))
|
|
|
+ impl := (^_File)(f.impl)
|
|
|
+ return _get_platform_error(linux.utimensat(impl.fd, nil, ×[0], nil))
|
|
|
}
|
|
|
|
|
|
_exists :: proc(name: string) -> bool {
|