aboutsummaryrefslogtreecommitdiffstats
path: root/util-src/pposix.c
diff options
context:
space:
mode:
Diffstat (limited to 'util-src/pposix.c')
-rw-r--r--util-src/pposix.c656
1 files changed, 368 insertions, 288 deletions
diff --git a/util-src/pposix.c b/util-src/pposix.c
index df814c28..4b4552f5 100644
--- a/util-src/pposix.c
+++ b/util-src/pposix.c
@@ -15,6 +15,14 @@
#define MODULE_VERSION "0.3.6"
+
+#if defined(__linux__)
+#define _GNU_SOURCE
+#else
+#define _DEFAULT_SOURCE
+#endif
+#define _POSIX_C_SOURCE 200809L
+
#include <stdlib.h>
#include <math.h>
#include <unistd.h>
@@ -35,40 +43,52 @@
#include "lualib.h"
#include "lauxlib.h"
+#if (LUA_VERSION_NUM == 501)
+#define luaL_setfuncs(L, R, N) luaL_register(L, NULL, R)
+#endif
+
#include <fcntl.h>
-#if defined(__linux__) && defined(_GNU_SOURCE)
+#if defined(__linux__)
#include <linux/falloc.h>
#endif
-#if (defined(_SVID_SOURCE) && !defined(WITHOUT_MALLINFO))
- #include <malloc.h>
- #define WITH_MALLINFO
+#if !defined(WITHOUT_MALLINFO) && defined(__linux__)
+#include <malloc.h>
+#define WITH_MALLINFO
+#endif
+
+#if defined(__FreeBSD__) && defined(RFPROC)
+/*
+ * On FreeBSD, calling fork() is equivalent to rfork(RFPROC | RFFDG).
+ *
+ * RFFDG being set means that the file descriptor table is copied,
+ * otherwise it's shared. We want the later, otherwise libevent gets
+ * messed up.
+ *
+ * See issue #412
+ */
+#define fork() rfork(RFPROC)
#endif
/* Daemonization support */
-static int lc_daemonize(lua_State *L)
-{
+static int lc_daemonize(lua_State *L) {
pid_t pid;
- if ( getppid() == 1 )
- {
+ if(getppid() == 1) {
lua_pushboolean(L, 0);
lua_pushstring(L, "already-daemonized");
return 2;
}
/* Attempt initial fork */
- if((pid = fork()) < 0)
- {
+ if((pid = fork()) < 0) {
/* Forking failed */
lua_pushboolean(L, 0);
lua_pushstring(L, "fork-failed");
return 2;
- }
- else if(pid != 0)
- {
+ } else if(pid != 0) {
/* We are the parent process */
lua_pushboolean(L, 1);
lua_pushnumber(L, pid);
@@ -76,8 +96,7 @@ static int lc_daemonize(lua_State *L)
}
/* and we are the child process */
- if(setsid() == -1)
- {
+ if(setsid() == -1) {
/* We failed to become session leader */
/* (we probably already were) */
lua_pushboolean(L, 0);
@@ -95,8 +114,9 @@ static int lc_daemonize(lua_State *L)
open("/dev/null", O_WRONLY);
/* Final fork, use it wisely */
- if(fork())
+ if(fork()) {
exit(0);
+ }
/* Show's over, let's continue */
lua_pushboolean(L, 1);
@@ -106,59 +126,59 @@ static int lc_daemonize(lua_State *L)
/* Syslog support */
-const char * const facility_strings[] = {
- "auth",
+const char *const facility_strings[] = {
+ "auth",
#if !(defined(sun) || defined(__sun))
- "authpriv",
+ "authpriv",
#endif
- "cron",
- "daemon",
+ "cron",
+ "daemon",
#if !(defined(sun) || defined(__sun))
- "ftp",
+ "ftp",
#endif
- "kern",
- "local0",
- "local1",
- "local2",
- "local3",
- "local4",
- "local5",
- "local6",
- "local7",
- "lpr",
- "mail",
- "syslog",
- "user",
- "uucp",
- NULL
- };
+ "kern",
+ "local0",
+ "local1",
+ "local2",
+ "local3",
+ "local4",
+ "local5",
+ "local6",
+ "local7",
+ "lpr",
+ "mail",
+ "syslog",
+ "user",
+ "uucp",
+ NULL
+};
int facility_constants[] = {
- LOG_AUTH,
+ LOG_AUTH,
#if !(defined(sun) || defined(__sun))
- LOG_AUTHPRIV,
+ LOG_AUTHPRIV,
#endif
- LOG_CRON,
- LOG_DAEMON,
+ LOG_CRON,
+ LOG_DAEMON,
#if !(defined(sun) || defined(__sun))
- LOG_FTP,
+ LOG_FTP,
#endif
- LOG_KERN,
- LOG_LOCAL0,
- LOG_LOCAL1,
- LOG_LOCAL2,
- LOG_LOCAL3,
- LOG_LOCAL4,
- LOG_LOCAL5,
- LOG_LOCAL6,
- LOG_LOCAL7,
- LOG_LPR,
- LOG_MAIL,
- LOG_NEWS,
- LOG_SYSLOG,
- LOG_USER,
- LOG_UUCP,
- -1
- };
+ LOG_KERN,
+ LOG_LOCAL0,
+ LOG_LOCAL1,
+ LOG_LOCAL2,
+ LOG_LOCAL3,
+ LOG_LOCAL4,
+ LOG_LOCAL5,
+ LOG_LOCAL6,
+ LOG_LOCAL7,
+ LOG_LPR,
+ LOG_MAIL,
+ LOG_NEWS,
+ LOG_SYSLOG,
+ LOG_USER,
+ LOG_UUCP,
+ -1
+};
/* "
The parameter ident in the call of openlog() is probably stored as-is.
@@ -168,17 +188,17 @@ int facility_constants[] = {
constant.
" -- syslog manpage
*/
-char* syslog_ident = NULL;
+char *syslog_ident = NULL;
-int lc_syslog_open(lua_State* L)
-{
+int lc_syslog_open(lua_State *L) {
int facility = luaL_checkoption(L, 2, "daemon", facility_strings);
facility = facility_constants[facility];
luaL_checkstring(L, 1);
- if(syslog_ident)
+ if(syslog_ident) {
free(syslog_ident);
+ }
syslog_ident = strdup(lua_tostring(L, 1));
@@ -186,53 +206,52 @@ int lc_syslog_open(lua_State* L)
return 0;
}
-const char * const level_strings[] = {
- "debug",
- "info",
- "notice",
- "warn",
- "error",
- NULL
- };
+const char *const level_strings[] = {
+ "debug",
+ "info",
+ "notice",
+ "warn",
+ "error",
+ NULL
+};
int level_constants[] = {
- LOG_DEBUG,
- LOG_INFO,
- LOG_NOTICE,
- LOG_WARNING,
- LOG_CRIT,
- -1
- };
-int lc_syslog_log(lua_State* L)
-{
+ LOG_DEBUG,
+ LOG_INFO,
+ LOG_NOTICE,
+ LOG_WARNING,
+ LOG_CRIT,
+ -1
+};
+int lc_syslog_log(lua_State *L) {
int level = level_constants[luaL_checkoption(L, 1, "notice", level_strings)];
- if(lua_gettop(L) == 3)
+ if(lua_gettop(L) == 3) {
syslog(level, "%s: %s", luaL_checkstring(L, 2), luaL_checkstring(L, 3));
- else
+ } else {
syslog(level, "%s", lua_tostring(L, 2));
+ }
return 0;
}
-int lc_syslog_close(lua_State* L)
-{
+int lc_syslog_close(lua_State *L) {
closelog();
- if(syslog_ident)
- {
+
+ if(syslog_ident) {
free(syslog_ident);
syslog_ident = NULL;
}
+
return 0;
}
-int lc_syslog_setmask(lua_State* L)
-{
+int lc_syslog_setmask(lua_State *L) {
int level_idx = luaL_checkoption(L, 1, "notice", level_strings);
int mask = 0;
- do
- {
+
+ do {
mask |= LOG_MASK(level_constants[level_idx]);
- } while (++level_idx<=4);
+ } while(++level_idx <= 4);
setlogmask(mask);
return 0;
@@ -240,72 +259,69 @@ int lc_syslog_setmask(lua_State* L)
/* getpid */
-int lc_getpid(lua_State* L)
-{
+int lc_getpid(lua_State *L) {
lua_pushinteger(L, getpid());
return 1;
}
/* UID/GID functions */
-int lc_getuid(lua_State* L)
-{
+int lc_getuid(lua_State *L) {
lua_pushinteger(L, getuid());
return 1;
}
-int lc_getgid(lua_State* L)
-{
+int lc_getgid(lua_State *L) {
lua_pushinteger(L, getgid());
return 1;
}
-int lc_setuid(lua_State* L)
-{
+int lc_setuid(lua_State *L) {
int uid = -1;
- if(lua_gettop(L) < 1)
+
+ if(lua_gettop(L) < 1) {
return 0;
- if(!lua_isnumber(L, 1) && lua_tostring(L, 1))
- {
+ }
+
+ if(!lua_isnumber(L, 1) && lua_tostring(L, 1)) {
/* Passed UID is actually a string, so look up the UID */
struct passwd *p;
p = getpwnam(lua_tostring(L, 1));
- if(!p)
- {
+
+ if(!p) {
lua_pushboolean(L, 0);
lua_pushstring(L, "no-such-user");
return 2;
}
+
uid = p->pw_uid;
- }
- else
- {
+ } else {
uid = lua_tonumber(L, 1);
}
- if(uid>-1)
- {
+ if(uid > -1) {
/* Ok, attempt setuid */
errno = 0;
- if(setuid(uid))
- {
+
+ if(setuid(uid)) {
/* Fail */
lua_pushboolean(L, 0);
- switch(errno)
- {
- case EINVAL:
- lua_pushstring(L, "invalid-uid");
- break;
- case EPERM:
- lua_pushstring(L, "permission-denied");
- break;
- default:
- lua_pushstring(L, "unknown-error");
+
+ switch(errno) {
+ case EINVAL:
+ lua_pushstring(L, "invalid-uid");
+ break;
+
+ case EPERM:
+ lua_pushstring(L, "permission-denied");
+ break;
+
+ default:
+ lua_pushstring(L, "unknown-error");
}
+
return 2;
- }
- else
- {
+ } else {
/* Success! */
lua_pushboolean(L, 1);
return 1;
@@ -318,52 +334,52 @@ int lc_setuid(lua_State* L)
return 2;
}
-int lc_setgid(lua_State* L)
-{
+int lc_setgid(lua_State *L) {
int gid = -1;
- if(lua_gettop(L) < 1)
+
+ if(lua_gettop(L) < 1) {
return 0;
- if(!lua_isnumber(L, 1) && lua_tostring(L, 1))
- {
+ }
+
+ if(!lua_isnumber(L, 1) && lua_tostring(L, 1)) {
/* Passed GID is actually a string, so look up the GID */
struct group *g;
g = getgrnam(lua_tostring(L, 1));
- if(!g)
- {
+
+ if(!g) {
lua_pushboolean(L, 0);
lua_pushstring(L, "no-such-group");
return 2;
}
+
gid = g->gr_gid;
- }
- else
- {
+ } else {
gid = lua_tonumber(L, 1);
}
- if(gid>-1)
- {
+ if(gid > -1) {
/* Ok, attempt setgid */
errno = 0;
- if(setgid(gid))
- {
+
+ if(setgid(gid)) {
/* Fail */
lua_pushboolean(L, 0);
- switch(errno)
- {
- case EINVAL:
- lua_pushstring(L, "invalid-gid");
- break;
- case EPERM:
- lua_pushstring(L, "permission-denied");
- break;
- default:
- lua_pushstring(L, "unknown-error");
+
+ switch(errno) {
+ case EINVAL:
+ lua_pushstring(L, "invalid-gid");
+ break;
+
+ case EPERM:
+ lua_pushstring(L, "permission-denied");
+ break;
+
+ default:
+ lua_pushstring(L, "unknown-error");
}
+
return 2;
- }
- else
- {
+ } else {
/* Success! */
lua_pushboolean(L, 1);
return 1;
@@ -376,90 +392,93 @@ int lc_setgid(lua_State* L)
return 2;
}
-int lc_initgroups(lua_State* L)
-{
+int lc_initgroups(lua_State *L) {
int ret;
gid_t gid;
struct passwd *p;
- if(!lua_isstring(L, 1))
- {
+ if(!lua_isstring(L, 1)) {
lua_pushnil(L);
lua_pushstring(L, "invalid-username");
return 2;
}
+
p = getpwnam(lua_tostring(L, 1));
- if(!p)
- {
+
+ if(!p) {
lua_pushnil(L);
lua_pushstring(L, "no-such-user");
return 2;
}
- if(lua_gettop(L) < 2)
- lua_pushnil(L);
- switch(lua_type(L, 2))
- {
- case LUA_TNIL:
- gid = p->pw_gid;
- break;
- case LUA_TNUMBER:
- gid = lua_tointeger(L, 2);
- break;
- default:
+
+ if(lua_gettop(L) < 2) {
lua_pushnil(L);
- lua_pushstring(L, "invalid-gid");
- return 2;
}
- ret = initgroups(lua_tostring(L, 1), gid);
- if(ret)
- {
- switch(errno)
- {
- case ENOMEM:
- lua_pushnil(L);
- lua_pushstring(L, "no-memory");
+
+ switch(lua_type(L, 2)) {
+ case LUA_TNIL:
+ gid = p->pw_gid;
break;
- case EPERM:
- lua_pushnil(L);
- lua_pushstring(L, "permission-denied");
+
+ case LUA_TNUMBER:
+ gid = lua_tointeger(L, 2);
break;
+
default:
lua_pushnil(L);
- lua_pushstring(L, "unknown-error");
- }
+ lua_pushstring(L, "invalid-gid");
+ return 2;
}
- else
- {
+
+ ret = initgroups(lua_tostring(L, 1), gid);
+
+ if(ret) {
+ switch(errno) {
+ case ENOMEM:
+ lua_pushnil(L);
+ lua_pushstring(L, "no-memory");
+ break;
+
+ case EPERM:
+ lua_pushnil(L);
+ lua_pushstring(L, "permission-denied");
+ break;
+
+ default:
+ lua_pushnil(L);
+ lua_pushstring(L, "unknown-error");
+ }
+ } else {
lua_pushboolean(L, 1);
lua_pushnil(L);
}
+
return 2;
}
-int lc_umask(lua_State* L)
-{
+int lc_umask(lua_State *L) {
char old_mode_string[7];
mode_t old_mode = umask(strtoul(luaL_checkstring(L, 1), NULL, 8));
snprintf(old_mode_string, sizeof(old_mode_string), "%03o", old_mode);
- old_mode_string[sizeof(old_mode_string)-1] = 0;
+ old_mode_string[sizeof(old_mode_string) - 1] = 0;
lua_pushstring(L, old_mode_string);
return 1;
}
-int lc_mkdir(lua_State* L)
-{
+int lc_mkdir(lua_State *L) {
int ret = mkdir(luaL_checkstring(L, 1), S_IRUSR | S_IWUSR | S_IXUSR
- | S_IRGRP | S_IWGRP | S_IXGRP
- | S_IROTH | S_IXOTH); /* mode 775 */
+ | S_IRGRP | S_IWGRP | S_IXGRP
+ | S_IROTH | S_IXOTH); /* mode 775 */
- lua_pushboolean(L, ret==0);
- if(ret)
- {
+ lua_pushboolean(L, ret == 0);
+
+ if(ret) {
lua_pushstring(L, strerror(errno));
return 2;
}
+
return 1;
}
@@ -474,68 +493,110 @@ int lc_mkdir(lua_State* L)
* pposix.setrlimit("NOFILE", 1000, 2000)
*/
int string2resource(const char *s) {
- if (!strcmp(s, "CORE")) return RLIMIT_CORE;
- if (!strcmp(s, "CPU")) return RLIMIT_CPU;
- if (!strcmp(s, "DATA")) return RLIMIT_DATA;
- if (!strcmp(s, "FSIZE")) return RLIMIT_FSIZE;
- if (!strcmp(s, "NOFILE")) return RLIMIT_NOFILE;
- if (!strcmp(s, "STACK")) return RLIMIT_STACK;
+ if(!strcmp(s, "CORE")) {
+ return RLIMIT_CORE;
+ }
+
+ if(!strcmp(s, "CPU")) {
+ return RLIMIT_CPU;
+ }
+
+ if(!strcmp(s, "DATA")) {
+ return RLIMIT_DATA;
+ }
+
+ if(!strcmp(s, "FSIZE")) {
+ return RLIMIT_FSIZE;
+ }
+
+ if(!strcmp(s, "NOFILE")) {
+ return RLIMIT_NOFILE;
+ }
+
+ if(!strcmp(s, "STACK")) {
+ return RLIMIT_STACK;
+ }
+
#if !(defined(sun) || defined(__sun))
- if (!strcmp(s, "MEMLOCK")) return RLIMIT_MEMLOCK;
- if (!strcmp(s, "NPROC")) return RLIMIT_NPROC;
- if (!strcmp(s, "RSS")) return RLIMIT_RSS;
+
+ if(!strcmp(s, "MEMLOCK")) {
+ return RLIMIT_MEMLOCK;
+ }
+
+ if(!strcmp(s, "NPROC")) {
+ return RLIMIT_NPROC;
+ }
+
+ if(!strcmp(s, "RSS")) {
+ return RLIMIT_RSS;
+ }
+
#endif
#ifdef RLIMIT_NICE
- if (!strcmp(s, "NICE")) return RLIMIT_NICE;
+
+ if(!strcmp(s, "NICE")) {
+ return RLIMIT_NICE;
+ }
+
#endif
return -1;
}
+rlim_t arg_to_rlimit(lua_State *L, int idx, rlim_t current) {
+ switch(lua_type(L, idx)) {
+ case LUA_TSTRING:
+
+ if(strcmp(lua_tostring(L, idx), "unlimited") == 0) {
+ return RLIM_INFINITY;
+ }
+
+ case LUA_TNUMBER:
+ return lua_tointeger(L, idx);
+
+ case LUA_TNONE:
+ case LUA_TNIL:
+ return current;
+
+ default:
+ return luaL_argerror(L, idx, "unexpected type");
+ }
+}
+
int lc_setrlimit(lua_State *L) {
+ struct rlimit lim;
int arguments = lua_gettop(L);
- int softlimit = -1;
- int hardlimit = -1;
- const char *resource = NULL;
int rid = -1;
+
if(arguments < 1 || arguments > 3) {
lua_pushboolean(L, 0);
lua_pushstring(L, "incorrect-arguments");
return 2;
}
- resource = luaL_checkstring(L, 1);
- softlimit = luaL_checkinteger(L, 2);
- hardlimit = luaL_checkinteger(L, 3);
+ rid = string2resource(luaL_checkstring(L, 1));
- rid = string2resource(resource);
- if (rid != -1) {
- struct rlimit lim;
- struct rlimit lim_current;
-
- if (softlimit < 0 || hardlimit < 0) {
- if (getrlimit(rid, &lim_current)) {
- lua_pushboolean(L, 0);
- lua_pushstring(L, "getrlimit-failed");
- return 2;
- }
- }
+ if(rid == -1) {
+ lua_pushboolean(L, 0);
+ lua_pushstring(L, "invalid-resource");
+ return 2;
+ }
- if (softlimit < 0) lim.rlim_cur = lim_current.rlim_cur;
- else lim.rlim_cur = softlimit;
- if (hardlimit < 0) lim.rlim_max = lim_current.rlim_max;
- else lim.rlim_max = hardlimit;
+ /* Fetch current values to use as defaults */
+ if(getrlimit(rid, &lim)) {
+ lua_pushboolean(L, 0);
+ lua_pushstring(L, "getrlimit-failed");
+ return 2;
+ }
- if (setrlimit(rid, &lim)) {
- lua_pushboolean(L, 0);
- lua_pushstring(L, "setrlimit-failed");
- return 2;
- }
- } else {
- /* Unsupported resoucrce. Sorry I'm pretty limited by POSIX standard. */
+ lim.rlim_cur = arg_to_rlimit(L, 2, lim.rlim_cur);
+ lim.rlim_max = arg_to_rlimit(L, 3, lim.rlim_max);
+
+ if(setrlimit(rid, &lim)) {
lua_pushboolean(L, 0);
- lua_pushstring(L, "invalid-resource");
+ lua_pushstring(L, "setrlimit-failed");
return 2;
}
+
lua_pushboolean(L, 1);
return 1;
}
@@ -546,7 +607,7 @@ int lc_getrlimit(lua_State *L) {
int rid = -1;
struct rlimit lim;
- if (arguments != 1) {
+ if(arguments != 1) {
lua_pushboolean(L, 0);
lua_pushstring(L, "invalid-arguments");
return 2;
@@ -554,40 +615,52 @@ int lc_getrlimit(lua_State *L) {
resource = luaL_checkstring(L, 1);
rid = string2resource(resource);
- if (rid != -1) {
- if (getrlimit(rid, &lim)) {
+
+ if(rid != -1) {
+ if(getrlimit(rid, &lim)) {
lua_pushboolean(L, 0);
lua_pushstring(L, "getrlimit-failed.");
return 2;
}
} else {
- /* Unsupported resoucrce. Sorry I'm pretty limited by POSIX standard. */
+ /* Unsupported resource. Sorry I'm pretty limited by POSIX standard. */
lua_pushboolean(L, 0);
lua_pushstring(L, "invalid-resource");
return 2;
}
+
lua_pushboolean(L, 1);
- lua_pushnumber(L, lim.rlim_cur);
- lua_pushnumber(L, lim.rlim_max);
+
+ if(lim.rlim_cur == RLIM_INFINITY) {
+ lua_pushstring(L, "unlimited");
+ } else {
+ lua_pushnumber(L, lim.rlim_cur);
+ }
+
+ if(lim.rlim_max == RLIM_INFINITY) {
+ lua_pushstring(L, "unlimited");
+ } else {
+ lua_pushnumber(L, lim.rlim_max);
+ }
+
return 3;
}
-int lc_abort(lua_State* L)
-{
+int lc_abort(lua_State *L) {
abort();
return 0;
}
-int lc_uname(lua_State* L)
-{
+int lc_uname(lua_State *L) {
struct utsname uname_info;
- if(uname(&uname_info) != 0)
- {
+
+ if(uname(&uname_info) != 0) {
lua_pushnil(L);
lua_pushstring(L, strerror(errno));
return 2;
}
- lua_newtable(L);
+
+ lua_createtable(L, 0, 6);
lua_pushstring(L, uname_info.sysname);
lua_setfield(L, -2, "sysname");
lua_pushstring(L, uname_info.nodename);
@@ -598,31 +671,32 @@ int lc_uname(lua_State* L)
lua_setfield(L, -2, "version");
lua_pushstring(L, uname_info.machine);
lua_setfield(L, -2, "machine");
+#ifdef __USE_GNU
+ lua_pushstring(L, uname_info.domainname);
+ lua_setfield(L, -2, "domainname");
+#endif
return 1;
}
-int lc_setenv(lua_State* L)
-{
+int lc_setenv(lua_State *L) {
const char *var = luaL_checkstring(L, 1);
const char *value;
/* If the second argument is nil or nothing, unset the var */
- if(lua_isnoneornil(L, 2))
- {
- if(unsetenv(var) != 0)
- {
+ if(lua_isnoneornil(L, 2)) {
+ if(unsetenv(var) != 0) {
lua_pushnil(L);
lua_pushstring(L, strerror(errno));
return 2;
}
+
lua_pushboolean(L, 1);
return 1;
}
value = luaL_checkstring(L, 2);
- if(setenv(var, value, 1) != 0)
- {
+ if(setenv(var, value, 1) != 0) {
lua_pushnil(L);
lua_pushstring(L, strerror(errno));
return 2;
@@ -633,10 +707,9 @@ int lc_setenv(lua_State* L)
}
#ifdef WITH_MALLINFO
-int lc_meminfo(lua_State* L)
-{
+int lc_meminfo(lua_State *L) {
struct mallinfo info = mallinfo();
- lua_newtable(L);
+ lua_createtable(L, 0, 5);
/* This is the total size of memory allocated with sbrk by malloc, in bytes. */
lua_pushinteger(L, info.arena);
lua_setfield(L, -2, "allocated");
@@ -661,63 +734,66 @@ int lc_meminfo(lua_State* L)
* https://github.com/rrthomas/luaposix/blob/master/lposix.c#L631
* */
-#if _XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L || defined(_GNU_SOURCE)
-int lc_fallocate(lua_State* L)
-{
+int lc_fallocate(lua_State *L) {
int ret;
off_t offset, len;
- FILE *f = *(FILE**) luaL_checkudata(L, 1, LUA_FILEHANDLE);
- if (f == NULL)
- luaL_error(L, "attempt to use a closed file");
+ FILE *f = *(FILE **) luaL_checkudata(L, 1, LUA_FILEHANDLE);
+
+ if(f == NULL) {
+ return luaL_error(L, "attempt to use a closed file");
+ }
offset = luaL_checkinteger(L, 2);
len = luaL_checkinteger(L, 3);
-#if defined(__linux__) && defined(_GNU_SOURCE)
+#if defined(__linux__)
errno = 0;
ret = fallocate(fileno(f), FALLOC_FL_KEEP_SIZE, offset, len);
- if(ret == 0)
- {
+
+ if(ret == 0) {
lua_pushboolean(L, 1);
return 1;
}
+
/* Some old versions of Linux apparently use the return value instead of errno */
- if(errno == 0) errno = ret;
+ if(errno == 0) {
+ errno = ret;
+ }
- if(errno != ENOSYS && errno != EOPNOTSUPP)
- {
+ if(errno != ENOSYS && errno != EOPNOTSUPP) {
lua_pushnil(L);
lua_pushstring(L, strerror(errno));
return 2;
}
-#else
-#warning Only using posix_fallocate() fallback.
-#warning Linux fallocate() is strongly recommended if available: recompile with -D_GNU_SOURCE
-#warning Note that posix_fallocate() will still be used on filesystems that dont support fallocate()
+
#endif
ret = posix_fallocate(fileno(f), offset, len);
- if(ret == 0)
- {
+
+ if(ret == 0) {
lua_pushboolean(L, 1);
return 1;
- }
- else
- {
+ } else {
lua_pushnil(L);
lua_pushstring(L, strerror(ret));
+
/* posix_fallocate() can leave a bunch of NULs at the end, so we cut that
* this assumes that offset == length of the file */
- ftruncate(fileno(f), offset);
+ if(ftruncate(fileno(f), offset) != 0) {
+ lua_pushstring(L, strerror(errno));
+ return 3;
+ }
+
return 2;
}
}
-#endif
/* Register functions */
-int luaopen_util_pposix(lua_State *L)
-{
+int luaopen_util_pposix(lua_State *L) {
+#if (LUA_VERSION_NUM > 501)
+ luaL_checkversion(L);
+#endif
luaL_Reg exports[] = {
{ "abort", lc_abort },
@@ -751,14 +827,18 @@ int luaopen_util_pposix(lua_State *L)
{ "meminfo", lc_meminfo },
#endif
-#if _XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L || defined(_GNU_SOURCE)
{ "fallocate", lc_fallocate },
-#endif
{ NULL, NULL }
};
- luaL_register(L, "pposix", exports);
+ lua_newtable(L);
+ luaL_setfuncs(L, exports, 0);
+
+#ifdef ENOENT
+ lua_pushinteger(L, ENOENT);
+ lua_setfield(L, -2, "ENOENT");
+#endif
lua_pushliteral(L, "pposix");
lua_setfield(L, -2, "_NAME");