|
@@ -22,6 +22,59 @@ stdin: Handle = 0
|
|
stdout: Handle = 1
|
|
stdout: Handle = 1
|
|
stderr: Handle = 2
|
|
stderr: Handle = 2
|
|
|
|
|
|
|
|
+pid_t :: distinct i32
|
|
|
|
+off_t :: distinct i64
|
|
|
|
+dev_t :: distinct i32
|
|
|
|
+ino_t :: distinct i64
|
|
|
|
+mode_t :: distinct u32
|
|
|
|
+nlink_t :: distinct i32
|
|
|
|
+uid_t :: distinct u32
|
|
|
|
+gid_t :: distinct u32
|
|
|
|
+blksize_t :: distinct i32
|
|
|
|
+blkcnt_t :: distinct i64
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+Unix_File_Time :: struct {
|
|
|
|
+ seconds: time_t,
|
|
|
|
+ nanoseconds: c.long,
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+OS_Stat :: struct {
|
|
|
|
+ device_id: dev_t, // device ID that this file resides on
|
|
|
|
+ serial: ino_t, // this file's serial inode ID
|
|
|
|
+ mode: mode_t, // file mode (rwx for user, group, etc)
|
|
|
|
+ nlink: nlink_t, // number of hard links to this file
|
|
|
|
+ uid: uid_t, // user ID of the file's owner
|
|
|
|
+ gid: gid_t, // group ID of the file's group
|
|
|
|
+ size: off_t, // file size, in bytes
|
|
|
|
+ rdev: dev_t, // device type (not used)
|
|
|
|
+ block_size: blksize_t, // optimal blocksize for I/O
|
|
|
|
+
|
|
|
|
+ last_access: Unix_File_Time, // time of last access
|
|
|
|
+ modified: Unix_File_Time, // time of last data modification
|
|
|
|
+ status_change: Unix_File_Time, // time of last file status change
|
|
|
|
+ birthtime: Unix_File_Time, // time of file creation
|
|
|
|
+
|
|
|
|
+ type: u32 // attribute/index type
|
|
|
|
+
|
|
|
|
+ blocks: blkcnt_t, // blocks allocated for file
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* file access modes for open() */
|
|
|
|
+O_RDONLY :: 0x0000 /* read only */
|
|
|
|
+O_WRONLY :: 0x0001 /* write only */
|
|
|
|
+O_RDWR :: 0x0002 /* read and write */
|
|
|
|
+O_ACCMODE :: 0x0003 /* mask to get the access modes above */
|
|
|
|
+O_RWMASK :: O_ACCMODE
|
|
|
|
+
|
|
|
|
+/* flags for open() */
|
|
|
|
+O_EXCL :: 0x0100 /* exclusive creat */
|
|
|
|
+O_CREAT :: 0x0200 /* create and open file */
|
|
|
|
+O_TRUNC :: 0x0400 /* open with truncation */
|
|
|
|
+O_NOCTTY :: 0x1000 /* don't make tty the controlling tty */
|
|
|
|
+O_NOTRAVERSE :: 0x2000 /* do not traverse leaf link */
|
|
|
|
+
|
|
|
|
+
|
|
foreign libc {
|
|
foreign libc {
|
|
@(link_name="_errnop") __error :: proc() -> ^c.int ---
|
|
@(link_name="_errnop") __error :: proc() -> ^c.int ---
|
|
|
|
|
|
@@ -102,6 +155,51 @@ close :: proc(fd: Handle) -> Errno {
|
|
return ERROR_NONE
|
|
return ERROR_NONE
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// In practice a read/write call would probably never read/write these big buffers all at once,
|
|
|
|
+// which is why the number of bytes is returned and why there are procs that will call this in a
|
|
|
|
+// loop for you.
|
|
|
|
+// We set a max of 1GB to keep alignment and to be safe.
|
|
|
|
+@(private)
|
|
|
|
+MAX_RW :: 1 << 30
|
|
|
|
+
|
|
|
|
+read :: proc(fd: Handle, data: []byte) -> (int, Errno) {
|
|
|
|
+ to_read := min(c.size_t(len(data)), MAX_RW)
|
|
|
|
+ bytes_read := _unix_read(fd, &data[0], to_read)
|
|
|
|
+ if bytes_read == -1 {
|
|
|
|
+ return -1, Errno(get_last_error())
|
|
|
|
+ }
|
|
|
|
+ return int(bytes_read), ERROR_NONE
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+write :: proc(fd: Handle, data: []byte) -> (int, Errno) {
|
|
|
|
+ if len(data) == 0 {
|
|
|
|
+ return 0, ERROR_NONE
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ to_write := min(c.size_t(len(data)), MAX_RW)
|
|
|
|
+ bytes_written := _unix_write(fd, &data[0], to_write)
|
|
|
|
+ if bytes_written == -1 {
|
|
|
|
+ return -1, Errno(get_last_error())
|
|
|
|
+ }
|
|
|
|
+ return int(bytes_written), ERROR_NONE
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
|
|
|
|
+ res := _unix_seek(fd, offset, c.int(whence))
|
|
|
|
+ if res == -1 {
|
|
|
|
+ return -1, Errno(get_last_error())
|
|
|
|
+ }
|
|
|
|
+ return res, ERROR_NONE
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+file_size :: proc(fd: Handle) -> (i64, Errno) {
|
|
|
|
+ s, err := _fstat(fd)
|
|
|
|
+ if err != ERROR_NONE {
|
|
|
|
+ return -1, err
|
|
|
|
+ }
|
|
|
|
+ return s.size, ERROR_NONE
|
|
|
|
+}
|
|
|
|
+
|
|
_alloc_command_line_arguments :: proc() -> []string {
|
|
_alloc_command_line_arguments :: proc() -> []string {
|
|
res := make([]string, len(runtime.args__))
|
|
res := make([]string, len(runtime.args__))
|
|
for arg, i in runtime.args__ {
|
|
for arg, i in runtime.args__ {
|