webmcp

annotate libraries/extos/extos.c @ 398:ac9a4e1885da

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

Impressum / About Us