tek.os.posix has been moved to tek.lib.posix, module initialization procedure
authorTimm S. Mueller <tmueller@neoscientists.org>
Fri, 24 Oct 2008 01:35:27 +0200
changeset 2512de5931b723d
parent 250 5107767c6c1e
child 252 8b4bf1c5d718
tek.os.posix has been moved to tek.lib.posix, module initialization procedure
simplified, added statvfs() under Linux
Makefile
cgi-bin/Makefile
cgi-bin/tek/class/loona.lua
cgi-bin/tek/class/loona/util.lua
cgi-bin/tek/lib/posix.c
cgi-bin/tek/os/posix.c
     1.1 --- a/Makefile	Fri Oct 24 01:19:42 2008 +0200
     1.2 +++ b/Makefile	Fri Oct 24 01:35:27 2008 +0200
     1.3 @@ -47,6 +47,9 @@
     1.4  	@echo
     1.5  
     1.6  
     1.7 +all: modules
     1.8 +
     1.9 +
    1.10  clean install modules:
    1.11  	$(MAKE) -C cgi-bin $@
    1.12  
    1.13 @@ -73,9 +76,6 @@
    1.14  	find . -name CVS -type d | xargs -r chmod g+rw
    1.15  
    1.16  
    1.17 -all: modules setup permissions
    1.18 -
    1.19 -
    1.20  distclean: clean
    1.21  	-rm -Rf $(CONTENTDIR)
    1.22  	-rm -Rf $(VARDIR)
     2.1 --- a/cgi-bin/Makefile	Fri Oct 24 01:19:42 2008 +0200
     2.2 +++ b/cgi-bin/Makefile	Fri Oct 24 01:35:27 2008 +0200
     2.3 @@ -4,7 +4,9 @@
     2.4  #DEBUG = -g
     2.5  OPT = -O2
     2.6  
     2.7 -INSTPATH ?= /usr/local/lib/lua/5.1
     2.8 +LUA_LIB ?= /usr/local/lib/lua/5.1
     2.9 +LUA_SHARE ?= /usr/local/share/lua/5.1
    2.10 +LUA_MODULES = tek/lib/luahtml.so tek/lib/posix.so
    2.11  
    2.12  help:
    2.13  	@echo
    2.14 @@ -12,7 +14,7 @@
    2.15  	@echo "-------------------------------------------------------------------------------"
    2.16  	@echo "help .......... This help"
    2.17  	@echo "modules ....... Build modules"
    2.18 -	@echo "install ....... Install modules [INSTPATH: $(INSTPATH)]"
    2.19 +	@echo "install ....... Install modules [LUA_SHARE: $(LUA_SHARE)]"
    2.20  	@echo
    2.21  	@echo "fastcgi-run ... Run as FastCGI external server"
    2.22  	@echo "                See loona_fastcgi.lua for configuration options"
    2.23 @@ -24,36 +26,38 @@
    2.24  .c.o:
    2.25  	$(CC) $(INCL) $(WARN) $(DEBUG) $(OPT) -fPIC -DPIC -c $? -o $@
    2.26  
    2.27 -modules: tek/lib/luahtml.so tek/os/posix.so
    2.28 +modules: $(LUA_MODULES)
    2.29  
    2.30  all: modules
    2.31  
    2.32 -install: tek/lib/luahtml.so tek/os/posix.so
    2.33 -	-install -d $(INSTPATH)/tek/app $(INSTPATH)/tek/lib $(INSTPATH)/tek/os
    2.34 -	-install -d $(INSTPATH)/tek/class/cgi $(INSTPATH)/tek/class/loona
    2.35 -	-install -s tek/lib/*.so $(INSTPATH)/tek/lib
    2.36 -	-install -s tek/os/*.so $(INSTPATH)/tek/os
    2.37 -	-luac -s -o $(INSTPATH)/tek/lib.lua tek/lib.lua
    2.38 -	-luac -s -o $(INSTPATH)/tek/lib/debug.lua tek/lib/debug.lua
    2.39 -	-luac -s -o $(INSTPATH)/tek/app/loona.lua tek/app/loona.lua
    2.40 -	-luac -s -o $(INSTPATH)/tek/class.lua tek/class.lua
    2.41 -	-luac -s -o $(INSTPATH)/tek/class/cgi.lua tek/class/cgi.lua
    2.42 -	-luac -s -o $(INSTPATH)/tek/class/fastcgi.lua tek/class/fastcgi.lua
    2.43 -	-luac -s -o $(INSTPATH)/tek/class/cgi/post.lua tek/class/cgi/post.lua
    2.44 -	-luac -s -o $(INSTPATH)/tek/class/cgi/request.lua tek/class/cgi/request.lua
    2.45 -	-luac -s -o $(INSTPATH)/tek/class/loona.lua tek/class/loona.lua
    2.46 -	-luac -s -o $(INSTPATH)/tek/class/loona/buffer.lua tek/class/loona/buffer.lua
    2.47 -	-luac -s -o $(INSTPATH)/tek/class/markup.lua tek/class/markup.lua
    2.48 -	-luac -s -o $(INSTPATH)/tek/class/loona/util.lua tek/class/loona/util.lua
    2.49 +install: $(LUA_MODULES)
    2.50 +	-install -d $(LUA_LIB)/tek/lib
    2.51 +	-install -d $(LUA_SHARE)/tek/app
    2.52 +	-install -d $(LUA_SHARE)/tek/lib
    2.53 +	-install -d $(LUA_SHARE)/tek/class/cgi
    2.54 +	-install -d $(LUA_SHARE)/tek/class/loona
    2.55 +	-install -s tek/lib/posix.so tek/lib/luahtml.so $(LUA_LIB)/tek/lib
    2.56 +	-luac -s -o $(LUA_SHARE)/tek/lib.lua tek/lib.lua
    2.57 +	-luac -s -o $(LUA_SHARE)/tek/lib/debug.lua tek/lib/debug.lua
    2.58 +	-luac -s -o $(LUA_SHARE)/tek/app/loona.lua tek/app/loona.lua
    2.59 +	-luac -s -o $(LUA_SHARE)/tek/class.lua tek/class.lua
    2.60 +	-luac -s -o $(LUA_SHARE)/tek/class/cgi.lua tek/class/cgi.lua
    2.61 +	-luac -s -o $(LUA_SHARE)/tek/class/fastcgi.lua tek/class/fastcgi.lua
    2.62 +	-luac -s -o $(LUA_SHARE)/tek/class/cgi/post.lua tek/class/cgi/post.lua
    2.63 +	-luac -s -o $(LUA_SHARE)/tek/class/cgi/request.lua tek/class/cgi/request.lua
    2.64 +	-luac -s -o $(LUA_SHARE)/tek/class/loona.lua tek/class/loona.lua
    2.65 +	-luac -s -o $(LUA_SHARE)/tek/class/loona/buffer.lua tek/class/loona/buffer.lua
    2.66 +	-luac -s -o $(LUA_SHARE)/tek/class/markup.lua tek/class/markup.lua
    2.67 +	-luac -s -o $(LUA_SHARE)/tek/class/loona/util.lua tek/class/loona/util.lua
    2.68  
    2.69  tek/lib/luahtml.so: tek/lib/luahtml.o
    2.70  	$(CC) $^ -shared -o $@ $(LIBS)
    2.71  
    2.72 -tek/os/posix.so: tek/os/posix.o
    2.73 +tek/lib/posix.so: tek/lib/posix.o
    2.74  	$(CC) $^ -shared -o $@ $(LIBS)
    2.75  
    2.76  clean:
    2.77 -	-rm tek/lib/*.so tek/lib/*.o tek/os/*.so tek/os/*.o
    2.78 +	-rm tek/lib/*.so tek/lib/*.o
    2.79  
    2.80  fastcgi-run:
    2.81  	./loona_fastcgi.lua
     3.1 --- a/cgi-bin/tek/class/loona.lua	Fri Oct 24 01:19:42 2008 +0200
     3.2 +++ b/cgi-bin/tek/class/loona.lua	Fri Oct 24 01:35:27 2008 +0200
     3.3 @@ -8,7 +8,7 @@
     3.4  local Class = require "tek.class"
     3.5  local lib = require "tek.lib"
     3.6  local luahtml = require "tek.lib.luahtml"
     3.7 -local posix = require "tek.os.posix"
     3.8 +local posix = require "tek.lib.posix"
     3.9  local cgi = require "tek.class.cgi"
    3.10  local Request = require "tek.class.cgi.request"
    3.11  local util = require "tek.class.loona.util"
     4.1 --- a/cgi-bin/tek/class/loona/util.lua	Fri Oct 24 01:19:42 2008 +0200
     4.2 +++ b/cgi-bin/tek/class/loona/util.lua	Fri Oct 24 01:35:27 2008 +0200
     4.3 @@ -6,7 +6,7 @@
     4.4  --
     4.5  
     4.6  local utf8values = require "tek.lib".utf8values
     4.7 -local posix = require "tek.os.posix"
     4.8 +local posix = require "tek.lib.posix"
     4.9  local assert, os_time, os_remove = assert, os.time, os.remove
    4.10  local insert, concat, char = table.insert, table.concat, string.char
    4.11  
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/cgi-bin/tek/lib/posix.c	Fri Oct 24 01:35:27 2008 +0200
     5.3 @@ -0,0 +1,467 @@
     5.4 +
     5.5 +/*
     5.6 +**	tek.lib.posix - tek POSIX library
     5.7 +**	Written by Timm S. Mueller <tmueller at neoscientists.org>
     5.8 +**	See copyright notice in COPYRIGHT
     5.9 +*/
    5.10 +
    5.11 +
    5.12 +#include <stdlib.h>
    5.13 +#include <string.h>
    5.14 +#include <sys/types.h>
    5.15 +#include <sys/stat.h>
    5.16 +#include <unistd.h>
    5.17 +#include <dirent.h>
    5.18 +#include <errno.h>
    5.19 +#include <math.h>
    5.20 +#include <time.h>
    5.21 +#include <lua.h>
    5.22 +#include <lualib.h>
    5.23 +#include <lauxlib.h>
    5.24 +
    5.25 +
    5.26 +#define DIRCLASSNAME "dir*"
    5.27 +
    5.28 +
    5.29 +static void
    5.30 +setfield(lua_State *L, const char *attr, const char *key, lua_Integer n)
    5.31 +{
    5.32 +	if (attr == NULL || strcmp(attr, key) == 0)
    5.33 +		lua_pushinteger(L, n);
    5.34 +	if (attr == NULL)
    5.35 +		lua_setfield(L, -2, key);
    5.36 +}
    5.37 +
    5.38 +
    5.39 +static int
    5.40 +setstat(lua_State *L, int result, struct stat *s, const char *attr)
    5.41 +{
    5.42 +	if (result != 0)
    5.43 +	{
    5.44 +		lua_pushnil(L);
    5.45 +		lua_pushstring(L, strerror(errno));
    5.46 +		return 2;
    5.47 +	}
    5.48 +
    5.49 +	if (attr == NULL)
    5.50 +		lua_newtable(L);
    5.51 +
    5.52 +	setfield(L, attr, "dev", s->st_dev);
    5.53 +	setfield(L, attr, "ino", s->st_ino);
    5.54 +
    5.55 +	if (attr == NULL || strcmp(attr, "mode") == 0)
    5.56 +	{
    5.57 +		if (S_ISREG(s->st_mode))
    5.58 +			lua_pushstring(L, "file");
    5.59 +		else if (S_ISDIR(s->st_mode))
    5.60 +			lua_pushstring(L, "directory");
    5.61 +		else if (S_ISLNK(s->st_mode))
    5.62 +			lua_pushstring(L, "link");
    5.63 +		else if (S_ISSOCK(s->st_mode))
    5.64 +			lua_pushstring(L, "socket");
    5.65 +		else if (S_ISFIFO(s->st_mode))
    5.66 +			lua_pushstring(L, "named pipe");
    5.67 +		else if (S_ISCHR(s->st_mode))
    5.68 +			lua_pushstring(L, "char device");
    5.69 +		else if (S_ISBLK(s->st_mode))
    5.70 +			lua_pushstring(L, "block device");
    5.71 +		else
    5.72 +			lua_pushstring(L, "other");
    5.73 +		if (attr == NULL)
    5.74 +			lua_setfield(L, -2, "mode");
    5.75 +	}
    5.76 +
    5.77 +	setfield(L, attr, "nlink", s->st_nlink);
    5.78 +	setfield(L, attr, "uid", s->st_uid);
    5.79 +	setfield(L, attr, "gid", s->st_gid);
    5.80 +	setfield(L, attr, "rdev", s->st_rdev);
    5.81 +	setfield(L, attr, "access", s->st_atime);
    5.82 +	setfield(L, attr, "modification", s->st_mtime);
    5.83 +	setfield(L, attr, "change", s->st_ctime);
    5.84 +	setfield(L, attr, "size", s->st_size);
    5.85 +	setfield(L, attr, "blocks", s->st_blocks);
    5.86 +	setfield(L, attr, "blksize", s->st_blksize);
    5.87 +
    5.88 +	return 1;
    5.89 +}
    5.90 +
    5.91 +
    5.92 +static int
    5.93 +posix_stat(lua_State *L)
    5.94 +{
    5.95 +	const char *path = luaL_checkstring(L, 1);
    5.96 +	const char *attr = luaL_optstring(L, 2, NULL);
    5.97 +	struct stat s;
    5.98 +	return setstat(L, stat(path, &s), &s, attr);
    5.99 +}
   5.100 +
   5.101 +
   5.102 +static int
   5.103 +posix_lstat(lua_State *L)
   5.104 +{
   5.105 +	const char *path = luaL_checkstring(L, 1);
   5.106 +	const char *attr = luaL_optstring(L, 2, NULL);
   5.107 +	struct stat s;
   5.108 +	return setstat(L, lstat(path, &s), &s, attr);
   5.109 +}
   5.110 +
   5.111 +
   5.112 +static int
   5.113 +posix_opendir(lua_State *L)
   5.114 +{
   5.115 +	const char *path = luaL_checkstring(L, 1);
   5.116 +	DIR **pdir = lua_newuserdata(L, sizeof(void *));
   5.117 +	/* s: udata */
   5.118 +	*pdir = opendir(path);
   5.119 +	if (*pdir == NULL)
   5.120 +	{
   5.121 +		lua_pushnil(L);
   5.122 +		lua_pushstring(L, strerror(errno));
   5.123 +		return 2;
   5.124 +	}
   5.125 +	lua_getfield(L, LUA_REGISTRYINDEX, DIRCLASSNAME);
   5.126 +	/* s: udata, meta */
   5.127 +	lua_setmetatable(L, -2);
   5.128 +	/* s: udata */
   5.129 +	return 1;
   5.130 +}
   5.131 +
   5.132 +
   5.133 +static DIR **
   5.134 +getinstptr(lua_State *L, int narg, const char *classname)
   5.135 +{
   5.136 +	DIR **pinst = luaL_checkudata(L, narg, classname);
   5.137 +	if (*pinst) return pinst;
   5.138 +	luaL_argerror(L, narg, "Closed handle");
   5.139 +	return NULL;
   5.140 +}
   5.141 +
   5.142 +
   5.143 +static int
   5.144 +posix_closedir(lua_State *L)
   5.145 +{
   5.146 +	DIR **pdir = getinstptr(L, 1, DIRCLASSNAME);
   5.147 +	closedir(*pdir);
   5.148 +	*pdir = NULL;
   5.149 +	return 0;
   5.150 +}
   5.151 +
   5.152 +
   5.153 +static int
   5.154 +posix_readdir(lua_State *L)
   5.155 +{
   5.156 +	DIR *dir = *getinstptr(L, 1, DIRCLASSNAME);
   5.157 +	struct dirent *de = readdir(dir);
   5.158 +	if (de)
   5.159 +		lua_pushstring(L, de->d_name);
   5.160 +	else
   5.161 +		lua_pushnil(L);
   5.162 +	return 1;
   5.163 +}
   5.164 +
   5.165 +
   5.166 +static int
   5.167 +posix_readlink(lua_State *L)
   5.168 +{
   5.169 +	const char *path = luaL_checkstring(L, 1);
   5.170 +	char buf[PATH_MAX + 1];
   5.171 +	ssize_t len = readlink(path, buf, sizeof(buf) - 1);
   5.172 +	if (len < 0)
   5.173 +	{
   5.174 +		lua_pushnil(L);
   5.175 +		lua_pushstring(L, strerror(errno));
   5.176 +		return 2;
   5.177 +	}
   5.178 +	buf[len] = 0;
   5.179 +	lua_pushstring(L, buf);
   5.180 +	return 1;
   5.181 +}
   5.182 +
   5.183 +
   5.184 +static int
   5.185 +posix_mkdir(lua_State *L)
   5.186 +{
   5.187 +	const char *path = luaL_checkstring(L, 1);
   5.188 +	if (mkdir(path, 0775) == 0)
   5.189 +	{
   5.190 +		lua_pushboolean(L, 1);
   5.191 +		return 1;
   5.192 +	}
   5.193 +	lua_pushnil(L);
   5.194 +	lua_pushstring(L, strerror(errno));
   5.195 +	return 2;
   5.196 +}
   5.197 +
   5.198 +
   5.199 +static int
   5.200 +posix_symlink(lua_State *L)
   5.201 +{
   5.202 +	const char *oldpath = luaL_checkstring(L, 1);
   5.203 +	const char *newpath = luaL_checkstring(L, 2);
   5.204 +	if (symlink(oldpath, newpath) == 0)
   5.205 +	{
   5.206 +		lua_pushboolean(L, 1);
   5.207 +		return 1;
   5.208 +	}
   5.209 +	lua_pushnil(L);
   5.210 +	lua_pushstring(L, strerror(errno));
   5.211 +	return 2;
   5.212 +}
   5.213 +
   5.214 +
   5.215 +static int
   5.216 +resolvepath(const char *src, char *dest)
   5.217 +{
   5.218 +	int len = strlen(src);
   5.219 +	const char *sp = src + len;
   5.220 +	char *dp = dest;
   5.221 +	int dc = 0, slc = 0, eac = 0, wc = 0;
   5.222 +	int i, c;
   5.223 +
   5.224 +	while (len--)
   5.225 +	{
   5.226 +		c = *(--sp);
   5.227 +		switch (c)
   5.228 +		{
   5.229 +			case '/':
   5.230 +				if (dc == 2)
   5.231 +					eac++;
   5.232 +				dc = 0;
   5.233 +				slc = 1;
   5.234 +				wc = 0;
   5.235 +				break;
   5.236 +
   5.237 +			case '.':
   5.238 +				if (slc)
   5.239 +				{
   5.240 +					dc++;
   5.241 +					break;
   5.242 +				}
   5.243 +				/* fallthru: */
   5.244 +
   5.245 +			default:
   5.246 +				if (wc)
   5.247 +					break;
   5.248 +
   5.249 +				if (slc)
   5.250 +				{
   5.251 +					slc = 0;
   5.252 +
   5.253 +					if (eac > 0)
   5.254 +					{
   5.255 +						/* resolve one eatcount */
   5.256 +						eac--;
   5.257 +						/* now wait for next path part */
   5.258 +						wc = 1;
   5.259 +						break;
   5.260 +					}
   5.261 +
   5.262 +					*dp++ = '/';
   5.263 +				}
   5.264 +
   5.265 +				while (dc == 2 || dc == 1)
   5.266 +				{
   5.267 +					*dp++ = '.';
   5.268 +					dc--;
   5.269 +				}
   5.270 +				dc = 0;
   5.271 +
   5.272 +				*dp++ = c;
   5.273 +				break;
   5.274 +		}
   5.275 +	}
   5.276 +
   5.277 +	/* unresolved eatcount */
   5.278 +	if (eac)
   5.279 +		return 0;
   5.280 +
   5.281 +	/* resolve remaining slash */
   5.282 +	if (slc)
   5.283 +		*dp++ = '/';
   5.284 +
   5.285 +	*dp = 0;
   5.286 +
   5.287 +	len = dp - dest;
   5.288 +	for (i = 0; i < len / 2; ++i)
   5.289 +	{
   5.290 +		char t = dest[i];
   5.291 +		dest[i] = dest[len - i - 1];
   5.292 +		dest[len - i - 1] = t;
   5.293 +	}
   5.294 +
   5.295 +	return 1;
   5.296 +}
   5.297 +
   5.298 +
   5.299 +static int
   5.300 +posix_abspath(lua_State *L)
   5.301 +{
   5.302 +	const char *path = luaL_checkstring(L, 1);
   5.303 +	char *pwd = NULL;
   5.304 +	size_t pwdsize = 16;
   5.305 +	size_t len1, len2;
   5.306 +	char *srcpath, *dstpath;
   5.307 +
   5.308 +	for (;;)
   5.309 +	{
   5.310 +		if (path[0] == '/')
   5.311 +		{
   5.312 +			pwd = malloc(2);
   5.313 +			if (pwd == NULL)
   5.314 +				break;
   5.315 +			pwd[0] = '/';
   5.316 +			pwd[1] = 0;
   5.317 +		}
   5.318 +		else
   5.319 +		{
   5.320 +			char *newpwd = realloc(pwd, pwdsize);
   5.321 +			if (newpwd == NULL)
   5.322 +				break;
   5.323 +			pwd = newpwd;
   5.324 +
   5.325 +			if (!getcwd(pwd, pwdsize))
   5.326 +			{
   5.327 +				if (errno == ERANGE)
   5.328 +				{
   5.329 +					pwdsize <<= 1;
   5.330 +					continue;
   5.331 +				}
   5.332 +				lua_pushnil(L);
   5.333 +				lua_pushstring(L, strerror(errno));
   5.334 +				return 2;
   5.335 +			}
   5.336 +		}
   5.337 +
   5.338 +		len1 = strlen(pwd);
   5.339 +		len2 = strlen(path);
   5.340 +		srcpath = malloc(len1 + 1 + len2 + 1);
   5.341 +		dstpath = malloc(len1 + 1 + len2 + 1);
   5.342 +
   5.343 +		if (srcpath && dstpath)
   5.344 +		{
   5.345 +			int res;
   5.346 +
   5.347 +			strcpy(srcpath, pwd);
   5.348 +			free(pwd);
   5.349 +			srcpath[len1] = '/';
   5.350 +			strcpy(srcpath + len1 + 1, path);
   5.351 +			res = resolvepath(srcpath, dstpath);
   5.352 +			free(srcpath);
   5.353 +
   5.354 +			if (res)
   5.355 +			{
   5.356 +				lua_pushstring(L, dstpath);
   5.357 +				free(dstpath);
   5.358 +				return 1;
   5.359 +			}
   5.360 +
   5.361 +			free(dstpath);
   5.362 +			lua_pushnil(L);
   5.363 +			lua_pushstring(L, "Not a valid path");
   5.364 +			return 2;
   5.365 +		}
   5.366 +
   5.367 +		free(srcpath);
   5.368 +		free(dstpath);
   5.369 +		break;
   5.370 +	}
   5.371 +
   5.372 +	free(pwd);
   5.373 +	luaL_error(L, "Out of memory");
   5.374 +	return 0;
   5.375 +}
   5.376 +
   5.377 +
   5.378 +static int
   5.379 +posix_nanosleep(lua_State *L)
   5.380 +{
   5.381 +	struct timespec req;
   5.382 +	lua_Number d = luaL_checknumber(L, 1);
   5.383 +
   5.384 +	req.tv_sec = (time_t) d;
   5.385 +	req.tv_nsec = (long) ((d - req.tv_sec) * 1000000000);
   5.386 +
   5.387 +	if (nanosleep(&req, NULL) == 0)
   5.388 +	{
   5.389 +		lua_pushboolean(L, 1);
   5.390 +		return 1;
   5.391 +	}
   5.392 +
   5.393 +	lua_pushnil(L);
   5.394 +	lua_pushstring(L, strerror(errno));
   5.395 +	return 2;
   5.396 +}
   5.397 +
   5.398 +#if defined(__linux)
   5.399 +#include <sys/statvfs.h>
   5.400 +
   5.401 +static int
   5.402 +posix_statvfs(lua_State *L)
   5.403 +{
   5.404 +	struct statvfs buf;
   5.405 +	const char *path = luaL_checkstring(L, 1);
   5.406 +	if (statvfs(path, &buf) == 0)
   5.407 +	{
   5.408 +		lua_newtable(L);
   5.409 +		lua_pushinteger(L, buf.f_bsize);
   5.410 +		lua_setfield(L, -2, "bsize");
   5.411 +		lua_pushinteger(L, buf.f_blocks);
   5.412 +		lua_setfield(L, -2, "blocks");
   5.413 +		lua_pushinteger(L, buf.f_bfree);
   5.414 +		lua_setfield(L, -2, "bfree");
   5.415 +		lua_pushinteger(L, buf.f_fsid);
   5.416 +		lua_setfield(L, -2, "fsid");
   5.417 +		lua_pushinteger(L, buf.f_namemax);
   5.418 +		lua_setfield(L, -2, "namemax");
   5.419 +		return 1;
   5.420 +	}
   5.421 +	lua_pushnil(L);
   5.422 +	lua_pushstring(L, strerror(errno));
   5.423 +	return 2;
   5.424 +}
   5.425 +
   5.426 +#endif
   5.427 +
   5.428 +static const luaL_Reg libfuncs[] =
   5.429 +{
   5.430 +	{ "stat", posix_stat },
   5.431 +	{ "lstat", posix_lstat },
   5.432 +	{ "opendir", posix_opendir },
   5.433 +	{ "closedir", posix_closedir },
   5.434 +	{ "readdir", posix_readdir },
   5.435 +	{ "mkdir", posix_mkdir },
   5.436 +	{ "readlink", posix_readlink },
   5.437 +	{ "symlink", posix_symlink },
   5.438 +	{ "abspath", posix_abspath },
   5.439 +	{ "nanosleep", posix_nanosleep },
   5.440 +#if defined(__linux)
   5.441 +	{ "statvfs", posix_statvfs },
   5.442 +#endif
   5.443 +	{ NULL, NULL }
   5.444 +};
   5.445 +
   5.446 +
   5.447 +static const luaL_Reg dirmethods[] =
   5.448 +{
   5.449 +	{"read", posix_readdir },
   5.450 +	{"close", posix_closedir },
   5.451 +	{"__gc", posix_closedir },
   5.452 +	{NULL, NULL}
   5.453 +};
   5.454 +
   5.455 +int luaopen_tek_lib_posix(lua_State *L)
   5.456 +{
   5.457 +	luaL_register(L, "tek.lib.posix", libfuncs);
   5.458 +	/* s: lib */
   5.459 +	luaL_newmetatable(L, DIRCLASSNAME);
   5.460 +	/* s: lib, meta */
   5.461 +	lua_pushvalue(L, -1);
   5.462 +	/* s: lib, meta, meta */
   5.463 +	lua_setfield(L, -2, "__index");
   5.464 +	/* s: lib, meta */
   5.465 +	luaL_register(L, NULL, dirmethods);
   5.466 +	/* s: lib, meta */
   5.467 +	lua_pop(L, 2);
   5.468 +	/* s: */
   5.469 +	return 0;
   5.470 +}
     6.1 --- a/cgi-bin/tek/os/posix.c	Fri Oct 24 01:19:42 2008 +0200
     6.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.3 @@ -1,453 +0,0 @@
     6.4 -
     6.5 -/*
     6.6 -**	tek.os.posix - tek POSIX library
     6.7 -**	Written by Timm S. Mueller <tmueller at neoscientists.org>
     6.8 -**	See copyright notice in COPYRIGHT
     6.9 -*/
    6.10 -
    6.11 -#include <stdlib.h>
    6.12 -#include <string.h>
    6.13 -#include <sys/types.h>
    6.14 -#include <sys/stat.h>
    6.15 -#include <unistd.h>
    6.16 -#include <dirent.h>
    6.17 -#include <errno.h>
    6.18 -#include <math.h>
    6.19 -#include <time.h>
    6.20 -#include <lua.h>
    6.21 -#include <lualib.h>
    6.22 -#include <lauxlib.h>
    6.23 -
    6.24 -
    6.25 -#define DIRCLASSNAME "dir*"
    6.26 -
    6.27 -
    6.28 -static void
    6.29 -setfield(lua_State *L, const char *attr, const char *key, lua_Integer n)
    6.30 -{
    6.31 -	if (attr == NULL || strcmp(attr, key) == 0)
    6.32 -		lua_pushinteger(L, n);
    6.33 -	if (attr == NULL)
    6.34 -		lua_setfield(L, -2, key);
    6.35 -}
    6.36 -
    6.37 -
    6.38 -static int
    6.39 -setstat(lua_State *L, int result, struct stat *s, const char *attr)
    6.40 -{
    6.41 -	if (result != 0)
    6.42 -	{
    6.43 -		lua_pushnil(L);
    6.44 -		lua_pushstring(L, strerror(errno));
    6.45 -		return 2;
    6.46 -	}
    6.47 -
    6.48 -	if (attr == NULL)
    6.49 -		lua_newtable(L);
    6.50 -
    6.51 -	setfield(L, attr, "dev", s->st_dev);
    6.52 -	setfield(L, attr, "ino", s->st_ino);
    6.53 -
    6.54 -	if (attr == NULL || strcmp(attr, "mode") == 0)
    6.55 -	{
    6.56 -		if (S_ISREG(s->st_mode))
    6.57 -			lua_pushstring(L, "file");
    6.58 -		else if (S_ISDIR(s->st_mode))
    6.59 -			lua_pushstring(L, "directory");
    6.60 -		else if (S_ISLNK(s->st_mode))
    6.61 -			lua_pushstring(L, "link");
    6.62 -		else if (S_ISSOCK(s->st_mode))
    6.63 -			lua_pushstring(L, "socket");
    6.64 -		else if (S_ISFIFO(s->st_mode))
    6.65 -			lua_pushstring(L, "named pipe");
    6.66 -		else if (S_ISCHR(s->st_mode))
    6.67 -			lua_pushstring(L, "char device");
    6.68 -		else if (S_ISBLK(s->st_mode))
    6.69 -			lua_pushstring(L, "block device");
    6.70 -		else
    6.71 -			lua_pushstring(L, "other");
    6.72 -		if (attr == NULL)
    6.73 -			lua_setfield(L, -2, "mode");
    6.74 -	}
    6.75 -
    6.76 -	setfield(L, attr, "nlink", s->st_nlink);
    6.77 -	setfield(L, attr, "uid", s->st_uid);
    6.78 -	setfield(L, attr, "gid", s->st_gid);
    6.79 -	setfield(L, attr, "rdev", s->st_rdev);
    6.80 -	setfield(L, attr, "access", s->st_atime);
    6.81 -	setfield(L, attr, "modifications", s->st_mtime);
    6.82 -	setfield(L, attr, "change", s->st_ctime);
    6.83 -	setfield(L, attr, "size", s->st_size);
    6.84 -	setfield(L, attr, "blocks", s->st_blocks);
    6.85 -	setfield(L, attr, "blksize", s->st_blksize);
    6.86 -
    6.87 -	return 1;
    6.88 -}
    6.89 -
    6.90 -
    6.91 -static int
    6.92 -posix_stat(lua_State *L)
    6.93 -{
    6.94 -	const char *path = luaL_checkstring(L, 1);
    6.95 -	const char *attr = luaL_optstring(L, 2, NULL);
    6.96 -	struct stat s;
    6.97 -	return setstat(L, stat(path, &s), &s, attr);
    6.98 -}
    6.99 -
   6.100 -
   6.101 -static int
   6.102 -posix_lstat(lua_State *L)
   6.103 -{
   6.104 -	const char *path = luaL_checkstring(L, 1);
   6.105 -	const char *attr = luaL_optstring(L, 2, NULL);
   6.106 -	struct stat s;
   6.107 -	return setstat(L, lstat(path, &s), &s, attr);
   6.108 -}
   6.109 -
   6.110 -
   6.111 -static int
   6.112 -posix_opendir(lua_State *L)
   6.113 -{
   6.114 -	const char *path = luaL_checkstring(L, 1);
   6.115 -	DIR **pdir = lua_newuserdata(L, sizeof(void *));
   6.116 -	*pdir = NULL;
   6.117 -	lua_pushvalue(L, lua_upvalueindex(2)); /* class metatable */
   6.118 -	/* attach metatable to the userdata object */
   6.119 -	lua_setmetatable(L, -2); /* s: udata */
   6.120 -	/* create class instance */
   6.121 -	*pdir = opendir(path);
   6.122 -	if (*pdir == NULL)
   6.123 -	{
   6.124 -		lua_pushnil(L);
   6.125 -		lua_pushstring(L, strerror(errno));
   6.126 -		return 2;
   6.127 -	}
   6.128 -	return 1;
   6.129 -}
   6.130 -
   6.131 -
   6.132 -static DIR **
   6.133 -getinstptr(lua_State *L, int narg, const char *classname)
   6.134 -{
   6.135 -	DIR **pinst = luaL_checkudata(L, narg, classname);
   6.136 -	if (*pinst) return pinst;
   6.137 -	luaL_argerror(L, narg, "Closed handle");
   6.138 -	return NULL;
   6.139 -}
   6.140 -
   6.141 -
   6.142 -static int
   6.143 -posix_closedir(lua_State *L)
   6.144 -{
   6.145 -	DIR **pdir = getinstptr(L, 1, DIRCLASSNAME);
   6.146 -	closedir(*pdir);
   6.147 -	*pdir = NULL;
   6.148 -	return 0;
   6.149 -}
   6.150 -
   6.151 -
   6.152 -static int
   6.153 -posix_readdir(lua_State *L)
   6.154 -{
   6.155 -	DIR *dir = *getinstptr(L, 1, DIRCLASSNAME);
   6.156 -	struct dirent *de = readdir(dir);
   6.157 -	if (de)
   6.158 -		lua_pushstring(L, de->d_name);
   6.159 -	else
   6.160 -		lua_pushnil(L);
   6.161 -	return 1;
   6.162 -}
   6.163 -
   6.164 -
   6.165 -static int
   6.166 -posix_readlink(lua_State *L)
   6.167 -{
   6.168 -	const char *path = luaL_checkstring(L, 1);
   6.169 -	char buf[PATH_MAX + 1];
   6.170 -	ssize_t len = readlink(path, buf, sizeof(buf) - 1);
   6.171 -	if (len < 0)
   6.172 -	{
   6.173 -		lua_pushnil(L);
   6.174 -		lua_pushstring(L, strerror(errno));
   6.175 -		return 2;
   6.176 -	}
   6.177 -	buf[len] = 0;
   6.178 -	lua_pushstring(L, buf);
   6.179 -	return 1;
   6.180 -}
   6.181 -
   6.182 -
   6.183 -static int
   6.184 -posix_mkdir(lua_State *L)
   6.185 -{
   6.186 -	const char *path = luaL_checkstring(L, 1);
   6.187 -	if (mkdir(path, 0775) == 0)
   6.188 -	{
   6.189 -		lua_pushboolean(L, 1);
   6.190 -		return 1;
   6.191 -	}
   6.192 -	lua_pushnil(L);
   6.193 -	lua_pushstring(L, strerror(errno));
   6.194 -	return 2;
   6.195 -}
   6.196 -
   6.197 -
   6.198 -static int
   6.199 -posix_symlink(lua_State *L)
   6.200 -{
   6.201 -	const char *oldpath = luaL_checkstring(L, 1);
   6.202 -	const char *newpath = luaL_checkstring(L, 2);
   6.203 -	if (symlink(oldpath, newpath) == 0)
   6.204 -	{
   6.205 -		lua_pushboolean(L, 1);
   6.206 -		return 1;
   6.207 -	}
   6.208 -	lua_pushnil(L);
   6.209 -	lua_pushstring(L, strerror(errno));
   6.210 -	return 2;
   6.211 -}
   6.212 -
   6.213 -
   6.214 -static int
   6.215 -resolvepath(const char *src, char *dest)
   6.216 -{
   6.217 -	int len = strlen(src);
   6.218 -	const char *sp = src + len;
   6.219 -	char *dp = dest;
   6.220 -	int dc = 0, slc = 0, eac = 0, wc = 0;
   6.221 -	int i, c;
   6.222 -
   6.223 -	while (len--)
   6.224 -	{
   6.225 -		c = *(--sp);
   6.226 -		switch (c)
   6.227 -		{
   6.228 -			case '/':
   6.229 -				if (dc == 2)
   6.230 -					eac++;
   6.231 -				dc = 0;
   6.232 -				slc = 1;
   6.233 -				wc = 0;
   6.234 -				break;
   6.235 -
   6.236 -			case '.':
   6.237 -				if (slc)
   6.238 -				{
   6.239 -					dc++;
   6.240 -					break;
   6.241 -				}
   6.242 -				/* fallthru: */
   6.243 -
   6.244 -			default:
   6.245 -				if (wc)
   6.246 -					break;
   6.247 -
   6.248 -				if (slc)
   6.249 -				{
   6.250 -					slc = 0;
   6.251 -
   6.252 -					if (eac > 0)
   6.253 -					{
   6.254 -						/* resolve one eatcount */
   6.255 -						eac--;
   6.256 -						/* now wait for next path part */
   6.257 -						wc = 1;
   6.258 -						break;
   6.259 -					}
   6.260 -
   6.261 -					*dp++ = '/';
   6.262 -				}
   6.263 -
   6.264 -				while (dc == 2 || dc == 1)
   6.265 -				{
   6.266 -					*dp++ = '.';
   6.267 -					dc--;
   6.268 -				}
   6.269 -				dc = 0;
   6.270 -
   6.271 -				*dp++ = c;
   6.272 -				break;
   6.273 -		}
   6.274 -	}
   6.275 -
   6.276 -	/* unresolved eatcount */
   6.277 -	if (eac)
   6.278 -		return 0;
   6.279 -
   6.280 -	/* resolve remaining slash */
   6.281 -	if (slc)
   6.282 -		*dp++ = '/';
   6.283 -
   6.284 -	*dp = 0;
   6.285 -
   6.286 -	len = dp - dest;
   6.287 -	for (i = 0; i < len / 2; ++i)
   6.288 -	{
   6.289 -		char t = dest[i];
   6.290 -		dest[i] = dest[len - i - 1];
   6.291 -		dest[len - i - 1] = t;
   6.292 -	}
   6.293 -
   6.294 -	return 1;
   6.295 -}
   6.296 -
   6.297 -
   6.298 -static int
   6.299 -posix_abspath(lua_State *L)
   6.300 -{
   6.301 -	const char *path = luaL_checkstring(L, 1);
   6.302 -	char *pwd = NULL;
   6.303 -	size_t pwdsize = 16;
   6.304 -	size_t len1, len2;
   6.305 -	char *srcpath, *dstpath;
   6.306 -
   6.307 -	for (;;)
   6.308 -	{
   6.309 -		if (path[0] == '/')
   6.310 -		{
   6.311 -			pwd = malloc(2);
   6.312 -			if (pwd == NULL)
   6.313 -				break;
   6.314 -			pwd[0] = '/';
   6.315 -			pwd[1] = 0;
   6.316 -		}
   6.317 -		else
   6.318 -		{
   6.319 -			char *newpwd = realloc(pwd, pwdsize);
   6.320 -			if (newpwd == NULL)
   6.321 -				break;
   6.322 -			pwd = newpwd;
   6.323 -
   6.324 -			if (!getcwd(pwd, pwdsize))
   6.325 -			{
   6.326 -				if (errno == ERANGE)
   6.327 -				{
   6.328 -					pwdsize <<= 1;
   6.329 -					continue;
   6.330 -				}
   6.331 -				lua_pushnil(L);
   6.332 -				lua_pushstring(L, strerror(errno));
   6.333 -				return 2;
   6.334 -			}
   6.335 -		}
   6.336 -
   6.337 -		len1 = strlen(pwd);
   6.338 -		len2 = strlen(path);
   6.339 -		srcpath = malloc(len1 + 1 + len2 + 1);
   6.340 -		dstpath = malloc(len1 + 1 + len2 + 1);
   6.341 -
   6.342 -		if (srcpath && dstpath)
   6.343 -		{
   6.344 -			int res;
   6.345 -
   6.346 -			strcpy(srcpath, pwd);
   6.347 -			free(pwd);
   6.348 -			srcpath[len1] = '/';
   6.349 -			strcpy(srcpath + len1 + 1, path);
   6.350 -			res = resolvepath(srcpath, dstpath);
   6.351 -			free(srcpath);
   6.352 -
   6.353 -			if (res)
   6.354 -			{
   6.355 -				lua_pushstring(L, dstpath);
   6.356 -				free(dstpath);
   6.357 -				return 1;
   6.358 -			}
   6.359 -
   6.360 -			free(dstpath);
   6.361 -			lua_pushnil(L);
   6.362 -			lua_pushstring(L, "Not a valid path");
   6.363 -			return 2;
   6.364 -		}
   6.365 -
   6.366 -		free(srcpath);
   6.367 -		free(dstpath);
   6.368 -		break;
   6.369 -	}
   6.370 -
   6.371 -	free(pwd);
   6.372 -	luaL_error(L, "Out of memory");
   6.373 -	return 0;
   6.374 -}
   6.375 -
   6.376 -
   6.377 -static int
   6.378 -posix_nanosleep(lua_State *L)
   6.379 -{
   6.380 -	struct timespec req;
   6.381 -	lua_Number d = luaL_checknumber(L, 1);
   6.382 -
   6.383 -	req.tv_sec = (time_t) d;
   6.384 -	req.tv_nsec = (long) ((d - req.tv_sec) * 1000000000);
   6.385 -
   6.386 -	if (nanosleep(&req, NULL) == 0)
   6.387 -	{
   6.388 -		lua_pushboolean(L, 1);
   6.389 -		return 1;
   6.390 -	}
   6.391 -
   6.392 -	lua_pushnil(L);
   6.393 -	lua_pushstring(L, strerror(errno));
   6.394 -	return 2;
   6.395 -}
   6.396 -
   6.397 -
   6.398 -static const luaL_Reg lib[] =
   6.399 -{
   6.400 -	{ "stat", posix_stat },
   6.401 -	{ "lstat", posix_lstat },
   6.402 -	{ "opendir", posix_opendir },
   6.403 -	{ "closedir", posix_closedir },
   6.404 -	{ "readdir", posix_readdir },
   6.405 -	{ "mkdir", posix_mkdir },
   6.406 -	{ "readlink", posix_readlink },
   6.407 -	{ "symlink", posix_symlink },
   6.408 -	{ "abspath", posix_abspath },
   6.409 -	{ "nanosleep", posix_nanosleep },
   6.410 -	{ NULL, NULL }
   6.411 -};
   6.412 -
   6.413 -
   6.414 -static const luaL_Reg methods[] =
   6.415 -{
   6.416 -	{"read", posix_readdir },
   6.417 -	{"close", posix_closedir },
   6.418 -	{"__gc", posix_closedir },
   6.419 -	{NULL, NULL}
   6.420 -};
   6.421 -
   6.422 -
   6.423 -static void
   6.424 -addclass(lua_State *L, const char *libname, const char *classname,
   6.425 -	const luaL_Reg *functions, const luaL_Reg *methods, void *userdata)
   6.426 -{
   6.427 -	luaL_newmetatable(L, classname); /* classtab */
   6.428 -	lua_pushliteral(L, "__index"); /* classtab, "__index" */
   6.429 -
   6.430 -	/* insert self: classtab.__index = classtab */
   6.431 -	lua_pushvalue(L, -2); /* classtab, "__index", classtab */
   6.432 -	lua_rawset(L, -3); /* classtab */
   6.433 -
   6.434 -	/* insert methods. consume 1 userdata. do not create a new tab */
   6.435 -	lua_pushlightuserdata(L, userdata); /* classtab, userdata */
   6.436 -	luaL_openlib(L, NULL, methods, 1); /* classtab */
   6.437 -
   6.438 -	/* first upvalue: userdata */
   6.439 -	lua_pushlightuserdata(L, userdata); /* classtab, userdata */
   6.440 -
   6.441 -	/* duplicate table argument to be used as second upvalue for cclosure */
   6.442 -	lua_pushvalue(L, -2); /* classtab, userdata, classtab */
   6.443 -
   6.444 -	/* insert functions */
   6.445 -	luaL_openlib(L, libname, functions, 2);	/* classtab, libtab */
   6.446 -
   6.447 -	/* adjust stack */
   6.448 -	lua_pop(L, 2);
   6.449 -}
   6.450 -
   6.451 -
   6.452 -int luaopen_tek_os_posix(lua_State *L)
   6.453 -{
   6.454 -	addclass(L, "tek.os.posix", DIRCLASSNAME, lib, methods, NULL);
   6.455 -	return 0;
   6.456 -}