-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathplatform_posix.c
162 lines (139 loc) · 3.4 KB
/
platform_posix.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#define _DEFAULT_SOURCE 1
#include <dirent.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdint.h>
#include <stddef.h>
typedef uint8_t u8;
typedef int64_t i64;
typedef uint64_t u64;
typedef int32_t i32;
typedef uint32_t u32;
typedef uint32_t b32;
typedef uint16_t u16;
typedef ptrdiff_t size;
typedef size_t usize;
typedef ptrdiff_t iptr;
#define os_path_sep s8("/")
#include "jdict.c"
static void
os_exit(i32 code)
{
_exit(code);
unreachable();
}
static Arena
os_new_arena(size cap)
{
Arena a;
size pagesize = sysconf(_SC_PAGESIZE);
if (cap % pagesize != 0)
cap += pagesize - cap % pagesize;
a.beg = mmap(0, cap, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
if (a.beg == MAP_FAILED)
return (Arena){0};
a.end = a.beg + cap;
#ifdef _DEBUG_ARENA
a.min_capacity_remaining = cap;
#endif
return a;
}
static b32
os_read_stdin(u8 *buf, size count)
{
size rlen = read(STDIN_FILENO, buf, count);
return rlen == count;
}
static s8
os_read_whole_file_at(char *file, iptr dir_fd, Arena *a, u32 arena_flags)
{
i32 fd = openat(dir_fd, file, O_RDONLY);
if (fd < 0) {
stream_append_s8(&error_stream, s8("failed to open: "));
stream_append_s8(&error_stream, cstr_to_s8(file));
die(&error_stream);
}
struct stat st;
if (fstat(fd, &st) < 0) {
stream_append_s8(&error_stream, s8("failed to stat: "));
stream_append_s8(&error_stream, cstr_to_s8(file));
die(&error_stream);
}
s8 result = {.len = st.st_size, .s = alloc(a, u8, st.st_size, arena_flags|ARENA_NO_CLEAR)};
size rlen = read(fd, result.s, result.len);
close(fd);
if (rlen != result.len) {
stream_append_s8(&error_stream, s8("failed to read whole file: "));
stream_append_s8(&error_stream, cstr_to_s8(file));
die(&error_stream);
}
return result;
}
static b32
os_write(iptr file, s8 raw)
{
while (raw.len) {
size r = write(file, raw.s, raw.len);
if (r < 0) return 0;
raw = s8_cut_head(raw, r);
}
return 1;
}
static iptr
os_begin_path_stream(Stream *dir_name, Arena *a, u32 arena_flags)
{
(void)a; (void)arena_flags;
stream_append_byte(dir_name, 0);
DIR *dir = opendir((char *)dir_name->data);
if (!dir) {
stream_append_s8(&error_stream, s8("opendir: failed to open: "));
stream_append_s8(&error_stream, (s8){.len = dir_name->widx - 1, .s = dir_name->data});
die(&error_stream);
}
return (iptr)dir;
}
static s8
os_get_valid_file(iptr path_stream, s8 match_prefix, Arena *a, u32 arena_flags)
{
s8 result = {0};
if (path_stream) {
DIR *dir = (DIR *)path_stream;
iptr dir_fd = dirfd(dir);
struct dirent *dent;
while ((dent = readdir(dir)) != NULL) {
if (dent->d_type == DT_REG) {
b32 valid = 1;
for (size i = 0; i < match_prefix.len; i++) {
if (match_prefix.s[i] != dent->d_name[i]) {
valid = 0;
break;
}
}
if (valid) {
result = os_read_whole_file_at(dent->d_name, dir_fd, a, arena_flags);
break;
}
}
}
}
return result;
}
static void
os_end_path_stream(iptr path_stream)
{
closedir((DIR *)path_stream);
}
i32
main(i32 argc, char *argv[])
{
Arena memory = os_new_arena(1024 * MEGABYTE);
error_stream.fd = STDERR_FILENO;
error_stream.cap = 4096;
error_stream.data = alloc(&memory, u8, error_stream.cap, ARENA_NO_CLEAR);
stdout_stream.fd = STDOUT_FILENO;
stdout_stream.cap = 8 * MEGABYTE;
stdout_stream.data = alloc(&memory, u8, error_stream.cap, ARENA_NO_CLEAR);
return jdict(&memory, argc, argv);
}