rev |
line source |
jbe/bsw@0
|
1 #include <lua.h>
|
jbe/bsw@0
|
2 #include <lauxlib.h>
|
jbe/bsw@0
|
3 #include <dirent.h>
|
jbe/bsw@0
|
4 #include <time.h>
|
jbe/bsw@0
|
5 #include <unistd.h>
|
jbe/bsw@0
|
6 #include <sys/types.h>
|
jbe@344
|
7 #include <sys/stat.h>
|
jbe/bsw@0
|
8 #include <sys/wait.h>
|
jbe/bsw@0
|
9 #include <signal.h>
|
jbe/bsw@0
|
10 #include <errno.h>
|
jbe/bsw@0
|
11 #include <stdio.h>
|
jbe/bsw@0
|
12 #include <string.h>
|
jbe/bsw@0
|
13 #include <fcntl.h>
|
jbe/bsw@0
|
14 #include <poll.h>
|
jbe/bsw@0
|
15 #include <stdlib.h>
|
jbe/bsw@0
|
16
|
jbe/bsw@0
|
17 #define EXTOS_MAX_ERRLEN 80
|
jbe/bsw@0
|
18 #define EXTOS_EXEC_MAX_ARGS 64
|
jbe/bsw@0
|
19
|
jbe/bsw@0
|
20 static lua_Number extos_monotonic_start_time;
|
jbe/bsw@0
|
21
|
jbe/bsw@0
|
22 static int extos_pfilter(lua_State *L) {
|
jbe/bsw@0
|
23 int i, result, exit_status, status_pipe_len;
|
jbe/bsw@0
|
24 const char *in_buf;
|
jbe/bsw@0
|
25 size_t in_len;
|
jbe/bsw@0
|
26 size_t in_pos = 0;
|
jbe/bsw@0
|
27 const char *filename;
|
jbe/bsw@0
|
28 const char *args[EXTOS_EXEC_MAX_ARGS+2];
|
jbe/bsw@0
|
29 int pipe_status[2];
|
jbe/bsw@0
|
30 int pipe_in[2];
|
jbe/bsw@0
|
31 int pipe_out[2];
|
jbe/bsw@0
|
32 int pipe_err[2];
|
jbe/bsw@0
|
33 pid_t child;
|
jbe/bsw@0
|
34 char status_buf[1];
|
jbe/bsw@0
|
35 char *out_buf = NULL;
|
jbe/bsw@0
|
36 size_t out_len = 1024;
|
jbe/bsw@0
|
37 size_t out_pos = 0;
|
jbe/bsw@0
|
38 char *err_buf = NULL;
|
jbe/bsw@0
|
39 size_t err_len = 1024;
|
jbe/bsw@0
|
40 size_t err_pos = 0;
|
jbe/bsw@0
|
41 void *old_sigpipe_action;
|
jbe/bsw@0
|
42 struct pollfd fds[3];
|
jbe/bsw@0
|
43 int in_closed = 0;
|
jbe/bsw@0
|
44 int out_closed = 0;
|
jbe/bsw@0
|
45 int err_closed = 0;
|
jbe/bsw@0
|
46 void *newptr;
|
jbe/bsw@0
|
47 char errmsg[EXTOS_MAX_ERRLEN+1];
|
jbe/bsw@0
|
48 in_buf = luaL_optlstring(L, 1, "", &in_len);
|
jbe/bsw@0
|
49 filename = luaL_checkstring(L, 2);
|
jbe/bsw@0
|
50 args[0] = filename;
|
jbe/bsw@0
|
51 for (i = 0; i < EXTOS_EXEC_MAX_ARGS; i++) {
|
jbe/bsw@0
|
52 if (lua_isnoneornil(L, 3+i)) break;
|
jbe/bsw@0
|
53 else args[i+1] = luaL_checkstring(L, 3+i);
|
jbe/bsw@0
|
54 }
|
jbe/bsw@0
|
55 if (!lua_isnoneornil(L, 3+i)) {
|
jbe/bsw@0
|
56 return luaL_error(L, "Too many arguments for pfilter call.");
|
jbe/bsw@0
|
57 }
|
jbe/bsw@0
|
58 args[i+1] = 0;
|
jbe/bsw@0
|
59 // status pipe for internal communication
|
jbe/bsw@0
|
60 if (pipe(pipe_status) < 0) {
|
jbe/bsw@0
|
61 strerror_r(errno, errmsg, EXTOS_MAX_ERRLEN+1);
|
jbe/bsw@0
|
62 goto extos_pfilter_error_A0;
|
jbe/bsw@0
|
63 }
|
jbe/bsw@0
|
64 // stdin
|
jbe/bsw@0
|
65 if (pipe(pipe_in) < 0) {
|
jbe/bsw@0
|
66 strerror_r(errno, errmsg, EXTOS_MAX_ERRLEN+1);
|
jbe/bsw@0
|
67 goto extos_pfilter_error_A1;
|
jbe/bsw@0
|
68 }
|
jbe/bsw@0
|
69 if (in_len) {
|
jbe/bsw@0
|
70 do result = fcntl(pipe_in[1], F_SETFL, O_NONBLOCK); while (result < 0 && errno == EINTR);
|
jbe/bsw@0
|
71 } else {
|
jbe/bsw@0
|
72 do result = close(pipe_in[1]); while (result < 0 && errno == EINTR);
|
jbe/bsw@0
|
73 in_closed = 1;
|
jbe/bsw@0
|
74 }
|
jbe/bsw@0
|
75 if (result < 0) {
|
jbe/bsw@0
|
76 strerror_r(errno, errmsg, EXTOS_MAX_ERRLEN+1);
|
jbe/bsw@0
|
77 goto extos_pfilter_error_A2;
|
jbe/bsw@0
|
78 }
|
jbe/bsw@0
|
79 // stdout
|
jbe/bsw@0
|
80 if (pipe(pipe_out) < 0) {
|
jbe/bsw@0
|
81 strerror_r(errno, errmsg, EXTOS_MAX_ERRLEN+1);
|
jbe/bsw@0
|
82 goto extos_pfilter_error_A2;
|
jbe/bsw@0
|
83 }
|
jbe/bsw@0
|
84 do result = fcntl(pipe_out[0], F_SETFL, O_NONBLOCK); while (result < 0 && errno == EINTR);
|
jbe/bsw@0
|
85 if (result < 0) {
|
jbe/bsw@0
|
86 strerror_r(errno, errmsg, EXTOS_MAX_ERRLEN+1);
|
jbe/bsw@0
|
87 goto extos_pfilter_error_A3;
|
jbe/bsw@0
|
88 }
|
jbe/bsw@0
|
89 // stderr
|
jbe/bsw@0
|
90 if (pipe(pipe_err) < 0) {
|
jbe/bsw@0
|
91 strerror_r(errno, errmsg, EXTOS_MAX_ERRLEN+1);
|
jbe/bsw@0
|
92 goto extos_pfilter_error_A3;
|
jbe/bsw@0
|
93 }
|
jbe/bsw@0
|
94 do result = fcntl(pipe_err[0], F_SETFL, O_NONBLOCK); while (result < 0 && errno == EINTR);
|
jbe/bsw@0
|
95 if (result < 0) {
|
jbe/bsw@0
|
96 strerror_r(errno, errmsg, EXTOS_MAX_ERRLEN+1);
|
jbe/bsw@0
|
97 goto extos_pfilter_error_A4;
|
jbe/bsw@0
|
98 }
|
jbe/bsw@0
|
99 // fork
|
jbe/bsw@0
|
100 child = fork();
|
jbe/bsw@0
|
101 if (child < 0) {
|
jbe/bsw@0
|
102 strerror_r(errno, errmsg, EXTOS_MAX_ERRLEN+1);
|
jbe/bsw@0
|
103 goto extos_pfilter_error_A4;
|
jbe/bsw@0
|
104 }
|
jbe/bsw@0
|
105 // skip error handling
|
jbe/bsw@0
|
106 goto extos_pfilter_success_A;
|
jbe/bsw@0
|
107 // error handling
|
jbe/bsw@0
|
108 extos_pfilter_error_A4:
|
jbe/bsw@0
|
109 do result = close(pipe_err[0]); while (result < 0 && errno == EINTR);
|
jbe/bsw@0
|
110 do result = close(pipe_err[1]); while (result < 0 && errno == EINTR);
|
jbe/bsw@0
|
111 extos_pfilter_error_A3:
|
jbe/bsw@0
|
112 do result = close(pipe_out[0]); while (result < 0 && errno == EINTR);
|
jbe/bsw@0
|
113 do result = close(pipe_out[1]); while (result < 0 && errno == EINTR);
|
jbe/bsw@0
|
114 extos_pfilter_error_A2:
|
jbe/bsw@0
|
115 do result = close(pipe_in[0]); while (result < 0 && errno == EINTR);
|
jbe/bsw@0
|
116 do result = close(pipe_in[1]); while (result < 0 && errno == EINTR);
|
jbe/bsw@0
|
117 extos_pfilter_error_A1:
|
jbe/bsw@0
|
118 do result = close(pipe_status[0]); while (result < 0 && errno == EINTR);
|
jbe/bsw@0
|
119 do result = close(pipe_status[1]); while (result < 0 && errno == EINTR);
|
jbe/bsw@0
|
120 extos_pfilter_error_A0:
|
jbe/bsw@0
|
121 return luaL_error(L, "Unexpected error in pfilter: %s", errmsg);
|
jbe/bsw@0
|
122 // end of error handling
|
jbe/bsw@0
|
123 extos_pfilter_success_A:
|
jbe/bsw@0
|
124 if (child) { // parent
|
jbe/bsw@0
|
125 old_sigpipe_action = signal(SIGPIPE, SIG_IGN);
|
jbe/bsw@0
|
126 do result = close(pipe_status[1]); while (result < 0 && errno == EINTR);
|
jbe/bsw@0
|
127 if (result < 0) goto extos_pfilter_error_B;
|
jbe/bsw@0
|
128 do result = close(pipe_in[0]); while (result < 0 && errno == EINTR);
|
jbe/bsw@0
|
129 if (result < 0) goto extos_pfilter_error_B;
|
jbe/bsw@0
|
130 do result = close(pipe_out[1]); while (result < 0 && errno == EINTR);
|
jbe/bsw@0
|
131 if (result < 0) goto extos_pfilter_error_B;
|
jbe/bsw@0
|
132 do result = close(pipe_err[1]); while (result < 0 && errno == EINTR);
|
jbe/bsw@0
|
133 if (result < 0) goto extos_pfilter_error_B;
|
jbe/bsw@0
|
134 out_buf = malloc(out_len * sizeof(char));
|
jbe/bsw@0
|
135 if (!out_buf) goto extos_pfilter_error_B;
|
jbe/bsw@0
|
136 err_buf = malloc(err_len * sizeof(char));
|
jbe/bsw@0
|
137 if (!err_buf) goto extos_pfilter_error_B;
|
jbe/bsw@0
|
138 while (!in_closed || !out_closed || !err_closed) {
|
jbe/bsw@0
|
139 i = 0;
|
jbe/bsw@0
|
140 if (!in_closed) {
|
jbe/bsw@0
|
141 fds[i].fd = pipe_in[1];
|
jbe/bsw@0
|
142 fds[i].events = POLLOUT;
|
jbe/bsw@0
|
143 i++;
|
jbe/bsw@0
|
144 }
|
jbe/bsw@0
|
145 if (!out_closed) {
|
jbe/bsw@0
|
146 fds[i].fd = pipe_out[0];
|
jbe/bsw@0
|
147 fds[i].events = POLLIN;
|
jbe/bsw@0
|
148 i++;
|
jbe/bsw@0
|
149 }
|
jbe/bsw@0
|
150 if (!err_closed) {
|
jbe/bsw@0
|
151 fds[i].fd = pipe_err[0];
|
jbe/bsw@0
|
152 fds[i].events = POLLIN;
|
jbe/bsw@0
|
153 i++;
|
jbe/bsw@0
|
154 }
|
jbe/bsw@0
|
155 do result = poll(fds, i, -1); while (result < 0 && errno == EINTR);
|
jbe/bsw@0
|
156 if (result < 0) goto extos_pfilter_error_B;
|
jbe/bsw@0
|
157 if (!in_closed) {
|
jbe/bsw@0
|
158 do result = write(pipe_in[1], in_buf+in_pos, in_len-in_pos); while (result < 0 && errno == EINTR);
|
jbe/bsw@0
|
159 if (result < 0) {
|
jbe/bsw@0
|
160 if (errno == EPIPE) {
|
jbe/bsw@0
|
161 do result = close(pipe_in[1]); while (result < 0 && errno == EINTR);
|
jbe/bsw@0
|
162 in_closed = 1;
|
jbe/bsw@0
|
163 } else if (errno != EAGAIN) {
|
jbe/bsw@0
|
164 goto extos_pfilter_error_B;
|
jbe/bsw@0
|
165 }
|
jbe/bsw@0
|
166 } else {
|
jbe/bsw@0
|
167 in_pos += result;
|
jbe/bsw@0
|
168 if (in_pos == in_len) {
|
jbe/bsw@0
|
169 do result = close(pipe_in[1]); while (result < 0 && errno == EINTR);
|
jbe/bsw@0
|
170 in_closed = 1;
|
jbe/bsw@0
|
171 }
|
jbe/bsw@0
|
172 }
|
jbe/bsw@0
|
173 }
|
jbe/bsw@0
|
174 if (!out_closed) {
|
jbe/bsw@0
|
175 do result = read(pipe_out[0], out_buf+out_pos, out_len-out_pos); while (result < 0 && errno == EINTR);
|
jbe/bsw@0
|
176 if (result < 0) {
|
jbe/bsw@0
|
177 if (errno != EAGAIN) goto extos_pfilter_error_B;
|
jbe/bsw@0
|
178 } else if (result == 0) {
|
jbe/bsw@0
|
179 do result = close(pipe_out[0]); while (result < 0 && errno == EINTR);
|
jbe/bsw@0
|
180 out_closed = 1;
|
jbe/bsw@0
|
181 } else {
|
jbe/bsw@0
|
182 out_pos += result;
|
jbe/bsw@0
|
183 if (out_pos == out_len) {
|
jbe/bsw@0
|
184 out_len *= 2;
|
jbe/bsw@0
|
185 newptr = realloc(out_buf, out_len * sizeof(char));
|
jbe/bsw@0
|
186 if (!newptr) goto extos_pfilter_error_B;
|
jbe/bsw@0
|
187 out_buf = newptr;
|
jbe/bsw@0
|
188 }
|
jbe/bsw@0
|
189 }
|
jbe/bsw@0
|
190 }
|
jbe/bsw@0
|
191 if (!err_closed) {
|
jbe/bsw@0
|
192 do result = read(pipe_err[0], err_buf+err_pos, err_len-err_pos); while (result < 0 && errno == EINTR);
|
jbe/bsw@0
|
193 if (result < 0) {
|
jbe/bsw@0
|
194 if (errno != EAGAIN) goto extos_pfilter_error_B;
|
jbe/bsw@0
|
195 } else if (result == 0) {
|
jbe/bsw@0
|
196 do result = close(pipe_err[0]); while (result < 0 && errno == EINTR);
|
jbe/bsw@0
|
197 err_closed = 1;
|
jbe/bsw@0
|
198 } else {
|
jbe/bsw@0
|
199 err_pos += result;
|
jbe/bsw@0
|
200 if (err_pos == err_len) {
|
jbe/bsw@0
|
201 err_len *= 2;
|
jbe/bsw@0
|
202 newptr = realloc(err_buf, err_len * sizeof(char));
|
jbe/bsw@0
|
203 if (!newptr) goto extos_pfilter_error_B;
|
jbe/bsw@0
|
204 err_buf = newptr;
|
jbe/bsw@0
|
205 }
|
jbe/bsw@0
|
206 }
|
jbe/bsw@0
|
207 }
|
jbe/bsw@0
|
208 }
|
jbe/bsw@0
|
209 lua_pushlstring(L, out_buf, out_pos);
|
jbe/bsw@0
|
210 free(out_buf);
|
jbe/bsw@0
|
211 out_buf = NULL;
|
jbe/bsw@0
|
212 lua_pushlstring(L, err_buf, err_pos);
|
jbe/bsw@0
|
213 free(err_buf);
|
jbe/bsw@0
|
214 err_buf = NULL;
|
jbe/bsw@0
|
215 do result = waitpid(child, &exit_status, 0); while (result < 0 && errno == EINTR);
|
jbe/bsw@0
|
216 child = 0;
|
jbe/bsw@0
|
217 if (result < 0) goto extos_pfilter_error_B;
|
jbe/bsw@0
|
218 do status_pipe_len = read(pipe_status[0], status_buf, 1); while (status_pipe_len < 0 && errno == EINTR);
|
jbe/bsw@0
|
219 if (status_pipe_len < 0) goto extos_pfilter_error_B;
|
jbe/bsw@0
|
220 do result = close(pipe_status[0]); while (result < 0 && errno == EINTR);
|
jbe/bsw@0
|
221 signal(SIGPIPE, old_sigpipe_action);
|
jbe/bsw@0
|
222 if (status_pipe_len == 0) {
|
jbe/bsw@0
|
223 if (WIFEXITED(exit_status)) lua_pushinteger(L, WEXITSTATUS(exit_status));
|
jbe/bsw@0
|
224 else lua_pushinteger(L, -WTERMSIG(exit_status));
|
jbe/bsw@0
|
225 return 3;
|
jbe/bsw@0
|
226 } else if (status_buf[0] == 0) {
|
jbe/bsw@0
|
227 return luaL_error(L, "Error in pfilter while reopening standard file descriptors in child process.");
|
jbe/bsw@0
|
228 } else {
|
jbe/bsw@0
|
229 strerror_r(status_buf[0], errmsg, EXTOS_MAX_ERRLEN+1);
|
jbe/bsw@0
|
230 lua_pushnil(L);
|
jbe/bsw@0
|
231 lua_pushfstring(L, "Could not execute \"%s\": %s", filename, errmsg);
|
jbe/bsw@0
|
232 return 2;
|
jbe/bsw@0
|
233 }
|
jbe/bsw@0
|
234 extos_pfilter_error_B:
|
jbe/bsw@0
|
235 signal(SIGPIPE, old_sigpipe_action);
|
jbe/bsw@0
|
236 strerror_r(errno, errmsg, EXTOS_MAX_ERRLEN+1);
|
jbe/bsw@0
|
237 if (out_buf) free(out_buf);
|
jbe/bsw@0
|
238 if (err_buf) free(err_buf);
|
jbe/bsw@0
|
239 if (!in_closed) {
|
jbe/bsw@0
|
240 do result = close(pipe_in[1]); while (result < 0 && errno == EINTR);
|
jbe/bsw@0
|
241 }
|
jbe/bsw@0
|
242 if (!out_closed) {
|
jbe/bsw@0
|
243 do result = close(pipe_out[0]); while (result < 0 && errno == EINTR);
|
jbe/bsw@0
|
244 }
|
jbe/bsw@0
|
245 if (!err_closed) {
|
jbe/bsw@0
|
246 do result = close(pipe_err[0]); while (result < 0 && errno == EINTR);
|
jbe/bsw@0
|
247 }
|
jbe/bsw@0
|
248 if (child) do result = waitpid(child, &exit_status, 0); while (result < 0 && errno == EINTR);
|
jbe/bsw@0
|
249 return luaL_error(L, "Unexpected error in pfilter: %s", errmsg);
|
jbe/bsw@0
|
250 } else { // child
|
jbe/bsw@0
|
251 do result = close(pipe_status[0]); while (result < 0 && errno == EINTR);
|
jbe/bsw@0
|
252 do result = close(pipe_in[1]); while (result < 0 && errno == EINTR);
|
jbe/bsw@0
|
253 do result = close(pipe_out[0]); while (result < 0 && errno == EINTR);
|
jbe/bsw@0
|
254 do result = close(0); while (result < 0 && errno == EINTR);
|
jbe/bsw@0
|
255 do result = close(1); while (result < 0 && errno == EINTR);
|
jbe/bsw@0
|
256 do result = close(2); while (result < 0 && errno == EINTR);
|
jbe/bsw@0
|
257 do result = dup(pipe_in[0]); while (result < 0 && errno == EINTR);
|
jbe/bsw@0
|
258 if (result != 0) goto extos_pfilter_error_fd_remapping;
|
jbe/bsw@0
|
259 do result = dup(pipe_out[1]); while (result < 0 && errno == EINTR);
|
jbe/bsw@0
|
260 if (result != 1) goto extos_pfilter_error_fd_remapping;
|
jbe/bsw@0
|
261 do result = dup(pipe_err[1]); while (result < 0 && errno == EINTR);
|
jbe/bsw@0
|
262 if (result != 2) goto extos_pfilter_error_fd_remapping;
|
jbe/bsw@0
|
263 execvp(filename, args);
|
jbe/bsw@0
|
264 status_buf[0] = errno;
|
jbe/bsw@0
|
265 do result = write(pipe_status[1], status_buf, 1); while (result < 0 && errno == EINTR);
|
jbe/bsw@0
|
266 _exit(0);
|
jbe/bsw@0
|
267 extos_pfilter_error_fd_remapping:
|
jbe/bsw@0
|
268 status_buf[0] = 0;
|
jbe/bsw@0
|
269 do result = write(pipe_status[1], status_buf, 1); while (result < 0 && errno == EINTR);
|
jbe/bsw@0
|
270 _exit(0);
|
jbe/bsw@0
|
271 }
|
jbe/bsw@0
|
272 }
|
jbe/bsw@0
|
273
|
jbe/bsw@0
|
274 static int extos_listdir(lua_State *L) {
|
jbe/bsw@0
|
275 DIR *dir;
|
jbe/bsw@0
|
276 int i = 1;
|
jbe/bsw@0
|
277 struct dirent entry_buffer;
|
jbe/bsw@0
|
278 struct dirent *entry;
|
jbe/bsw@0
|
279 dir = opendir(luaL_checkstring(L, 1));
|
jbe/bsw@0
|
280 if (!dir) {
|
jbe/bsw@0
|
281 lua_pushnil(L);
|
jbe/bsw@0
|
282 lua_pushliteral(L, "Could not list directory.");
|
jbe/bsw@0
|
283 return 2;
|
jbe/bsw@0
|
284 }
|
jbe/bsw@0
|
285 lua_settop(L, 0);
|
jbe/bsw@0
|
286 lua_newtable(L); // 1
|
jbe/bsw@0
|
287 while (1) {
|
jbe/bsw@0
|
288 readdir_r(dir, &entry_buffer, &entry);
|
jbe/bsw@0
|
289 if (!entry) break;
|
jbe/bsw@0
|
290 // Linux doesn't have d_namlen
|
jbe/bsw@0
|
291 //lua_pushlstring(L, entry->d_name, entry->d_namlen);
|
jbe/bsw@0
|
292 lua_pushstring(L, entry->d_name);
|
jbe/bsw@0
|
293 lua_rawseti(L, 1, i++);
|
jbe/bsw@0
|
294 }
|
jbe/bsw@0
|
295 closedir(dir);
|
jbe/bsw@0
|
296 return 1;
|
jbe/bsw@0
|
297 }
|
jbe/bsw@0
|
298
|
jbe@344
|
299 static int extos_stat(lua_State *L) {
|
jbe@344
|
300 const char *filename;
|
jbe@344
|
301 struct stat sb;
|
jbe@344
|
302 filename = luaL_checkstring(L, 1);
|
jbe@344
|
303 if (stat(filename, &sb)) {
|
jbe@344
|
304 char errmsg[EXTOS_MAX_ERRLEN+1];
|
jbe@344
|
305 strerror_r(errno, errmsg, EXTOS_MAX_ERRLEN+1);
|
jbe@344
|
306 lua_pushnil(L);
|
jbe@344
|
307 lua_pushfstring(L, "Could not get file stats for \"%s\": %s", filename, errmsg);
|
jbe@344
|
308 return 2;
|
jbe@344
|
309 }
|
jbe@344
|
310 lua_createtable(L, 0, 19);
|
jbe@344
|
311 lua_pushinteger(L, sb.st_dev);
|
jbe@344
|
312 lua_setfield(L, -2, "dev");
|
jbe@344
|
313 lua_pushinteger(L, sb.st_ino);
|
jbe@344
|
314 lua_setfield(L, -2, "ino");
|
jbe@344
|
315 lua_pushinteger(L, sb.st_nlink);
|
jbe@344
|
316 lua_setfield(L, -2, "nlink");
|
jbe@344
|
317 lua_pushinteger(L, sb.st_atime);
|
jbe@344
|
318 lua_setfield(L, -2, "atime");
|
jbe@344
|
319 lua_pushinteger(L, sb.st_mtime);
|
jbe@344
|
320 lua_setfield(L, -2, "mtime");
|
jbe@344
|
321 lua_pushinteger(L, sb.st_ctime);
|
jbe@344
|
322 lua_setfield(L, -2, "ctime");
|
jbe@344
|
323 lua_pushinteger(L, sb.st_size);
|
jbe@344
|
324 lua_setfield(L, -2, "size");
|
jbe@344
|
325 lua_pushinteger(L, sb.st_blksize);
|
jbe@344
|
326 lua_setfield(L, -2, "blksize");
|
jbe@344
|
327 lua_pushinteger(L, sb.st_blocks);
|
jbe@344
|
328 lua_setfield(L, -2, "blocks");
|
jbe@344
|
329 lua_pushinteger(L, sb.st_uid);
|
jbe@344
|
330 lua_setfield(L, -2, "uid");
|
jbe@344
|
331 lua_pushinteger(L, sb.st_gid);
|
jbe@344
|
332 lua_setfield(L, -2, "gid");
|
jbe@344
|
333 lua_pushinteger(L, sb.st_mode);
|
jbe@344
|
334 lua_setfield(L, -2, "mode");
|
jbe@344
|
335 lua_pushboolean(L, S_ISBLK(sb.st_mode));
|
jbe@344
|
336 lua_setfield(L, -2, "isblk");
|
jbe@344
|
337 lua_pushboolean(L, S_ISCHR(sb.st_mode));
|
jbe@344
|
338 lua_setfield(L, -2, "ischr");
|
jbe@344
|
339 lua_pushboolean(L, S_ISDIR(sb.st_mode));
|
jbe@344
|
340 lua_setfield(L, -2, "isdir");
|
jbe@344
|
341 lua_pushboolean(L, S_ISFIFO(sb.st_mode));
|
jbe@344
|
342 lua_setfield(L, -2, "isfifo");
|
jbe@344
|
343 lua_pushboolean(L, S_ISLNK(sb.st_mode));
|
jbe@344
|
344 lua_setfield(L, -2, "islnk");
|
jbe@344
|
345 lua_pushboolean(L, S_ISREG(sb.st_mode));
|
jbe@344
|
346 lua_setfield(L, -2, "isreg");
|
jbe@344
|
347 lua_pushboolean(L, S_ISSOCK(sb.st_mode));
|
jbe@344
|
348 lua_setfield(L, -2, "issock");
|
jbe@344
|
349 return 1;
|
jbe@344
|
350 }
|
jbe@344
|
351
|
jbe/bsw@0
|
352 static int extos_crypt(lua_State *L) {
|
jbe@343
|
353 const char *key;
|
jbe@343
|
354 const char *salt;
|
jbe/bsw@0
|
355 char *result;
|
jbe/bsw@0
|
356 key = luaL_checkstring(L, 1);
|
jbe/bsw@0
|
357 salt = luaL_checkstring(L, 2);
|
jbe/bsw@0
|
358 result = crypt(key, salt); // TODO: Call not thread safe
|
jbe/bsw@0
|
359 if (result) lua_pushstring(L, result);
|
jbe/bsw@0
|
360 else lua_pushnil(L);
|
jbe/bsw@0
|
361 return 1;
|
jbe/bsw@0
|
362 }
|
jbe/bsw@0
|
363
|
jbe/bsw@0
|
364 static int extos_hires_time(lua_State *L) {
|
jbe/bsw@0
|
365 struct timespec tp;
|
jbe/bsw@0
|
366 if (clock_gettime(CLOCK_REALTIME, &tp)) {
|
jbe/bsw@0
|
367 return luaL_error(L, "Could not access CLOCK_REALTIME.");
|
jbe/bsw@0
|
368 }
|
jbe@343
|
369 lua_pushnumber(L, tp.tv_sec + tp.tv_nsec / 1.0e9);
|
jbe/bsw@0
|
370 return 1;
|
jbe/bsw@0
|
371 }
|
jbe/bsw@0
|
372
|
jbe/bsw@0
|
373 // returns time in seconds since loading the library
|
jbe/bsw@0
|
374 static int extos_monotonic_hires_time(lua_State *L) {
|
jbe/bsw@0
|
375 struct timespec tp;
|
jbe/bsw@0
|
376 if (clock_gettime(CLOCK_MONOTONIC, &tp)) {
|
jbe/bsw@0
|
377 return luaL_error(L, "Could not access CLOCK_MONOTONIC.");
|
jbe/bsw@0
|
378 }
|
jbe/bsw@0
|
379 lua_pushnumber(L,
|
jbe@343
|
380 tp.tv_sec + tp.tv_nsec / 1.0e9 - extos_monotonic_start_time
|
jbe/bsw@0
|
381 );
|
jbe/bsw@0
|
382 return 1;
|
jbe/bsw@0
|
383 }
|
jbe/bsw@0
|
384
|
jbe@64
|
385 static const struct luaL_Reg extos_module_functions[] = {
|
jbe@64
|
386 {"pfilter", extos_pfilter},
|
jbe@64
|
387 {"listdir", extos_listdir},
|
jbe@344
|
388 {"stat", extos_stat},
|
jbe@64
|
389 {"crypt", extos_crypt},
|
jbe@64
|
390 {"hires_time", extos_hires_time},
|
jbe@64
|
391 {"monotonic_hires_time", extos_monotonic_hires_time},
|
jbe@64
|
392 {NULL, NULL}
|
jbe@64
|
393 };
|
jbe@64
|
394
|
jbe/bsw@0
|
395 int luaopen_extos(lua_State *L) {
|
jbe/bsw@0
|
396 {
|
jbe/bsw@0
|
397 struct timespec tp;
|
jbe/bsw@0
|
398 if (clock_gettime(CLOCK_MONOTONIC, &tp)) {
|
jbe/bsw@0
|
399 return luaL_error(L, "Could not access monotonic hires time.");
|
jbe/bsw@0
|
400 }
|
jbe@343
|
401 extos_monotonic_start_time = tp.tv_sec + tp.tv_nsec / 1.0e9;
|
jbe/bsw@0
|
402 }
|
jbe@64
|
403 #if LUA_VERSION_NUM >= 502
|
jbe@64
|
404 lua_newtable(L);
|
jbe@64
|
405 luaL_setfuncs(L, extos_module_functions, 0);
|
jbe@64
|
406 #else
|
jbe@70
|
407 luaL_register(L, lua_tostring(L, 1), extos_module_functions);
|
jbe@64
|
408 #endif
|
jbe@64
|
409 return 1;
|
jbe/bsw@0
|
410 }
|