lib/std/sys/unix.rad 3.7 KiB raw
1
//! Unix-specific system calls and utilities.
2
use std::intrinsics;
3
4
/// File access modes.
5
// TODO: Use unlabeled struct.
6
pub record OpenFlags {
7
    value: i32,
8
}
9
10
/// Open file for reading only.
11
pub const O_RDONLY: OpenFlags = OpenFlags { value: 0 };
12
13
/// Open file for writing only.
14
pub const O_WRONLY: OpenFlags = OpenFlags { value: 1 };
15
16
/// Open file for reading and writing.
17
pub const O_RDWR: OpenFlags = OpenFlags { value: 2 };
18
19
/// Create file if it doesn't exist.
20
pub const O_CREAT: OpenFlags = OpenFlags { value: 64 };
21
22
/// Truncate file to zero length.
23
pub const O_TRUNC: OpenFlags = OpenFlags { value: 512 };
24
25
/// Standard file descriptor for stdin.
26
pub const STDIN: i32 = 0;
27
28
/// Standard file descriptor for stdout.
29
pub const STDOUT: i32 = 1;
30
31
/// Standard file descriptor for stderr.
32
pub const STDERR: i32 = 2;
33
34
/// Special value representing current working directory for `openat()`.
35
const AT_FDCWD: i32 = -100;
36
37
/// Opens a file at the given path and returns a file descriptor.
38
/// Returns a negative value on error.
39
pub fn open(path: *[u8], flags: OpenFlags) -> i32 {
40
    return intrinsics::ecall(56, AT_FDCWD, path.ptr as i32, flags.value, 0);
41
}
42
43
/// Opens a file at the given path with mode, returns a file descriptor.
44
pub fn openOpts(path: *[u8], flags: OpenFlags, mode: i32) -> i32 {
45
    return intrinsics::ecall(56, AT_FDCWD, path.ptr as i32, flags.value, mode);
46
}
47
48
/// Reads from a file descriptor into the provided buffer.
49
/// Returns the number of bytes read, or a negative value on error.
50
pub fn read(fd: i32, buf: *mut [u8]) -> i32 {
51
    return intrinsics::ecall(63, fd, buf.ptr as i32, buf.len as i32, 0);
52
}
53
54
/// Reads from a file descriptor until EOF or buffer is full.
55
/// Returns the total number of bytes read, or a negative value on error.
56
pub fn readToEnd(fd: i32, buf: *mut [u8]) -> i32 {
57
    let mut total: u32 = 0;
58
    while total < buf.len {
59
        let chunk = &mut buf[total..];
60
        let n = read(fd, chunk);
61
62
        if n < 0 {
63
            return n;
64
        }
65
        if n == 0 {
66
            break;
67
        }
68
        total += n as u32;
69
    }
70
    return total as i32;
71
}
72
73
/// Writes to a file descriptor from the provided buffer.
74
/// Returns the number of bytes written, or a negative value on error.
75
pub fn write(fd: i32, buf: *[u8]) -> i32 {
76
    return intrinsics::ecall(64, fd, buf.ptr as i32, buf.len as i32, 0);
77
}
78
79
/// Closes a file descriptor.
80
/// Returns `0` on success, or a negative value on error.
81
pub fn close(fd: i32) -> i32 {
82
    return intrinsics::ecall(57, fd, 0, 0, 0);
83
}
84
85
86
/// Reads the entire contents of a file at the given path into the provided buffer.
87
/// Returns a slice containing the data read, or `nil` on error.
88
pub fn readFile(path: *[u8], buf: *mut [u8]) -> ?*[u8] {
89
    let fd = open(path, O_RDONLY);
90
    if fd < 0 {
91
        return nil;
92
    }
93
    let n = readToEnd(fd, buf);
94
95
    if close(fd) < 0 {
96
        return nil;
97
    }
98
    if n < 0 {
99
        return nil;
100
    }
101
    return &buf[..(n as u32)];
102
}
103
104
/// Exit the current process with the given status code.
105
pub fn exit(status: i32) {
106
    intrinsics::ecall(93, status, 0, 0, 0);
107
}
108
109
/// Writes the entire contents of a buffer to a file at the given path.
110
/// Creates the file if it doesn't exist, truncates if it does.
111
/// Returns `true` on success.
112
pub fn writeFile(path: *[u8], data: *[u8]) -> bool {
113
    let flags = OpenFlags {
114
        value: O_WRONLY.value | O_CREAT.value | O_TRUNC.value
115
    };
116
    let fd = openOpts(path, flags, 420); // 0644 in octal.
117
    if fd < 0 {
118
        return false;
119
    }
120
    let mut written: u32 = 0;
121
    while written < data.len {
122
        let chunk = &data[written..];
123
        let n = write(fd, chunk);
124
        if n <= 0 {
125
            close(fd);
126
            return false;
127
        }
128
        written += n as u32;
129
    }
130
    close(fd);
131
132
    return true;
133
}