浏览代码

replace Windows CRLF with Unix newline

Signed-off-by: Danny Al-Gaaf <danny.al-gaaf@bisect.de>
Danny Al-Gaaf 10 年之前
父节点
当前提交
ec9d5413a8
共有 6 个文件被更改,包括 1336 次插入1336 次删除
  1. 187 187
      examples/websocket/WebSockCallbacks.c
  2. 38 38
      examples/websocket/WebSockCallbacks.h
  3. 17 17
      src/main.c
  4. 895 895
      src/third_party/lfs.c
  5. 17 17
      src/third_party/lfs.h
  6. 182 182
      test/embed.c

+ 187 - 187
examples/websocket/WebSockCallbacks.c

@@ -1,187 +1,187 @@
-#include <assert.h>
-#include <stdlib.h>
-#include <time.h>
-#include <string.h>
-#include "WebSockCallbacks.h"
-
-#ifdef _WIN32
-#include <Windows.h>
-#define mg_sleep(x) Sleep(x)
-#else
-#include <unistd.h>
-#include <pthread.h>
-#define mg_sleep(x) usleep((x) * 1000)
-#endif
-
-
-static void send_to_all_websockets(struct mg_context *ctx, const char * data, int data_len) {
-
-    int i;
-    tWebSockContext *ws_ctx = (tWebSockContext*) mg_get_user_data(ctx);
-
-    mg_lock_context(ctx);
-    for (i=0;i<MAX_NUM_OF_WEBSOCKS;i++) {
-        if (ws_ctx->socketList[i] && (ws_ctx->socketList[i]->webSockState==2)) {
-            mg_websocket_write(ws_ctx->socketList[i]->conn, WEBSOCKET_OPCODE_TEXT, data, data_len);
-        }
-    }
-    mg_unlock_context(ctx);
-}
-
-
-void websocket_ready_handler(struct mg_connection *conn) {
-
-    int i;
-    struct mg_request_info * rq = mg_get_request_info(conn);
-    struct mg_context * ctx = mg_get_context(conn);
-    tWebSockContext *ws_ctx = (tWebSockContext*) mg_get_user_data(ctx);
-    tWebSockInfo * wsock = malloc(sizeof(tWebSockInfo));
-    assert(wsock);
-    wsock->webSockState = 0;
-    rq->conn_data = wsock;
-
-    mg_lock_context(ctx);
-    for (i=0;i<MAX_NUM_OF_WEBSOCKS;i++) {
-        if (0==ws_ctx->socketList[i]) {
-            ws_ctx->socketList[i] = wsock;
-            wsock->conn = conn;
-            wsock->webSockState = 1;
-            break;
-        }
-    }
-    printf("\nNew websocket attached: %s:%u\n", rq->remote_addr, rq->remote_port);
-    mg_unlock_context(ctx);
-}
-
-
-static void websocket_done(tWebSockContext *ws_ctx, tWebSockInfo * wsock) {
-
-    int i;
-
-    if (wsock) {
-        wsock->webSockState = 99;
-        for (i=0;i<MAX_NUM_OF_WEBSOCKS;i++) {
-            if (wsock==ws_ctx->socketList[i]) {
-                ws_ctx->socketList[i] = 0;
-                break;
-            }
-        }
-        printf("\nClose websocket attached: %s:%u\n", mg_get_request_info(wsock->conn)->remote_addr, mg_get_request_info(wsock->conn)->remote_port);
-        free(wsock);
-    }
-}
-
-
-int websocket_data_handler(struct mg_connection *conn, int flags, char *data, size_t data_len) {
-
-    struct mg_request_info * rq = mg_get_request_info(conn);
-    tWebSockInfo * wsock = (tWebSockInfo*)rq->conn_data;
-    struct mg_context * ctx = mg_get_context(conn);
-    tWebSockContext *ws_ctx = (tWebSockContext*) mg_get_user_data(ctx);
-    char msg[128];
-
-    mg_lock_context(ctx);
-    if (flags==136) {
-        // close websock
-        websocket_done(ws_ctx, wsock);
-        rq->conn_data = 0;
-        mg_unlock_context(ctx);
-        return 1;
-    }
-    if (((data_len>=5) && (data_len<100) && (flags==129)) || (flags==130)) {
-
-        // init command
-        if ((wsock->webSockState==1) && (!memcmp(data,"init ",5))) {
-            char * chk;
-            unsigned long gid;
-            memcpy(msg,data+5,data_len-5);
-            msg[data_len-5]=0;
-            gid = strtoul(msg,&chk,10);
-            wsock->initId = gid;
-            if (gid>0 && chk!=NULL && *chk==0) {
-                wsock->webSockState = 2;
-            }
-            mg_unlock_context(ctx);
-            return 1;
-        }
-
-        // chat message
-        if ((wsock->webSockState==2) && (!memcmp(data,"msg ",4))) {
-            send_to_all_websockets(ctx, data, data_len);
-            mg_unlock_context(ctx);
-            return 1;
-        }
-    }
-
-    // keep alive
-    if ((data_len==4) && !memcmp(data,"ping",4)) {
-        mg_unlock_context(ctx);
-        return 1;
-    }
-
-    mg_unlock_context(ctx);
-    return 0;
-}
-
-
-void connection_close_handler(struct mg_connection *conn) {
-
-    struct mg_request_info * rq = mg_get_request_info(conn);
-    tWebSockInfo * wsock = (tWebSockInfo*)rq->conn_data;
-    struct mg_context * ctx = mg_get_context(conn);
-    tWebSockContext *ws_ctx = (tWebSockContext*) mg_get_user_data(ctx);
-
-    mg_lock_context(ctx);
-    websocket_done(ws_ctx, wsock);
-    rq->conn_data = 0;
-    mg_unlock_context(ctx);
-}
-
-
-static void * eventMain(void * arg) {
-
-    char msg[256];
-    struct mg_context *ctx = (struct mg_context *)arg;
-    tWebSockContext *ws_ctx = (tWebSockContext*) mg_get_user_data(ctx);
-
-    ws_ctx->runLoop = 1;
-    while (ws_ctx->runLoop) {
-        time_t t = time(0);
-        struct tm * timestr = localtime(&t);
-        sprintf(msg,"title %s",asctime(timestr));
-
-        send_to_all_websockets(ctx, msg, strlen(msg));
-
-        mg_sleep(1000);
-    }
-
-    return NULL;
-}
-
-void websock_send_broadcast(struct mg_context *ctx, const char * data, int data_len) {
-
-    char buffer[260];
-
-    if (data_len<=256) {
-        strcpy(buffer, "msg ");
-        memcpy(buffer+4, data, data_len);
-
-        send_to_all_websockets(ctx, buffer, data_len+4);
-    }
-}
-
-void websock_init_lib(struct mg_context *ctx) {
-
-    tWebSockContext *ws_ctx = (tWebSockContext*) mg_get_user_data(ctx);
-    memset(ws_ctx,0,sizeof(*ws_ctx));
-    /* todo: use mg_start_thread_id instead of mg_start_thread */
-    mg_start_thread(eventMain, ctx);
-}
-
-void websock_exit_lib(struct mg_context *ctx) {
-
-    tWebSockContext *ws_ctx = (tWebSockContext*) mg_get_user_data(ctx);
-    ws_ctx->runLoop = 0;
-    /* todo: wait for the thread instead of a timeout */
-    mg_sleep(2000);
-}
+#include <assert.h>
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+#include "WebSockCallbacks.h"
+
+#ifdef _WIN32
+#include <Windows.h>
+#define mg_sleep(x) Sleep(x)
+#else
+#include <unistd.h>
+#include <pthread.h>
+#define mg_sleep(x) usleep((x) * 1000)
+#endif
+
+
+static void send_to_all_websockets(struct mg_context *ctx, const char * data, int data_len) {
+
+    int i;
+    tWebSockContext *ws_ctx = (tWebSockContext*) mg_get_user_data(ctx);
+
+    mg_lock_context(ctx);
+    for (i=0;i<MAX_NUM_OF_WEBSOCKS;i++) {
+        if (ws_ctx->socketList[i] && (ws_ctx->socketList[i]->webSockState==2)) {
+            mg_websocket_write(ws_ctx->socketList[i]->conn, WEBSOCKET_OPCODE_TEXT, data, data_len);
+        }
+    }
+    mg_unlock_context(ctx);
+}
+
+
+void websocket_ready_handler(struct mg_connection *conn) {
+
+    int i;
+    struct mg_request_info * rq = mg_get_request_info(conn);
+    struct mg_context * ctx = mg_get_context(conn);
+    tWebSockContext *ws_ctx = (tWebSockContext*) mg_get_user_data(ctx);
+    tWebSockInfo * wsock = malloc(sizeof(tWebSockInfo));
+    assert(wsock);
+    wsock->webSockState = 0;
+    rq->conn_data = wsock;
+
+    mg_lock_context(ctx);
+    for (i=0;i<MAX_NUM_OF_WEBSOCKS;i++) {
+        if (0==ws_ctx->socketList[i]) {
+            ws_ctx->socketList[i] = wsock;
+            wsock->conn = conn;
+            wsock->webSockState = 1;
+            break;
+        }
+    }
+    printf("\nNew websocket attached: %s:%u\n", rq->remote_addr, rq->remote_port);
+    mg_unlock_context(ctx);
+}
+
+
+static void websocket_done(tWebSockContext *ws_ctx, tWebSockInfo * wsock) {
+
+    int i;
+
+    if (wsock) {
+        wsock->webSockState = 99;
+        for (i=0;i<MAX_NUM_OF_WEBSOCKS;i++) {
+            if (wsock==ws_ctx->socketList[i]) {
+                ws_ctx->socketList[i] = 0;
+                break;
+            }
+        }
+        printf("\nClose websocket attached: %s:%u\n", mg_get_request_info(wsock->conn)->remote_addr, mg_get_request_info(wsock->conn)->remote_port);
+        free(wsock);
+    }
+}
+
+
+int websocket_data_handler(struct mg_connection *conn, int flags, char *data, size_t data_len) {
+
+    struct mg_request_info * rq = mg_get_request_info(conn);
+    tWebSockInfo * wsock = (tWebSockInfo*)rq->conn_data;
+    struct mg_context * ctx = mg_get_context(conn);
+    tWebSockContext *ws_ctx = (tWebSockContext*) mg_get_user_data(ctx);
+    char msg[128];
+
+    mg_lock_context(ctx);
+    if (flags==136) {
+        // close websock
+        websocket_done(ws_ctx, wsock);
+        rq->conn_data = 0;
+        mg_unlock_context(ctx);
+        return 1;
+    }
+    if (((data_len>=5) && (data_len<100) && (flags==129)) || (flags==130)) {
+
+        // init command
+        if ((wsock->webSockState==1) && (!memcmp(data,"init ",5))) {
+            char * chk;
+            unsigned long gid;
+            memcpy(msg,data+5,data_len-5);
+            msg[data_len-5]=0;
+            gid = strtoul(msg,&chk,10);
+            wsock->initId = gid;
+            if (gid>0 && chk!=NULL && *chk==0) {
+                wsock->webSockState = 2;
+            }
+            mg_unlock_context(ctx);
+            return 1;
+        }
+
+        // chat message
+        if ((wsock->webSockState==2) && (!memcmp(data,"msg ",4))) {
+            send_to_all_websockets(ctx, data, data_len);
+            mg_unlock_context(ctx);
+            return 1;
+        }
+    }
+
+    // keep alive
+    if ((data_len==4) && !memcmp(data,"ping",4)) {
+        mg_unlock_context(ctx);
+        return 1;
+    }
+
+    mg_unlock_context(ctx);
+    return 0;
+}
+
+
+void connection_close_handler(struct mg_connection *conn) {
+
+    struct mg_request_info * rq = mg_get_request_info(conn);
+    tWebSockInfo * wsock = (tWebSockInfo*)rq->conn_data;
+    struct mg_context * ctx = mg_get_context(conn);
+    tWebSockContext *ws_ctx = (tWebSockContext*) mg_get_user_data(ctx);
+
+    mg_lock_context(ctx);
+    websocket_done(ws_ctx, wsock);
+    rq->conn_data = 0;
+    mg_unlock_context(ctx);
+}
+
+
+static void * eventMain(void * arg) {
+
+    char msg[256];
+    struct mg_context *ctx = (struct mg_context *)arg;
+    tWebSockContext *ws_ctx = (tWebSockContext*) mg_get_user_data(ctx);
+
+    ws_ctx->runLoop = 1;
+    while (ws_ctx->runLoop) {
+        time_t t = time(0);
+        struct tm * timestr = localtime(&t);
+        sprintf(msg,"title %s",asctime(timestr));
+
+        send_to_all_websockets(ctx, msg, strlen(msg));
+
+        mg_sleep(1000);
+    }
+
+    return NULL;
+}
+
+void websock_send_broadcast(struct mg_context *ctx, const char * data, int data_len) {
+
+    char buffer[260];
+
+    if (data_len<=256) {
+        strcpy(buffer, "msg ");
+        memcpy(buffer+4, data, data_len);
+
+        send_to_all_websockets(ctx, buffer, data_len+4);
+    }
+}
+
+void websock_init_lib(struct mg_context *ctx) {
+
+    tWebSockContext *ws_ctx = (tWebSockContext*) mg_get_user_data(ctx);
+    memset(ws_ctx,0,sizeof(*ws_ctx));
+    /* todo: use mg_start_thread_id instead of mg_start_thread */
+    mg_start_thread(eventMain, ctx);
+}
+
+void websock_exit_lib(struct mg_context *ctx) {
+
+    tWebSockContext *ws_ctx = (tWebSockContext*) mg_get_user_data(ctx);
+    ws_ctx->runLoop = 0;
+    /* todo: wait for the thread instead of a timeout */
+    mg_sleep(2000);
+}

+ 38 - 38
examples/websocket/WebSockCallbacks.h

@@ -1,39 +1,39 @@
-
-#ifndef WEBSOCKCALLBACKS_H_INCLUDED
-#define WEBSOCKCALLBACKS_H_INCLUDED
-
-#include "civetweb.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct tWebSockInfo {
-    int webSockState;
-    unsigned long initId;
-    struct mg_connection *conn;
-} tWebSockInfo;
-
-#define MAX_NUM_OF_WEBSOCKS (256)
-typedef struct tWebSockContext {
-    int runLoop;
-    void * thread_id;
-    tWebSockInfo *socketList[MAX_NUM_OF_WEBSOCKS];
-} tWebSockContext;
-
-
-void websock_init_lib(struct mg_context *ctx);
-void websock_exit_lib(struct mg_context *ctx);
-
-void websock_send_broadcast(struct mg_context *ctx, const char * data, int data_len);
-
-void websocket_ready_handler(struct mg_connection *conn);
-int websocket_data_handler(struct mg_connection *conn, int flags, char *data, size_t data_len);
-void connection_close_handler(struct mg_connection *conn);
-
-
-#ifdef __cplusplus
-}
-#endif
-
+
+#ifndef WEBSOCKCALLBACKS_H_INCLUDED
+#define WEBSOCKCALLBACKS_H_INCLUDED
+
+#include "civetweb.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct tWebSockInfo {
+    int webSockState;
+    unsigned long initId;
+    struct mg_connection *conn;
+} tWebSockInfo;
+
+#define MAX_NUM_OF_WEBSOCKS (256)
+typedef struct tWebSockContext {
+    int runLoop;
+    void * thread_id;
+    tWebSockInfo *socketList[MAX_NUM_OF_WEBSOCKS];
+} tWebSockContext;
+
+
+void websock_init_lib(struct mg_context *ctx);
+void websock_exit_lib(struct mg_context *ctx);
+
+void websock_send_broadcast(struct mg_context *ctx, const char * data, int data_len);
+
+void websocket_ready_handler(struct mg_connection *conn);
+int websocket_data_handler(struct mg_connection *conn, int flags, char *data, size_t data_len);
+void connection_close_handler(struct mg_connection *conn);
+
+
+#ifdef __cplusplus
+}
+#endif
+
 #endif

+ 17 - 17
src/main.c

@@ -1510,25 +1510,25 @@ static int MakeConsole() {
     if (!ok) {
         if (!AttachConsole(ATTACH_PARENT_PROCESS)) {
             FreeConsole();
-            if (!AllocConsole()) {
-                err = GetLastError();
-                if (err==ERROR_ACCESS_DENIED) {
-                    MessageBox(NULL, "Insufficient rights to create a console window", "Error", MB_ICONERROR);
-                }
-            }
-            AttachConsole(GetCurrentProcessId());
-        }
+            if (!AllocConsole()) {
+                err = GetLastError();
+                if (err==ERROR_ACCESS_DENIED) {
+                    MessageBox(NULL, "Insufficient rights to create a console window", "Error", MB_ICONERROR);
+                }
+            }
+            AttachConsole(GetCurrentProcessId());
+        }
 
         ok = (GetConsoleWindow() != NULL);
-        if (ok) {
-            freopen("CONIN$", "r", stdin);
-            freopen("CONOUT$", "w", stdout);
-            freopen("CONOUT$", "w", stderr);
-        }
-    }
-
-    if (ok) {
-        SetConsoleTitle(server_name);
+        if (ok) {
+            freopen("CONIN$", "r", stdin);
+            freopen("CONOUT$", "w", stdout);
+            freopen("CONOUT$", "w", stderr);
+        }
+    }
+
+    if (ok) {
+        SetConsoleTitle(server_name);
     }
 
     return ok;

+ 895 - 895
src/third_party/lfs.c

@@ -1,895 +1,895 @@
-/*
-** LuaFileSystem
-** Copyright Kepler Project 2003 (http://www.keplerproject.org/luafilesystem)
-**
-** File system manipulation library.
-** This library offers these functions:
-**   lfs.attributes (filepath [, attributename])
-**   lfs.chdir (path)
-**   lfs.currentdir ()
-**   lfs.dir (path)
-**   lfs.lock (fh, mode)
-**   lfs.lock_dir (path)
-**   lfs.mkdir (path)
-**   lfs.rmdir (path)
-**   lfs.setmode (filepath, mode)
-**   lfs.symlinkattributes (filepath [, attributename]) -- thanks to Sam Roberts
-**   lfs.touch (filepath [, atime [, mtime]])
-**   lfs.unlock (fh)
-**
-** $Id: lfs.c,v 1.61 2009/07/04 02:10:16 mascarenhas Exp $
-*/
-
-#ifdef _MSC_VER
-#ifndef _CRT_SECURE_NO_WARNINGS
-#define _CRT_SECURE_NO_WARNINGS /* disable Visual Studio compiler warnings for using standard C functions */
-#endif
-#endif
-
-#ifndef _WIN32
-#ifndef _AIX
-#define _FILE_OFFSET_BITS 64 /* Linux, Solaris and HP-UX */
-#else
-#define _LARGE_FILES 1 /* AIX */
-#endif
-#endif
-
-#define _LARGEFILE64_SOURCE
-
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <time.h>
-#include <sys/stat.h>
-
-#ifdef _WIN32
-#include <direct.h>
-#include <windows.h>
-#include <io.h>
-#include <sys/locking.h>
-#ifdef __BORLANDC__
- #include <utime.h>
-#else
- #include <sys/utime.h>
-#endif
-#include <fcntl.h>
-#else
-#include <unistd.h>
-#include <dirent.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <utime.h>
-#endif
-
-#include <lua.h>
-#include <lauxlib.h>
-#include <lualib.h>
-
-#include "lfs.h"
-
-#define LFS_VERSION "1.6.2"
-#define LFS_LIBNAME "lfs"
-
-#if LUA_VERSION_NUM < 502
-#  define luaL_newlib(L,l) (lua_newtable(L), luaL_register(L,NULL,l))
-#endif
-
-/* Define 'strerror' for systems that do not implement it */
-#ifdef NO_STRERROR
-#define strerror(_)     "System unable to describe the error"
-#endif
-
-/* Define 'getcwd' for systems that do not implement it */
-#ifdef NO_GETCWD
-#define getcwd(p,s)     NULL
-#define getcwd_error    "Function 'getcwd' not provided by system"
-#else
-#define getcwd_error    strerror(errno)
-  #ifdef _WIN32
-	 /* MAX_PATH seems to be 260. Seems kind of small. Is there a better one? */
-    #define LFS_MAXPATHLEN MAX_PATH
-  #else
-	/* For MAXPATHLEN: */
-    #include <sys/param.h>
-    #define LFS_MAXPATHLEN MAXPATHLEN
-  #endif
-#endif
-
-#define DIR_METATABLE "directory metatable"
-typedef struct dir_data {
-        int  closed;
-#ifdef _WIN32
-        long hFile;
-        char pattern[MAX_PATH+1];
-#else
-        DIR *dir;
-#endif
-} dir_data;
-
-#define LOCK_METATABLE "lock metatable"
-
-#ifdef _WIN32
- #ifdef __BORLANDC__
-  #define lfs_setmode(L,file,m)   ((void)L, setmode(_fileno(file), m))
-  #define STAT_STRUCT struct stati64
- #else
-  #define lfs_setmode(L,file,m)   ((void)L, _setmode(_fileno(file), m))
-  #define STAT_STRUCT struct _stati64
- #endif
-#define STAT_FUNC _stati64
-#define LSTAT_FUNC STAT_FUNC
-#else
-#define _O_TEXT               0
-#define _O_BINARY             0
-#define lfs_setmode(L,file,m)   ((void)L, (void)file, (void)m, 0)
-#define STAT_STRUCT struct stat
-#define STAT_FUNC stat
-#define LSTAT_FUNC lstat
-#endif
-
-/*
-** Utility functions
-*/
-static int pusherror(lua_State *L, const char *info)
-{
-        lua_pushnil(L);
-        if (info==NULL)
-                lua_pushstring(L, strerror(errno));
-        else
-                lua_pushfstring(L, "%s: %s", info, strerror(errno));
-        lua_pushinteger(L, errno);
-        return 3;
-}
-
-static int pushresult(lua_State *L, int i, const char *info)
-{
-        if (i==-1)
-                return pusherror(L, info);
-        lua_pushinteger(L, i);
-        return 1;
-}
-
-
-/*
-** This function changes the working (current) directory
-*/
-static int change_dir (lua_State *L) {
-        const char *path = luaL_checkstring(L, 1);
-        if (chdir(path)) {
-                lua_pushnil (L);
-                lua_pushfstring (L,"Unable to change working directory to '%s'\n%s\n",
-                                path, chdir_error);
-                return 2;
-        } else {
-                lua_pushboolean (L, 1);
-                return 1;
-        }
-}
-
-/*
-** This function returns the current directory
-** If unable to get the current directory, it returns nil
-**  and a string describing the error
-*/
-static int get_dir (lua_State *L) {
-  char *path;
-  /* Passing (NULL, 0) is not guaranteed to work. Use a temp buffer and size instead. */
-  char buf[LFS_MAXPATHLEN];
-  if ((path = getcwd(buf, LFS_MAXPATHLEN)) == NULL) {
-    lua_pushnil(L);
-    lua_pushstring(L, getcwd_error);
-    return 2;
-  }
-  else {
-    lua_pushstring(L, path);
-    return 1;
-  }
-}
-
-/*
-** Check if the given element on the stack is a file and returns it.
-*/
-static FILE *check_file (lua_State *L, int idx, const char *funcname) {
-        FILE **fh = (FILE **)luaL_checkudata (L, idx, "FILE*");
-        if (fh == NULL) {
-                luaL_error (L, "%s: not a file", funcname);
-                return 0;
-        } else if (*fh == NULL) {
-                luaL_error (L, "%s: closed file", funcname);
-                return 0;
-        } else
-                return *fh;
-}
-
-
-/*
-**
-*/
-static int _file_lock (lua_State *L, FILE *fh, const char *mode, const long start, long len, const char *funcname) {
-        int code;
-#ifdef _WIN32
-        /* lkmode valid values are:
-           LK_LOCK    Locks the specified bytes. If the bytes cannot be locked, the program immediately tries again after 1 second. If, after 10 attempts, the bytes cannot be locked, the constant returns an error.
-           LK_NBLCK   Locks the specified bytes. If the bytes cannot be locked, the constant returns an error.
-           LK_NBRLCK  Same as _LK_NBLCK.
-           LK_RLCK    Same as _LK_LOCK.
-           LK_UNLCK   Unlocks the specified bytes, which must have been previously locked.
-
-           Regions should be locked only briefly and should be unlocked before closing a file or exiting the program.
-
-           http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt__locking.asp
-        */
-        int lkmode;
-        switch (*mode) {
-                case 'r': lkmode = LK_NBLCK; break;
-                case 'w': lkmode = LK_NBLCK; break;
-                case 'u': lkmode = LK_UNLCK; break;
-                default : return luaL_error (L, "%s: invalid mode", funcname);
-        }
-        if (!len) {
-                fseek (fh, 0L, SEEK_END);
-                len = ftell (fh);
-        }
-        fseek (fh, start, SEEK_SET);
-#ifdef __BORLANDC__
-        code = locking (fileno(fh), lkmode, len);
-#else
-        code = _locking (fileno(fh), lkmode, len);
-#endif
-#else
-        struct flock f;
-        switch (*mode) {
-                case 'w': f.l_type = F_WRLCK; break;
-                case 'r': f.l_type = F_RDLCK; break;
-                case 'u': f.l_type = F_UNLCK; break;
-                default : return luaL_error (L, "%s: invalid mode", funcname);
-        }
-        f.l_whence = SEEK_SET;
-        f.l_start = (off_t)start;
-        f.l_len = (off_t)len;
-        code = fcntl (fileno(fh), F_SETLK, &f);
-#endif
-        return (code != -1);
-}
-
-#ifdef _WIN32
-typedef struct lfs_Lock {
-  HANDLE fd;
-} lfs_Lock;
-static int lfs_lock_dir(lua_State *L) {
-  size_t pathl; HANDLE fd;
-  lfs_Lock *lock;
-  char *ln;
-  const char *lockfile = "/lockfile.lfs";
-  const char *path = luaL_checklstring(L, 1, &pathl);
-  ln = (char*)malloc(pathl + strlen(lockfile) + 1);
-  if(!ln) {
-    lua_pushnil(L); lua_pushstring(L, strerror(errno)); return 2;
-  }
-  strcpy(ln, path); strcat(ln, lockfile);
-  /* Use "CreateFileA" to use the Multi-Byte-Character version, even if the rest of the project uses the Unicode (UTF16) version */
-  if((fd = CreateFileA(ln, GENERIC_WRITE, 0, NULL, CREATE_NEW,
-                FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL)) == INVALID_HANDLE_VALUE) {
-        int en = GetLastError();
-        free(ln); lua_pushnil(L);
-        if(en == ERROR_FILE_EXISTS || en == ERROR_SHARING_VIOLATION)
-                lua_pushstring(L, "File exists");
-        else
-                lua_pushstring(L, strerror(en));
-        return 2;
-  }
-  free(ln);
-  lock = (lfs_Lock*)lua_newuserdata(L, sizeof(lfs_Lock));
-  lock->fd = fd;
-  luaL_getmetatable (L, LOCK_METATABLE);
-  lua_setmetatable (L, -2);
-  return 1;
-}
-static int lfs_unlock_dir(lua_State *L) {
-  lfs_Lock *lock = luaL_checkudata(L, 1, LOCK_METATABLE);
-  CloseHandle(lock->fd);
-  return 0;
-}
-#else
-typedef struct lfs_Lock {
-  char *ln;
-} lfs_Lock;
-static int lfs_lock_dir(lua_State *L) {
-  lfs_Lock *lock;
-  size_t pathl;
-  char *ln;
-  const char *lockfile = "/lockfile.lfs";
-  const char *path = luaL_checklstring(L, 1, &pathl);
-  lock = (lfs_Lock*)lua_newuserdata(L, sizeof(lfs_Lock));
-  ln = (char*)malloc(pathl + strlen(lockfile) + 1);
-  if(!ln) {
-    lua_pushnil(L); lua_pushstring(L, strerror(errno)); return 2;
-  }
-  strcpy(ln, path); strcat(ln, lockfile);
-  if(symlink("lock", ln) == -1) {
-    free(ln); lua_pushnil(L);
-    lua_pushstring(L, strerror(errno)); return 2;
-  }
-  lock->ln = ln;
-  luaL_getmetatable (L, LOCK_METATABLE);
-  lua_setmetatable (L, -2);
-  return 1;
-}
-static int lfs_unlock_dir(lua_State *L) {
-  lfs_Lock *lock = luaL_checkudata(L, 1, LOCK_METATABLE);
-  if(lock->ln) {
-    unlink(lock->ln);
-    free(lock->ln);
-    lock->ln = NULL;
-  }
-  return 0;
-}
-#endif
-
-static int lfs_g_setmode (lua_State *L, FILE *f, int arg) {
-  static const int mode[] = {_O_BINARY, _O_TEXT};
-  static const char *const modenames[] = {"binary", "text", NULL};
-  int op = luaL_checkoption(L, arg, NULL, modenames);
-  int res = lfs_setmode(L, f, mode[op]);
-  if (res != -1) {
-    int i;
-    lua_pushboolean(L, 1);
-    for (i = 0; modenames[i] != NULL; i++) {
-      if (mode[i] == res) {
-        lua_pushstring(L, modenames[i]);
-        goto exit;
-      }
-    }
-    lua_pushnil(L);
-  exit:
-    return 2;
-  } else {
-    int en = errno;
-    lua_pushnil(L);
-    lua_pushfstring(L, "%s", strerror(en));
-    lua_pushinteger(L, en);
-    return 3;
-  }
-}
-
-static int lfs_f_setmode(lua_State *L) {
-  return lfs_g_setmode(L, check_file(L, 1, "setmode"), 2);
-}
-
-/*
-** Locks a file.
-** @param #1 File handle.
-** @param #2 String with lock mode ('w'rite, 'r'ead).
-** @param #3 Number with start position (optional).
-** @param #4 Number with length (optional).
-*/
-static int file_lock (lua_State *L) {
-        FILE *fh = check_file (L, 1, "lock");
-        const char *mode = luaL_checkstring (L, 2);
-        const long start = luaL_optlong (L, 3, 0);
-        long len = luaL_optlong (L, 4, 0);
-        if (_file_lock (L, fh, mode, start, len, "lock")) {
-                lua_pushboolean (L, 1);
-                return 1;
-        } else {
-                lua_pushnil (L);
-                lua_pushfstring (L, "%s", strerror(errno));
-                return 2;
-        }
-}
-
-
-/*
-** Unlocks a file.
-** @param #1 File handle.
-** @param #2 Number with start position (optional).
-** @param #3 Number with length (optional).
-*/
-static int file_unlock (lua_State *L) {
-        FILE *fh = check_file (L, 1, "unlock");
-        const long start = luaL_optlong (L, 2, 0);
-        long len = luaL_optlong (L, 3, 0);
-        if (_file_lock (L, fh, "u", start, len, "unlock")) {
-                lua_pushboolean (L, 1);
-                return 1;
-        } else {
-                lua_pushnil (L);
-                lua_pushfstring (L, "%s", strerror(errno));
-                return 2;
-        }
-}
-
-
-/*
-** Creates a link.
-** @param #1 Object to link to.
-** @param #2 Name of link.
-** @param #3 True if link is symbolic (optional).
-*/
-static int make_link(lua_State *L)
-{
-#ifndef _WIN32
-        const char *oldpath = luaL_checkstring(L, 1);
-        const char *newpath = luaL_checkstring(L, 2);
-        return pushresult(L,
-                (lua_toboolean(L,3) ? symlink : link)(oldpath, newpath), NULL);
-#else
-        return pusherror(L, "make_link is not supported on Windows");
-#endif
-}
-
-
-/*
-** Creates a directory.
-** @param #1 Directory path.
-*/
-static int make_dir (lua_State *L) {
-        const char *path = luaL_checkstring (L, 1);
-        int fail;
-#ifdef _WIN32
-        fail = _mkdir (path);
-#else
-        fail =  mkdir (path, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP |
-                             S_IWGRP | S_IXGRP | S_IROTH | S_IXOTH );
-#endif
-        if (fail) {
-                lua_pushnil (L);
-        lua_pushfstring (L, "%s", strerror(errno));
-                return 2;
-        }
-        lua_pushboolean (L, 1);
-        return 1;
-}
-
-/*
-** Removes a directory.
-** @param #1 Directory path.
-*/
-static int remove_dir (lua_State *L) {
-        const char *path = luaL_checkstring (L, 1);
-        int fail;
-
-        fail = rmdir (path);
-
-        if (fail) {
-                lua_pushnil (L);
-                lua_pushfstring (L, "%s", strerror(errno));
-                return 2;
-        }
-        lua_pushboolean (L, 1);
-        return 1;
-}
-
-/*
-** Directory iterator
-*/
-static int dir_iter (lua_State *L) {
-#ifdef _WIN32
-        struct _finddata_t c_file;
-#else
-        struct dirent *entry;
-#endif
-        dir_data *d = (dir_data *)luaL_checkudata (L, 1, DIR_METATABLE);
-        luaL_argcheck (L, d->closed == 0, 1, "closed directory");
-#ifdef _WIN32
-        if (d->hFile == 0L) { /* first entry */
-                if ((d->hFile = _findfirst (d->pattern, &c_file)) == -1L) {
-                        lua_pushnil (L);
-                        lua_pushstring (L, strerror (errno));
-                        d->closed = 1;
-                        return 2;
-                } else {
-                        lua_pushstring (L, c_file.name);
-                        return 1;
-                }
-        } else { /* next entry */
-                if (_findnext (d->hFile, &c_file) == -1L) {
-                        /* no more entries => close directory */
-                        _findclose (d->hFile);
-                        d->closed = 1;
-                        return 0;
-                } else {
-                        lua_pushstring (L, c_file.name);
-                        return 1;
-                }
-        }
-#else
-        if ((entry = readdir (d->dir)) != NULL) {
-                lua_pushstring (L, entry->d_name);
-                return 1;
-        } else {
-                /* no more entries => close directory */
-                closedir (d->dir);
-                d->closed = 1;
-                return 0;
-        }
-#endif
-}
-
-
-/*
-** Closes directory iterators
-*/
-static int dir_close (lua_State *L) {
-        dir_data *d = (dir_data *)lua_touserdata (L, 1);
-#ifdef _WIN32
-        if (!d->closed && d->hFile) {
-                _findclose (d->hFile);
-        }
-#else
-        if (!d->closed && d->dir) {
-                closedir (d->dir);
-        }
-#endif
-        d->closed = 1;
-        return 0;
-}
-
-
-/*
-** Factory of directory iterators
-*/
-static int dir_iter_factory (lua_State *L) {
-        const char *path = luaL_checkstring (L, 1);
-        dir_data *d;
-        lua_pushcfunction (L, dir_iter);
-        d = (dir_data *) lua_newuserdata (L, sizeof(dir_data));
-        luaL_getmetatable (L, DIR_METATABLE);
-        lua_setmetatable (L, -2);
-        d->closed = 0;
-#ifdef _WIN32
-        d->hFile = 0L;
-        if (strlen(path) > MAX_PATH-2)
-          luaL_error (L, "path too long: %s", path);
-        else
-          sprintf (d->pattern, "%s/*", path);
-#else
-        d->dir = opendir (path);
-        if (d->dir == NULL)
-          luaL_error (L, "cannot open %s: %s", path, strerror (errno));
-#endif
-        return 2;
-}
-
-
-/*
-** Creates directory metatable.
-*/
-static int dir_create_meta (lua_State *L) {
-        luaL_newmetatable (L, DIR_METATABLE);
-
-        /* Method table */
-        lua_newtable(L);
-        lua_pushcfunction (L, dir_iter);
-        lua_setfield(L, -2, "next");
-        lua_pushcfunction (L, dir_close);
-        lua_setfield(L, -2, "close");
-
-        /* Metamethods */
-        lua_setfield(L, -2, "__index");
-        lua_pushcfunction (L, dir_close);
-        lua_setfield (L, -2, "__gc");
-        return 1;
-}
-
-/*
-** Creates lock metatable.
-*/
-static int lock_create_meta (lua_State *L) {
-        luaL_newmetatable (L, LOCK_METATABLE);
-
-        /* Method table */
-        lua_newtable(L);
-        lua_pushcfunction(L, lfs_unlock_dir);
-        lua_setfield(L, -2, "free");
-
-        /* Metamethods */
-        lua_setfield(L, -2, "__index");
-        lua_pushcfunction(L, lfs_unlock_dir);
-        lua_setfield(L, -2, "__gc");
-        return 1;
-}
-
-
-#ifdef _WIN32
- #ifndef S_ISDIR
-   #define S_ISDIR(mode)  (mode&_S_IFDIR)
- #endif
- #ifndef S_ISREG
-   #define S_ISREG(mode)  (mode&_S_IFREG)
- #endif
- #ifndef S_ISLNK
-   #define S_ISLNK(mode)  (0)
- #endif
- #ifndef S_ISSOCK
-   #define S_ISSOCK(mode)  (0)
- #endif
- #ifndef S_ISFIFO
-   #define S_ISFIFO(mode)  (0)
- #endif
- #ifndef S_ISCHR
-   #define S_ISCHR(mode)  (mode&_S_IFCHR)
- #endif
- #ifndef S_ISBLK
-   #define S_ISBLK(mode)  (0)
- #endif
-#endif
-/*
-** Convert the inode protection mode to a string.
-*/
-#ifdef _WIN32
-static const char *mode2string (unsigned short mode) {
-#else
-static const char *mode2string (mode_t mode) {
-#endif
-  if ( S_ISREG(mode) )
-    return "file";
-  else if ( S_ISDIR(mode) )
-    return "directory";
-  else if ( S_ISLNK(mode) )
-        return "link";
-  else if ( S_ISSOCK(mode) )
-    return "socket";
-  else if ( S_ISFIFO(mode) )
-        return "named pipe";
-  else if ( S_ISCHR(mode) )
-        return "char device";
-  else if ( S_ISBLK(mode) )
-        return "block device";
-  else
-        return "other";
-}
-
-
-/*
-** Set access time and modification values for file
-*/
-static int file_utime (lua_State *L) {
-        const char *file = luaL_checkstring (L, 1);
-        struct utimbuf utb, *buf;
-
-        if (lua_gettop (L) == 1) /* set to current date/time */
-                buf = NULL;
-        else {
-                utb.actime = (time_t)luaL_optnumber (L, 2, 0);
-                utb.modtime = (time_t)luaL_optnumber (L, 3, utb.actime);
-                buf = &utb;
-        }
-        if (utime (file, buf)) {
-                lua_pushnil (L);
-                lua_pushfstring (L, "%s", strerror (errno));
-                return 2;
-        }
-        lua_pushboolean (L, 1);
-        return 1;
-}
-
-
-/* inode protection mode */
-static void push_st_mode (lua_State *L, STAT_STRUCT *info) {
-        lua_pushstring (L, mode2string (info->st_mode));
-}
-/* device inode resides on */
-static void push_st_dev (lua_State *L, STAT_STRUCT *info) {
-        lua_pushnumber (L, (lua_Number)info->st_dev);
-}
-/* inode's number */
-static void push_st_ino (lua_State *L, STAT_STRUCT *info) {
-        lua_pushnumber (L, (lua_Number)info->st_ino);
-}
-/* number of hard links to the file */
-static void push_st_nlink (lua_State *L, STAT_STRUCT *info) {
-        lua_pushnumber (L, (lua_Number)info->st_nlink);
-}
-/* user-id of owner */
-static void push_st_uid (lua_State *L, STAT_STRUCT *info) {
-        lua_pushnumber (L, (lua_Number)info->st_uid);
-}
-/* group-id of owner */
-static void push_st_gid (lua_State *L, STAT_STRUCT *info) {
-        lua_pushnumber (L, (lua_Number)info->st_gid);
-}
-/* device type, for special file inode */
-static void push_st_rdev (lua_State *L, STAT_STRUCT *info) {
-        lua_pushnumber (L, (lua_Number)info->st_rdev);
-}
-/* time of last access */
-static void push_st_atime (lua_State *L, STAT_STRUCT *info) {
-        lua_pushnumber (L, info->st_atime);
-}
-/* time of last data modification */
-static void push_st_mtime (lua_State *L, STAT_STRUCT *info) {
-        lua_pushnumber (L, info->st_mtime);
-}
-/* time of last file status change */
-static void push_st_ctime (lua_State *L, STAT_STRUCT *info) {
-        lua_pushnumber (L, info->st_ctime);
-}
-/* file size, in bytes */
-static void push_st_size (lua_State *L, STAT_STRUCT *info) {
-        lua_pushnumber (L, (lua_Number)info->st_size);
-}
-#ifndef _WIN32
-/* blocks allocated for file */
-static void push_st_blocks (lua_State *L, STAT_STRUCT *info) {
-        lua_pushnumber (L, (lua_Number)info->st_blocks);
-}
-/* optimal file system I/O blocksize */
-static void push_st_blksize (lua_State *L, STAT_STRUCT *info) {
-        lua_pushnumber (L, (lua_Number)info->st_blksize);
-}
-#endif
-static void push_invalid (lua_State *L, STAT_STRUCT *info) {
-  luaL_error(L, "invalid attribute name");
-#ifndef _WIN32
-  info->st_blksize = 0; /* never reached */
-#endif
-}
-
- /*
-** Convert the inode protection mode to a permission list.
-*/
-
-#ifdef _WIN32
-static const char *perm2string (unsigned short mode) {
-  static char perms[10] = "---------\0";
-  int i;
-  for (i=0;i<9;i++) perms[i]='-';
-  if (mode  & _S_IREAD)
-   { perms[0] = 'r'; perms[3] = 'r'; perms[6] = 'r'; }
-  if (mode  & _S_IWRITE)
-   { perms[1] = 'w'; perms[4] = 'w'; perms[7] = 'w'; }
-  if (mode  & _S_IEXEC)
-   { perms[2] = 'x'; perms[5] = 'x'; perms[8] = 'x'; }
-  return perms;
-}
-#else
-static const char *perm2string (mode_t mode) {
-  static char perms[10] = "---------\0";
-  int i;
-  for (i=0;i<9;i++) perms[i]='-';
-  if (mode & S_IRUSR) perms[0] = 'r';
-  if (mode & S_IWUSR) perms[1] = 'w';
-  if (mode & S_IXUSR) perms[2] = 'x';
-  if (mode & S_IRGRP) perms[3] = 'r';
-  if (mode & S_IWGRP) perms[4] = 'w';
-  if (mode & S_IXGRP) perms[5] = 'x';
-  if (mode & S_IROTH) perms[6] = 'r';
-  if (mode & S_IWOTH) perms[7] = 'w';
-  if (mode & S_IXOTH) perms[8] = 'x';
-  return perms;
-}
-#endif
-
-/* permssions string */
-static void push_st_perm (lua_State *L, STAT_STRUCT *info) {
-    lua_pushstring (L, perm2string (info->st_mode));
-}
-
-typedef void (*_push_function) (lua_State *L, STAT_STRUCT *info);
-
-struct _stat_members {
-        const char *name;
-        _push_function push;
-};
-
-struct _stat_members members[] = {
-        { "mode",         push_st_mode },
-        { "dev",          push_st_dev },
-        { "ino",          push_st_ino },
-        { "nlink",        push_st_nlink },
-        { "uid",          push_st_uid },
-        { "gid",          push_st_gid },
-        { "rdev",         push_st_rdev },
-        { "access",       push_st_atime },
-        { "modification", push_st_mtime },
-        { "change",       push_st_ctime },
-        { "size",         push_st_size },
-        { "permissions",  push_st_perm },
-#ifndef _WIN32
-        { "blocks",       push_st_blocks },
-        { "blksize",      push_st_blksize },
-#endif
-        { NULL, push_invalid }
-};
-
-/*
-** Get file or symbolic link information
-*/
-static int _file_info_ (lua_State *L, int (*st)(const char*, STAT_STRUCT*)) {
-        int i;
-        STAT_STRUCT info;
-        const char *file = luaL_checkstring (L, 1);
-
-        if (st(file, &info)) {
-                lua_pushnil (L);
-                lua_pushfstring (L, "cannot obtain information from file `%s'", file);
-                return 2;
-        }
-        if (lua_isstring (L, 2)) {
-                int v;
-                const char *member = lua_tostring (L, 2);
-                if (strcmp (member, "mode") == 0) v = 0;
-#ifndef _WIN32
-                else if (strcmp (member, "blocks")  == 0) v = 11;
-                else if (strcmp (member, "blksize") == 0) v = 12;
-#endif
-                else /* look for member */
-                        for (v = 1; members[v].name; v++)
-                                if (*members[v].name == *member)
-                                        break;
-                /* push member value and return */
-                members[v].push (L, &info);
-                return 1;
-        } else if (!lua_istable (L, 2))
-                /* creates a table if none is given */
-                lua_newtable (L);
-        /* stores all members in table on top of the stack */
-        for (i = 0; members[i].name; i++) {
-                lua_pushstring (L, members[i].name);
-                members[i].push (L, &info);
-                lua_rawset (L, -3);
-        }
-        return 1;
-}
-
-
-/*
-** Get file information using stat.
-*/
-static int file_info (lua_State *L) {
-        return _file_info_ (L, STAT_FUNC);
-}
-
-
-/*
-** Get symbolic link information using lstat.
-*/
-static int link_info (lua_State *L) {
-        return _file_info_ (L, LSTAT_FUNC);
-}
-
-
-/*
-** Assumes the table is on top of the stack.
-*/
-static void set_info (lua_State *L) {
-        lua_pushliteral (L, "_COPYRIGHT");
-        lua_pushliteral (L, "Copyright (C) 2003-2012 Kepler Project");
-        lua_settable (L, -3);
-        lua_pushliteral (L, "_DESCRIPTION");
-        lua_pushliteral (L, "LuaFileSystem is a Lua library developed to complement the set of functions related to file systems offered by the standard Lua distribution");
-        lua_settable (L, -3);
-        lua_pushliteral (L, "_VERSION");
-        lua_pushliteral (L, "LuaFileSystem "LFS_VERSION);
-        lua_settable (L, -3);
-}
-
-
-static const struct luaL_Reg fslib[] = {
-        {"attributes", file_info},
-        {"chdir", change_dir},
-        {"currentdir", get_dir},
-        {"dir", dir_iter_factory},
-        {"link", make_link},
-        {"lock", file_lock},
-        {"mkdir", make_dir},
-        {"rmdir", remove_dir},
-        {"symlinkattributes", link_info},
-        {"setmode", lfs_f_setmode},
-        {"touch", file_utime},
-        {"unlock", file_unlock},
-        {"lock_dir", lfs_lock_dir},
-        {NULL, NULL},
-};
-
-int luaopen_lfs (lua_State *L) {
-        dir_create_meta (L);
-        lock_create_meta (L);
-        luaL_newlib (L, fslib);
-        lua_pushvalue(L, -1);
-        lua_setglobal(L, LFS_LIBNAME);
-        set_info (L);
-        return 1;
-}
+/*
+** LuaFileSystem
+** Copyright Kepler Project 2003 (http://www.keplerproject.org/luafilesystem)
+**
+** File system manipulation library.
+** This library offers these functions:
+**   lfs.attributes (filepath [, attributename])
+**   lfs.chdir (path)
+**   lfs.currentdir ()
+**   lfs.dir (path)
+**   lfs.lock (fh, mode)
+**   lfs.lock_dir (path)
+**   lfs.mkdir (path)
+**   lfs.rmdir (path)
+**   lfs.setmode (filepath, mode)
+**   lfs.symlinkattributes (filepath [, attributename]) -- thanks to Sam Roberts
+**   lfs.touch (filepath [, atime [, mtime]])
+**   lfs.unlock (fh)
+**
+** $Id: lfs.c,v 1.61 2009/07/04 02:10:16 mascarenhas Exp $
+*/
+
+#ifdef _MSC_VER
+#ifndef _CRT_SECURE_NO_WARNINGS
+#define _CRT_SECURE_NO_WARNINGS /* disable Visual Studio compiler warnings for using standard C functions */
+#endif
+#endif
+
+#ifndef _WIN32
+#ifndef _AIX
+#define _FILE_OFFSET_BITS 64 /* Linux, Solaris and HP-UX */
+#else
+#define _LARGE_FILES 1 /* AIX */
+#endif
+#endif
+
+#define _LARGEFILE64_SOURCE
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+#include <sys/stat.h>
+
+#ifdef _WIN32
+#include <direct.h>
+#include <windows.h>
+#include <io.h>
+#include <sys/locking.h>
+#ifdef __BORLANDC__
+ #include <utime.h>
+#else
+ #include <sys/utime.h>
+#endif
+#include <fcntl.h>
+#else
+#include <unistd.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <utime.h>
+#endif
+
+#include <lua.h>
+#include <lauxlib.h>
+#include <lualib.h>
+
+#include "lfs.h"
+
+#define LFS_VERSION "1.6.2"
+#define LFS_LIBNAME "lfs"
+
+#if LUA_VERSION_NUM < 502
+#  define luaL_newlib(L,l) (lua_newtable(L), luaL_register(L,NULL,l))
+#endif
+
+/* Define 'strerror' for systems that do not implement it */
+#ifdef NO_STRERROR
+#define strerror(_)     "System unable to describe the error"
+#endif
+
+/* Define 'getcwd' for systems that do not implement it */
+#ifdef NO_GETCWD
+#define getcwd(p,s)     NULL
+#define getcwd_error    "Function 'getcwd' not provided by system"
+#else
+#define getcwd_error    strerror(errno)
+  #ifdef _WIN32
+	 /* MAX_PATH seems to be 260. Seems kind of small. Is there a better one? */
+    #define LFS_MAXPATHLEN MAX_PATH
+  #else
+	/* For MAXPATHLEN: */
+    #include <sys/param.h>
+    #define LFS_MAXPATHLEN MAXPATHLEN
+  #endif
+#endif
+
+#define DIR_METATABLE "directory metatable"
+typedef struct dir_data {
+        int  closed;
+#ifdef _WIN32
+        long hFile;
+        char pattern[MAX_PATH+1];
+#else
+        DIR *dir;
+#endif
+} dir_data;
+
+#define LOCK_METATABLE "lock metatable"
+
+#ifdef _WIN32
+ #ifdef __BORLANDC__
+  #define lfs_setmode(L,file,m)   ((void)L, setmode(_fileno(file), m))
+  #define STAT_STRUCT struct stati64
+ #else
+  #define lfs_setmode(L,file,m)   ((void)L, _setmode(_fileno(file), m))
+  #define STAT_STRUCT struct _stati64
+ #endif
+#define STAT_FUNC _stati64
+#define LSTAT_FUNC STAT_FUNC
+#else
+#define _O_TEXT               0
+#define _O_BINARY             0
+#define lfs_setmode(L,file,m)   ((void)L, (void)file, (void)m, 0)
+#define STAT_STRUCT struct stat
+#define STAT_FUNC stat
+#define LSTAT_FUNC lstat
+#endif
+
+/*
+** Utility functions
+*/
+static int pusherror(lua_State *L, const char *info)
+{
+        lua_pushnil(L);
+        if (info==NULL)
+                lua_pushstring(L, strerror(errno));
+        else
+                lua_pushfstring(L, "%s: %s", info, strerror(errno));
+        lua_pushinteger(L, errno);
+        return 3;
+}
+
+static int pushresult(lua_State *L, int i, const char *info)
+{
+        if (i==-1)
+                return pusherror(L, info);
+        lua_pushinteger(L, i);
+        return 1;
+}
+
+
+/*
+** This function changes the working (current) directory
+*/
+static int change_dir (lua_State *L) {
+        const char *path = luaL_checkstring(L, 1);
+        if (chdir(path)) {
+                lua_pushnil (L);
+                lua_pushfstring (L,"Unable to change working directory to '%s'\n%s\n",
+                                path, chdir_error);
+                return 2;
+        } else {
+                lua_pushboolean (L, 1);
+                return 1;
+        }
+}
+
+/*
+** This function returns the current directory
+** If unable to get the current directory, it returns nil
+**  and a string describing the error
+*/
+static int get_dir (lua_State *L) {
+  char *path;
+  /* Passing (NULL, 0) is not guaranteed to work. Use a temp buffer and size instead. */
+  char buf[LFS_MAXPATHLEN];
+  if ((path = getcwd(buf, LFS_MAXPATHLEN)) == NULL) {
+    lua_pushnil(L);
+    lua_pushstring(L, getcwd_error);
+    return 2;
+  }
+  else {
+    lua_pushstring(L, path);
+    return 1;
+  }
+}
+
+/*
+** Check if the given element on the stack is a file and returns it.
+*/
+static FILE *check_file (lua_State *L, int idx, const char *funcname) {
+        FILE **fh = (FILE **)luaL_checkudata (L, idx, "FILE*");
+        if (fh == NULL) {
+                luaL_error (L, "%s: not a file", funcname);
+                return 0;
+        } else if (*fh == NULL) {
+                luaL_error (L, "%s: closed file", funcname);
+                return 0;
+        } else
+                return *fh;
+}
+
+
+/*
+**
+*/
+static int _file_lock (lua_State *L, FILE *fh, const char *mode, const long start, long len, const char *funcname) {
+        int code;
+#ifdef _WIN32
+        /* lkmode valid values are:
+           LK_LOCK    Locks the specified bytes. If the bytes cannot be locked, the program immediately tries again after 1 second. If, after 10 attempts, the bytes cannot be locked, the constant returns an error.
+           LK_NBLCK   Locks the specified bytes. If the bytes cannot be locked, the constant returns an error.
+           LK_NBRLCK  Same as _LK_NBLCK.
+           LK_RLCK    Same as _LK_LOCK.
+           LK_UNLCK   Unlocks the specified bytes, which must have been previously locked.
+
+           Regions should be locked only briefly and should be unlocked before closing a file or exiting the program.
+
+           http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt__locking.asp
+        */
+        int lkmode;
+        switch (*mode) {
+                case 'r': lkmode = LK_NBLCK; break;
+                case 'w': lkmode = LK_NBLCK; break;
+                case 'u': lkmode = LK_UNLCK; break;
+                default : return luaL_error (L, "%s: invalid mode", funcname);
+        }
+        if (!len) {
+                fseek (fh, 0L, SEEK_END);
+                len = ftell (fh);
+        }
+        fseek (fh, start, SEEK_SET);
+#ifdef __BORLANDC__
+        code = locking (fileno(fh), lkmode, len);
+#else
+        code = _locking (fileno(fh), lkmode, len);
+#endif
+#else
+        struct flock f;
+        switch (*mode) {
+                case 'w': f.l_type = F_WRLCK; break;
+                case 'r': f.l_type = F_RDLCK; break;
+                case 'u': f.l_type = F_UNLCK; break;
+                default : return luaL_error (L, "%s: invalid mode", funcname);
+        }
+        f.l_whence = SEEK_SET;
+        f.l_start = (off_t)start;
+        f.l_len = (off_t)len;
+        code = fcntl (fileno(fh), F_SETLK, &f);
+#endif
+        return (code != -1);
+}
+
+#ifdef _WIN32
+typedef struct lfs_Lock {
+  HANDLE fd;
+} lfs_Lock;
+static int lfs_lock_dir(lua_State *L) {
+  size_t pathl; HANDLE fd;
+  lfs_Lock *lock;
+  char *ln;
+  const char *lockfile = "/lockfile.lfs";
+  const char *path = luaL_checklstring(L, 1, &pathl);
+  ln = (char*)malloc(pathl + strlen(lockfile) + 1);
+  if(!ln) {
+    lua_pushnil(L); lua_pushstring(L, strerror(errno)); return 2;
+  }
+  strcpy(ln, path); strcat(ln, lockfile);
+  /* Use "CreateFileA" to use the Multi-Byte-Character version, even if the rest of the project uses the Unicode (UTF16) version */
+  if((fd = CreateFileA(ln, GENERIC_WRITE, 0, NULL, CREATE_NEW,
+                FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL)) == INVALID_HANDLE_VALUE) {
+        int en = GetLastError();
+        free(ln); lua_pushnil(L);
+        if(en == ERROR_FILE_EXISTS || en == ERROR_SHARING_VIOLATION)
+                lua_pushstring(L, "File exists");
+        else
+                lua_pushstring(L, strerror(en));
+        return 2;
+  }
+  free(ln);
+  lock = (lfs_Lock*)lua_newuserdata(L, sizeof(lfs_Lock));
+  lock->fd = fd;
+  luaL_getmetatable (L, LOCK_METATABLE);
+  lua_setmetatable (L, -2);
+  return 1;
+}
+static int lfs_unlock_dir(lua_State *L) {
+  lfs_Lock *lock = luaL_checkudata(L, 1, LOCK_METATABLE);
+  CloseHandle(lock->fd);
+  return 0;
+}
+#else
+typedef struct lfs_Lock {
+  char *ln;
+} lfs_Lock;
+static int lfs_lock_dir(lua_State *L) {
+  lfs_Lock *lock;
+  size_t pathl;
+  char *ln;
+  const char *lockfile = "/lockfile.lfs";
+  const char *path = luaL_checklstring(L, 1, &pathl);
+  lock = (lfs_Lock*)lua_newuserdata(L, sizeof(lfs_Lock));
+  ln = (char*)malloc(pathl + strlen(lockfile) + 1);
+  if(!ln) {
+    lua_pushnil(L); lua_pushstring(L, strerror(errno)); return 2;
+  }
+  strcpy(ln, path); strcat(ln, lockfile);
+  if(symlink("lock", ln) == -1) {
+    free(ln); lua_pushnil(L);
+    lua_pushstring(L, strerror(errno)); return 2;
+  }
+  lock->ln = ln;
+  luaL_getmetatable (L, LOCK_METATABLE);
+  lua_setmetatable (L, -2);
+  return 1;
+}
+static int lfs_unlock_dir(lua_State *L) {
+  lfs_Lock *lock = luaL_checkudata(L, 1, LOCK_METATABLE);
+  if(lock->ln) {
+    unlink(lock->ln);
+    free(lock->ln);
+    lock->ln = NULL;
+  }
+  return 0;
+}
+#endif
+
+static int lfs_g_setmode (lua_State *L, FILE *f, int arg) {
+  static const int mode[] = {_O_BINARY, _O_TEXT};
+  static const char *const modenames[] = {"binary", "text", NULL};
+  int op = luaL_checkoption(L, arg, NULL, modenames);
+  int res = lfs_setmode(L, f, mode[op]);
+  if (res != -1) {
+    int i;
+    lua_pushboolean(L, 1);
+    for (i = 0; modenames[i] != NULL; i++) {
+      if (mode[i] == res) {
+        lua_pushstring(L, modenames[i]);
+        goto exit;
+      }
+    }
+    lua_pushnil(L);
+  exit:
+    return 2;
+  } else {
+    int en = errno;
+    lua_pushnil(L);
+    lua_pushfstring(L, "%s", strerror(en));
+    lua_pushinteger(L, en);
+    return 3;
+  }
+}
+
+static int lfs_f_setmode(lua_State *L) {
+  return lfs_g_setmode(L, check_file(L, 1, "setmode"), 2);
+}
+
+/*
+** Locks a file.
+** @param #1 File handle.
+** @param #2 String with lock mode ('w'rite, 'r'ead).
+** @param #3 Number with start position (optional).
+** @param #4 Number with length (optional).
+*/
+static int file_lock (lua_State *L) {
+        FILE *fh = check_file (L, 1, "lock");
+        const char *mode = luaL_checkstring (L, 2);
+        const long start = luaL_optlong (L, 3, 0);
+        long len = luaL_optlong (L, 4, 0);
+        if (_file_lock (L, fh, mode, start, len, "lock")) {
+                lua_pushboolean (L, 1);
+                return 1;
+        } else {
+                lua_pushnil (L);
+                lua_pushfstring (L, "%s", strerror(errno));
+                return 2;
+        }
+}
+
+
+/*
+** Unlocks a file.
+** @param #1 File handle.
+** @param #2 Number with start position (optional).
+** @param #3 Number with length (optional).
+*/
+static int file_unlock (lua_State *L) {
+        FILE *fh = check_file (L, 1, "unlock");
+        const long start = luaL_optlong (L, 2, 0);
+        long len = luaL_optlong (L, 3, 0);
+        if (_file_lock (L, fh, "u", start, len, "unlock")) {
+                lua_pushboolean (L, 1);
+                return 1;
+        } else {
+                lua_pushnil (L);
+                lua_pushfstring (L, "%s", strerror(errno));
+                return 2;
+        }
+}
+
+
+/*
+** Creates a link.
+** @param #1 Object to link to.
+** @param #2 Name of link.
+** @param #3 True if link is symbolic (optional).
+*/
+static int make_link(lua_State *L)
+{
+#ifndef _WIN32
+        const char *oldpath = luaL_checkstring(L, 1);
+        const char *newpath = luaL_checkstring(L, 2);
+        return pushresult(L,
+                (lua_toboolean(L,3) ? symlink : link)(oldpath, newpath), NULL);
+#else
+        return pusherror(L, "make_link is not supported on Windows");
+#endif
+}
+
+
+/*
+** Creates a directory.
+** @param #1 Directory path.
+*/
+static int make_dir (lua_State *L) {
+        const char *path = luaL_checkstring (L, 1);
+        int fail;
+#ifdef _WIN32
+        fail = _mkdir (path);
+#else
+        fail =  mkdir (path, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP |
+                             S_IWGRP | S_IXGRP | S_IROTH | S_IXOTH );
+#endif
+        if (fail) {
+                lua_pushnil (L);
+        lua_pushfstring (L, "%s", strerror(errno));
+                return 2;
+        }
+        lua_pushboolean (L, 1);
+        return 1;
+}
+
+/*
+** Removes a directory.
+** @param #1 Directory path.
+*/
+static int remove_dir (lua_State *L) {
+        const char *path = luaL_checkstring (L, 1);
+        int fail;
+
+        fail = rmdir (path);
+
+        if (fail) {
+                lua_pushnil (L);
+                lua_pushfstring (L, "%s", strerror(errno));
+                return 2;
+        }
+        lua_pushboolean (L, 1);
+        return 1;
+}
+
+/*
+** Directory iterator
+*/
+static int dir_iter (lua_State *L) {
+#ifdef _WIN32
+        struct _finddata_t c_file;
+#else
+        struct dirent *entry;
+#endif
+        dir_data *d = (dir_data *)luaL_checkudata (L, 1, DIR_METATABLE);
+        luaL_argcheck (L, d->closed == 0, 1, "closed directory");
+#ifdef _WIN32
+        if (d->hFile == 0L) { /* first entry */
+                if ((d->hFile = _findfirst (d->pattern, &c_file)) == -1L) {
+                        lua_pushnil (L);
+                        lua_pushstring (L, strerror (errno));
+                        d->closed = 1;
+                        return 2;
+                } else {
+                        lua_pushstring (L, c_file.name);
+                        return 1;
+                }
+        } else { /* next entry */
+                if (_findnext (d->hFile, &c_file) == -1L) {
+                        /* no more entries => close directory */
+                        _findclose (d->hFile);
+                        d->closed = 1;
+                        return 0;
+                } else {
+                        lua_pushstring (L, c_file.name);
+                        return 1;
+                }
+        }
+#else
+        if ((entry = readdir (d->dir)) != NULL) {
+                lua_pushstring (L, entry->d_name);
+                return 1;
+        } else {
+                /* no more entries => close directory */
+                closedir (d->dir);
+                d->closed = 1;
+                return 0;
+        }
+#endif
+}
+
+
+/*
+** Closes directory iterators
+*/
+static int dir_close (lua_State *L) {
+        dir_data *d = (dir_data *)lua_touserdata (L, 1);
+#ifdef _WIN32
+        if (!d->closed && d->hFile) {
+                _findclose (d->hFile);
+        }
+#else
+        if (!d->closed && d->dir) {
+                closedir (d->dir);
+        }
+#endif
+        d->closed = 1;
+        return 0;
+}
+
+
+/*
+** Factory of directory iterators
+*/
+static int dir_iter_factory (lua_State *L) {
+        const char *path = luaL_checkstring (L, 1);
+        dir_data *d;
+        lua_pushcfunction (L, dir_iter);
+        d = (dir_data *) lua_newuserdata (L, sizeof(dir_data));
+        luaL_getmetatable (L, DIR_METATABLE);
+        lua_setmetatable (L, -2);
+        d->closed = 0;
+#ifdef _WIN32
+        d->hFile = 0L;
+        if (strlen(path) > MAX_PATH-2)
+          luaL_error (L, "path too long: %s", path);
+        else
+          sprintf (d->pattern, "%s/*", path);
+#else
+        d->dir = opendir (path);
+        if (d->dir == NULL)
+          luaL_error (L, "cannot open %s: %s", path, strerror (errno));
+#endif
+        return 2;
+}
+
+
+/*
+** Creates directory metatable.
+*/
+static int dir_create_meta (lua_State *L) {
+        luaL_newmetatable (L, DIR_METATABLE);
+
+        /* Method table */
+        lua_newtable(L);
+        lua_pushcfunction (L, dir_iter);
+        lua_setfield(L, -2, "next");
+        lua_pushcfunction (L, dir_close);
+        lua_setfield(L, -2, "close");
+
+        /* Metamethods */
+        lua_setfield(L, -2, "__index");
+        lua_pushcfunction (L, dir_close);
+        lua_setfield (L, -2, "__gc");
+        return 1;
+}
+
+/*
+** Creates lock metatable.
+*/
+static int lock_create_meta (lua_State *L) {
+        luaL_newmetatable (L, LOCK_METATABLE);
+
+        /* Method table */
+        lua_newtable(L);
+        lua_pushcfunction(L, lfs_unlock_dir);
+        lua_setfield(L, -2, "free");
+
+        /* Metamethods */
+        lua_setfield(L, -2, "__index");
+        lua_pushcfunction(L, lfs_unlock_dir);
+        lua_setfield(L, -2, "__gc");
+        return 1;
+}
+
+
+#ifdef _WIN32
+ #ifndef S_ISDIR
+   #define S_ISDIR(mode)  (mode&_S_IFDIR)
+ #endif
+ #ifndef S_ISREG
+   #define S_ISREG(mode)  (mode&_S_IFREG)
+ #endif
+ #ifndef S_ISLNK
+   #define S_ISLNK(mode)  (0)
+ #endif
+ #ifndef S_ISSOCK
+   #define S_ISSOCK(mode)  (0)
+ #endif
+ #ifndef S_ISFIFO
+   #define S_ISFIFO(mode)  (0)
+ #endif
+ #ifndef S_ISCHR
+   #define S_ISCHR(mode)  (mode&_S_IFCHR)
+ #endif
+ #ifndef S_ISBLK
+   #define S_ISBLK(mode)  (0)
+ #endif
+#endif
+/*
+** Convert the inode protection mode to a string.
+*/
+#ifdef _WIN32
+static const char *mode2string (unsigned short mode) {
+#else
+static const char *mode2string (mode_t mode) {
+#endif
+  if ( S_ISREG(mode) )
+    return "file";
+  else if ( S_ISDIR(mode) )
+    return "directory";
+  else if ( S_ISLNK(mode) )
+        return "link";
+  else if ( S_ISSOCK(mode) )
+    return "socket";
+  else if ( S_ISFIFO(mode) )
+        return "named pipe";
+  else if ( S_ISCHR(mode) )
+        return "char device";
+  else if ( S_ISBLK(mode) )
+        return "block device";
+  else
+        return "other";
+}
+
+
+/*
+** Set access time and modification values for file
+*/
+static int file_utime (lua_State *L) {
+        const char *file = luaL_checkstring (L, 1);
+        struct utimbuf utb, *buf;
+
+        if (lua_gettop (L) == 1) /* set to current date/time */
+                buf = NULL;
+        else {
+                utb.actime = (time_t)luaL_optnumber (L, 2, 0);
+                utb.modtime = (time_t)luaL_optnumber (L, 3, utb.actime);
+                buf = &utb;
+        }
+        if (utime (file, buf)) {
+                lua_pushnil (L);
+                lua_pushfstring (L, "%s", strerror (errno));
+                return 2;
+        }
+        lua_pushboolean (L, 1);
+        return 1;
+}
+
+
+/* inode protection mode */
+static void push_st_mode (lua_State *L, STAT_STRUCT *info) {
+        lua_pushstring (L, mode2string (info->st_mode));
+}
+/* device inode resides on */
+static void push_st_dev (lua_State *L, STAT_STRUCT *info) {
+        lua_pushnumber (L, (lua_Number)info->st_dev);
+}
+/* inode's number */
+static void push_st_ino (lua_State *L, STAT_STRUCT *info) {
+        lua_pushnumber (L, (lua_Number)info->st_ino);
+}
+/* number of hard links to the file */
+static void push_st_nlink (lua_State *L, STAT_STRUCT *info) {
+        lua_pushnumber (L, (lua_Number)info->st_nlink);
+}
+/* user-id of owner */
+static void push_st_uid (lua_State *L, STAT_STRUCT *info) {
+        lua_pushnumber (L, (lua_Number)info->st_uid);
+}
+/* group-id of owner */
+static void push_st_gid (lua_State *L, STAT_STRUCT *info) {
+        lua_pushnumber (L, (lua_Number)info->st_gid);
+}
+/* device type, for special file inode */
+static void push_st_rdev (lua_State *L, STAT_STRUCT *info) {
+        lua_pushnumber (L, (lua_Number)info->st_rdev);
+}
+/* time of last access */
+static void push_st_atime (lua_State *L, STAT_STRUCT *info) {
+        lua_pushnumber (L, info->st_atime);
+}
+/* time of last data modification */
+static void push_st_mtime (lua_State *L, STAT_STRUCT *info) {
+        lua_pushnumber (L, info->st_mtime);
+}
+/* time of last file status change */
+static void push_st_ctime (lua_State *L, STAT_STRUCT *info) {
+        lua_pushnumber (L, info->st_ctime);
+}
+/* file size, in bytes */
+static void push_st_size (lua_State *L, STAT_STRUCT *info) {
+        lua_pushnumber (L, (lua_Number)info->st_size);
+}
+#ifndef _WIN32
+/* blocks allocated for file */
+static void push_st_blocks (lua_State *L, STAT_STRUCT *info) {
+        lua_pushnumber (L, (lua_Number)info->st_blocks);
+}
+/* optimal file system I/O blocksize */
+static void push_st_blksize (lua_State *L, STAT_STRUCT *info) {
+        lua_pushnumber (L, (lua_Number)info->st_blksize);
+}
+#endif
+static void push_invalid (lua_State *L, STAT_STRUCT *info) {
+  luaL_error(L, "invalid attribute name");
+#ifndef _WIN32
+  info->st_blksize = 0; /* never reached */
+#endif
+}
+
+ /*
+** Convert the inode protection mode to a permission list.
+*/
+
+#ifdef _WIN32
+static const char *perm2string (unsigned short mode) {
+  static char perms[10] = "---------\0";
+  int i;
+  for (i=0;i<9;i++) perms[i]='-';
+  if (mode  & _S_IREAD)
+   { perms[0] = 'r'; perms[3] = 'r'; perms[6] = 'r'; }
+  if (mode  & _S_IWRITE)
+   { perms[1] = 'w'; perms[4] = 'w'; perms[7] = 'w'; }
+  if (mode  & _S_IEXEC)
+   { perms[2] = 'x'; perms[5] = 'x'; perms[8] = 'x'; }
+  return perms;
+}
+#else
+static const char *perm2string (mode_t mode) {
+  static char perms[10] = "---------\0";
+  int i;
+  for (i=0;i<9;i++) perms[i]='-';
+  if (mode & S_IRUSR) perms[0] = 'r';
+  if (mode & S_IWUSR) perms[1] = 'w';
+  if (mode & S_IXUSR) perms[2] = 'x';
+  if (mode & S_IRGRP) perms[3] = 'r';
+  if (mode & S_IWGRP) perms[4] = 'w';
+  if (mode & S_IXGRP) perms[5] = 'x';
+  if (mode & S_IROTH) perms[6] = 'r';
+  if (mode & S_IWOTH) perms[7] = 'w';
+  if (mode & S_IXOTH) perms[8] = 'x';
+  return perms;
+}
+#endif
+
+/* permssions string */
+static void push_st_perm (lua_State *L, STAT_STRUCT *info) {
+    lua_pushstring (L, perm2string (info->st_mode));
+}
+
+typedef void (*_push_function) (lua_State *L, STAT_STRUCT *info);
+
+struct _stat_members {
+        const char *name;
+        _push_function push;
+};
+
+struct _stat_members members[] = {
+        { "mode",         push_st_mode },
+        { "dev",          push_st_dev },
+        { "ino",          push_st_ino },
+        { "nlink",        push_st_nlink },
+        { "uid",          push_st_uid },
+        { "gid",          push_st_gid },
+        { "rdev",         push_st_rdev },
+        { "access",       push_st_atime },
+        { "modification", push_st_mtime },
+        { "change",       push_st_ctime },
+        { "size",         push_st_size },
+        { "permissions",  push_st_perm },
+#ifndef _WIN32
+        { "blocks",       push_st_blocks },
+        { "blksize",      push_st_blksize },
+#endif
+        { NULL, push_invalid }
+};
+
+/*
+** Get file or symbolic link information
+*/
+static int _file_info_ (lua_State *L, int (*st)(const char*, STAT_STRUCT*)) {
+        int i;
+        STAT_STRUCT info;
+        const char *file = luaL_checkstring (L, 1);
+
+        if (st(file, &info)) {
+                lua_pushnil (L);
+                lua_pushfstring (L, "cannot obtain information from file `%s'", file);
+                return 2;
+        }
+        if (lua_isstring (L, 2)) {
+                int v;
+                const char *member = lua_tostring (L, 2);
+                if (strcmp (member, "mode") == 0) v = 0;
+#ifndef _WIN32
+                else if (strcmp (member, "blocks")  == 0) v = 11;
+                else if (strcmp (member, "blksize") == 0) v = 12;
+#endif
+                else /* look for member */
+                        for (v = 1; members[v].name; v++)
+                                if (*members[v].name == *member)
+                                        break;
+                /* push member value and return */
+                members[v].push (L, &info);
+                return 1;
+        } else if (!lua_istable (L, 2))
+                /* creates a table if none is given */
+                lua_newtable (L);
+        /* stores all members in table on top of the stack */
+        for (i = 0; members[i].name; i++) {
+                lua_pushstring (L, members[i].name);
+                members[i].push (L, &info);
+                lua_rawset (L, -3);
+        }
+        return 1;
+}
+
+
+/*
+** Get file information using stat.
+*/
+static int file_info (lua_State *L) {
+        return _file_info_ (L, STAT_FUNC);
+}
+
+
+/*
+** Get symbolic link information using lstat.
+*/
+static int link_info (lua_State *L) {
+        return _file_info_ (L, LSTAT_FUNC);
+}
+
+
+/*
+** Assumes the table is on top of the stack.
+*/
+static void set_info (lua_State *L) {
+        lua_pushliteral (L, "_COPYRIGHT");
+        lua_pushliteral (L, "Copyright (C) 2003-2012 Kepler Project");
+        lua_settable (L, -3);
+        lua_pushliteral (L, "_DESCRIPTION");
+        lua_pushliteral (L, "LuaFileSystem is a Lua library developed to complement the set of functions related to file systems offered by the standard Lua distribution");
+        lua_settable (L, -3);
+        lua_pushliteral (L, "_VERSION");
+        lua_pushliteral (L, "LuaFileSystem "LFS_VERSION);
+        lua_settable (L, -3);
+}
+
+
+static const struct luaL_Reg fslib[] = {
+        {"attributes", file_info},
+        {"chdir", change_dir},
+        {"currentdir", get_dir},
+        {"dir", dir_iter_factory},
+        {"link", make_link},
+        {"lock", file_lock},
+        {"mkdir", make_dir},
+        {"rmdir", remove_dir},
+        {"symlinkattributes", link_info},
+        {"setmode", lfs_f_setmode},
+        {"touch", file_utime},
+        {"unlock", file_unlock},
+        {"lock_dir", lfs_lock_dir},
+        {NULL, NULL},
+};
+
+int luaopen_lfs (lua_State *L) {
+        dir_create_meta (L);
+        lock_create_meta (L);
+        luaL_newlib (L, fslib);
+        lua_pushvalue(L, -1);
+        lua_setglobal(L, LFS_LIBNAME);
+        set_info (L);
+        return 1;
+}

+ 17 - 17
src/third_party/lfs.h

@@ -1,17 +1,17 @@
-/*
-** LuaFileSystem
-** Copyright Kepler Project 2003 (http://www.keplerproject.org/luafilesystem)
-**
-** $Id: lfs.h,v 1.5 2008/02/19 20:08:23 mascarenhas Exp $
-*/
-
-/* Define 'chdir' for systems that do not implement it */
-#ifdef NO_CHDIR
-#define chdir(p)	(-1)
-#define chdir_error	"Function 'chdir' not provided by system"
-#else
-#define chdir_error	strerror(errno)
-#endif
-
-
-int luaopen_lfs (lua_State *L);
+/*
+** LuaFileSystem
+** Copyright Kepler Project 2003 (http://www.keplerproject.org/luafilesystem)
+**
+** $Id: lfs.h,v 1.5 2008/02/19 20:08:23 mascarenhas Exp $
+*/
+
+/* Define 'chdir' for systems that do not implement it */
+#ifdef NO_CHDIR
+#define chdir(p)	(-1)
+#define chdir_error	"Function 'chdir' not provided by system"
+#else
+#define chdir_error	strerror(errno)
+#endif
+
+
+int luaopen_lfs (lua_State *L);

+ 182 - 182
test/embed.c

@@ -1,182 +1,182 @@
-// Copyright (c) 2004-2009 Sergey Lyubka
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//
-// Unit test for the civetweb web server. Tests embedded API.
-
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#ifndef _WIN32
-#include <unistd.h>
-#endif
-
-#include "civetweb.h"
-
-#if !defined(LISTENING_PORT)
-#define LISTENING_PORT "23456"
-#endif
-
-static const char *standard_reply = "HTTP/1.1 200 OK\r\n"
-  "Content-Type: text/plain\r\n"
-  "Connection: close\r\n\r\n";
-
-static void test_get_var(struct mg_connection *conn,
-                         const struct mg_request_info *ri) {
-  char *var, *buf;
-  size_t buf_len;
-  const char *cl;
-  int var_len;
-
-  mg_printf(conn, "%s", standard_reply);
-
-  buf_len = 0;
-  var = buf = NULL;
-  cl = mg_get_header(conn, "Content-Length");
-  mg_printf(conn, "cl: %p\n", cl);
-  if ((!strcmp(ri->request_method, "POST") ||
-       !strcmp(ri->request_method, "PUT"))
-      && cl != NULL) {
-    buf_len = atoi(cl);
-    buf = malloc(buf_len);
-    /* Read in two pieces, to test continuation */
-    if (buf_len > 2) {
-      mg_read(conn, buf, 2);
-      mg_read(conn, buf + 2, buf_len - 2);
-    } else {
-      mg_read(conn, buf, buf_len);
-    }
-  } else if (ri->query_string != NULL) {
-    buf_len = strlen(ri->query_string);
-    buf = malloc(buf_len + 1);
-    strcpy(buf, ri->query_string);
-  }
-  var = malloc(buf_len + 1);
-  var_len = mg_get_var(buf, buf_len, "my_var", var, buf_len + 1);
-  mg_printf(conn, "Value: [%s]\n", var);
-  mg_printf(conn, "Value size: [%d]\n", var_len);
-  free(buf);
-  free(var);
-}
-
-static void test_get_header(struct mg_connection *conn,
-                            const struct mg_request_info *ri) {
-  const char *value;
-  int i;
-
-  mg_printf(conn, "%s", standard_reply);
-  printf("HTTP headers: %d\n", ri->num_headers);
-  for (i = 0; i < ri->num_headers; i++) {
-    printf("[%s]: [%s]\n", ri->http_headers[i].name, ri->http_headers[i].value);
-  }
-
-  value = mg_get_header(conn, "Host");
-  if (value != NULL) {
-    mg_printf(conn, "Value: [%s]", value);
-  }
-}
-
-static void test_get_request_info(struct mg_connection *conn,
-                                  const struct mg_request_info *ri) {
-  int i;
-
-  mg_printf(conn, "%s", standard_reply);
-
-  mg_printf(conn, "Method: [%s]\n", ri->request_method);
-  mg_printf(conn, "URI: [%s]\n", ri->uri);
-  mg_printf(conn, "HTTP version: [%s]\n", ri->http_version);
-
-  for (i = 0; i < ri->num_headers; i++) {
-    mg_printf(conn, "HTTP header [%s]: [%s]\n",
-              ri->http_headers[i].name,
-              ri->http_headers[i].value);
-  }
-
-  mg_printf(conn, "Query string: [%s]\n",
-            ri->query_string ? ri->query_string: "");
-  mg_printf(conn, "Remote IP: [%lu]\n", ri->remote_ip);
-  mg_printf(conn, "Remote port: [%d]\n", ri->remote_port);
-  mg_printf(conn, "Remote user: [%s]\n",
-            ri->remote_user ? ri->remote_user : "");
-}
-
-static void test_error(struct mg_connection *conn,
-                       const struct mg_request_info *ri) {
-  int status = (int) ri->ev_data;
-  mg_printf(conn, "HTTP/1.1 %d XX\r\n"
-            "Conntection: close\r\n\r\n", status);
-  mg_printf(conn, "Error: [%d]", status);
-}
-
-static void test_post(struct mg_connection *conn,
-                      const struct mg_request_info *ri) {
-  const char *cl;
-  char *buf;
-  int len;
-
-  mg_printf(conn, "%s", standard_reply);
-  if (strcmp(ri->request_method, "POST") == 0 &&
-      (cl = mg_get_header(conn, "Content-Length")) != NULL) {
-    len = atoi(cl);
-    if ((buf = malloc(len)) != NULL) {
-      mg_write(conn, buf, len);
-      free(buf);
-    }
-  }
-}
-
-static const struct test_config {
-  enum mg_event event;
-  const char *uri;
-  void (*func)(struct mg_connection *, const struct mg_request_info *);
-} test_config[] = {
-  {MG_NEW_REQUEST, "/test_get_header", &test_get_header},
-  {MG_NEW_REQUEST, "/test_get_var", &test_get_var},
-  {MG_NEW_REQUEST, "/test_get_request_info", &test_get_request_info},
-  {MG_NEW_REQUEST, "/test_post", &test_post},
-  {MG_HTTP_ERROR, "", &test_error},
-  {0, NULL, NULL}
-};
-
-static void *callback(enum mg_event event,
-                      struct mg_connection *conn) {
-  const struct mg_request_info *request_info = mg_get_request_info(conn);
-  int i;
-
-  for (i = 0; test_config[i].uri != NULL; i++) {
-    if (event == test_config[i].event &&
-        (event == MG_HTTP_ERROR ||
-         !strcmp(request_info->uri, test_config[i].uri))) {
-      test_config[i].func(conn, request_info);
-      return "processed";
-    }
-  }
-
-  return NULL;
-}
-
-int main(void) {
-  struct mg_context *ctx;
-  const char *options[] = {"listening_ports", LISTENING_PORT, NULL};
-
-  ctx = mg_start(callback, NULL, options);
-  pause();
-  return 0;
-}
+// Copyright (c) 2004-2009 Sergey Lyubka
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+// Unit test for the civetweb web server. Tests embedded API.
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+
+#include "civetweb.h"
+
+#if !defined(LISTENING_PORT)
+#define LISTENING_PORT "23456"
+#endif
+
+static const char *standard_reply = "HTTP/1.1 200 OK\r\n"
+  "Content-Type: text/plain\r\n"
+  "Connection: close\r\n\r\n";
+
+static void test_get_var(struct mg_connection *conn,
+                         const struct mg_request_info *ri) {
+  char *var, *buf;
+  size_t buf_len;
+  const char *cl;
+  int var_len;
+
+  mg_printf(conn, "%s", standard_reply);
+
+  buf_len = 0;
+  var = buf = NULL;
+  cl = mg_get_header(conn, "Content-Length");
+  mg_printf(conn, "cl: %p\n", cl);
+  if ((!strcmp(ri->request_method, "POST") ||
+       !strcmp(ri->request_method, "PUT"))
+      && cl != NULL) {
+    buf_len = atoi(cl);
+    buf = malloc(buf_len);
+    /* Read in two pieces, to test continuation */
+    if (buf_len > 2) {
+      mg_read(conn, buf, 2);
+      mg_read(conn, buf + 2, buf_len - 2);
+    } else {
+      mg_read(conn, buf, buf_len);
+    }
+  } else if (ri->query_string != NULL) {
+    buf_len = strlen(ri->query_string);
+    buf = malloc(buf_len + 1);
+    strcpy(buf, ri->query_string);
+  }
+  var = malloc(buf_len + 1);
+  var_len = mg_get_var(buf, buf_len, "my_var", var, buf_len + 1);
+  mg_printf(conn, "Value: [%s]\n", var);
+  mg_printf(conn, "Value size: [%d]\n", var_len);
+  free(buf);
+  free(var);
+}
+
+static void test_get_header(struct mg_connection *conn,
+                            const struct mg_request_info *ri) {
+  const char *value;
+  int i;
+
+  mg_printf(conn, "%s", standard_reply);
+  printf("HTTP headers: %d\n", ri->num_headers);
+  for (i = 0; i < ri->num_headers; i++) {
+    printf("[%s]: [%s]\n", ri->http_headers[i].name, ri->http_headers[i].value);
+  }
+
+  value = mg_get_header(conn, "Host");
+  if (value != NULL) {
+    mg_printf(conn, "Value: [%s]", value);
+  }
+}
+
+static void test_get_request_info(struct mg_connection *conn,
+                                  const struct mg_request_info *ri) {
+  int i;
+
+  mg_printf(conn, "%s", standard_reply);
+
+  mg_printf(conn, "Method: [%s]\n", ri->request_method);
+  mg_printf(conn, "URI: [%s]\n", ri->uri);
+  mg_printf(conn, "HTTP version: [%s]\n", ri->http_version);
+
+  for (i = 0; i < ri->num_headers; i++) {
+    mg_printf(conn, "HTTP header [%s]: [%s]\n",
+              ri->http_headers[i].name,
+              ri->http_headers[i].value);
+  }
+
+  mg_printf(conn, "Query string: [%s]\n",
+            ri->query_string ? ri->query_string: "");
+  mg_printf(conn, "Remote IP: [%lu]\n", ri->remote_ip);
+  mg_printf(conn, "Remote port: [%d]\n", ri->remote_port);
+  mg_printf(conn, "Remote user: [%s]\n",
+            ri->remote_user ? ri->remote_user : "");
+}
+
+static void test_error(struct mg_connection *conn,
+                       const struct mg_request_info *ri) {
+  int status = (int) ri->ev_data;
+  mg_printf(conn, "HTTP/1.1 %d XX\r\n"
+            "Conntection: close\r\n\r\n", status);
+  mg_printf(conn, "Error: [%d]", status);
+}
+
+static void test_post(struct mg_connection *conn,
+                      const struct mg_request_info *ri) {
+  const char *cl;
+  char *buf;
+  int len;
+
+  mg_printf(conn, "%s", standard_reply);
+  if (strcmp(ri->request_method, "POST") == 0 &&
+      (cl = mg_get_header(conn, "Content-Length")) != NULL) {
+    len = atoi(cl);
+    if ((buf = malloc(len)) != NULL) {
+      mg_write(conn, buf, len);
+      free(buf);
+    }
+  }
+}
+
+static const struct test_config {
+  enum mg_event event;
+  const char *uri;
+  void (*func)(struct mg_connection *, const struct mg_request_info *);
+} test_config[] = {
+  {MG_NEW_REQUEST, "/test_get_header", &test_get_header},
+  {MG_NEW_REQUEST, "/test_get_var", &test_get_var},
+  {MG_NEW_REQUEST, "/test_get_request_info", &test_get_request_info},
+  {MG_NEW_REQUEST, "/test_post", &test_post},
+  {MG_HTTP_ERROR, "", &test_error},
+  {0, NULL, NULL}
+};
+
+static void *callback(enum mg_event event,
+                      struct mg_connection *conn) {
+  const struct mg_request_info *request_info = mg_get_request_info(conn);
+  int i;
+
+  for (i = 0; test_config[i].uri != NULL; i++) {
+    if (event == test_config[i].event &&
+        (event == MG_HTTP_ERROR ||
+         !strcmp(request_info->uri, test_config[i].uri))) {
+      test_config[i].func(conn, request_info);
+      return "processed";
+    }
+  }
+
+  return NULL;
+}
+
+int main(void) {
+  struct mg_context *ctx;
+  const char *options[] = {"listening_ports", LISTENING_PORT, NULL};
+
+  ctx = mg_start(callback, NULL, options);
+  pause();
+  return 0;
+}