mirror of
https://codeberg.org/1414codeforge/lua-osx.git
synced 2024-12-12 11:27:03 +01:00
[*] First commit.
This commit is contained in:
parent
d0d88a62a1
commit
7c36f77dfa
57
Makefile
Normal file
57
Makefile
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
# The lua-osx Makefile
|
||||||
|
# Author: Lorenzo Cogotti, The DoubleFourteen Code Forge
|
||||||
|
#
|
||||||
|
# For general configuration see config.mk.
|
||||||
|
# For system specific configuration see other config.*s.
|
||||||
|
#
|
||||||
|
# To pick a specific system configuration use the CONFIG variable
|
||||||
|
# (config.unix by default), e.g.:
|
||||||
|
# make CONFIG=config.macosx
|
||||||
|
#
|
||||||
|
# By default we build against system's lua interpreter,
|
||||||
|
# to build against other implementations use the LUA variable, e.g.:
|
||||||
|
# make LUA=luajit
|
||||||
|
#
|
||||||
|
# To manually specify lua's include path, library path and library name use:
|
||||||
|
# LUA_INCDIR, LUA_LIBDIR and LUALIB variables respectively.
|
||||||
|
# By default these are automatically detected via pkg-config.
|
||||||
|
#
|
||||||
|
# To manually specify the module install path use the LIBDIR variable,
|
||||||
|
# By default it is automatically detected via pkg-config.
|
||||||
|
#
|
||||||
|
# NOTE: there is NO support for the MSVC compiler.
|
||||||
|
|
||||||
|
CONFIG = config.unix
|
||||||
|
|
||||||
|
include config.mk
|
||||||
|
include $(CONFIG)
|
||||||
|
|
||||||
|
lib = osx.$(LIB_EXTENSION)
|
||||||
|
src = osx.c
|
||||||
|
o = $(src:.c=.o)
|
||||||
|
_o = $(_src:.c=.o)
|
||||||
|
|
||||||
|
.c.o:
|
||||||
|
$(CC) -std=c11 $(_cflags) $(CFLAGS) -c $<
|
||||||
|
|
||||||
|
all: $(lib)
|
||||||
|
|
||||||
|
$(_o): $(_src) xconf.h osx_dir.h
|
||||||
|
|
||||||
|
osx.o: osx.c xconf.h luacompat.h osx.h osx_dir.h
|
||||||
|
|
||||||
|
$(lib): $(o) $(_o)
|
||||||
|
$(LD) $(LIBFLAG) -o $@ $(_ldflags) $(LDFLAGS) $(o) $(_o)
|
||||||
|
|
||||||
|
install:
|
||||||
|
-$(MKDIR) $(DESTDIR)$(LIBDIR)/osx $(DESTDIR)$(LIBDIR)/osx/include
|
||||||
|
$(CP) $(lib) $(DESTDIR)$(LIBDIR)/osx/
|
||||||
|
$(CP) osx.h osx_dir.h $(DESTDIR)$(LIBDIR)/osx/include/
|
||||||
|
|
||||||
|
uninstall:
|
||||||
|
-$(RM) $(DESTDIR)$(LIBDIR)/osx/$(lib)
|
||||||
|
-$(RM) $(DESTDIR)$(LIBDIR)/osx/include/osx.h $(DESTDIR)$(LIBDIR)/osx/include/osx_dir.h
|
||||||
|
-$(RMDIR) $(DESTDIR)$(LIBDIR)/osx/include $(DESTDIR)$(LIBDIR)/osx
|
||||||
|
|
||||||
|
clean:
|
||||||
|
-$(RM) $(lib) $(o) $(_o)
|
7
config.macosx
Normal file
7
config.macosx
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# MacOSX configuration
|
||||||
|
LIB_EXTENSION = dylib
|
||||||
|
OBJ_EXTENSION = o
|
||||||
|
LIBFLAG = -bundle -undefined dynamic_lookup -all_load
|
||||||
|
|
||||||
|
_src = dir_unix.c
|
||||||
|
_cflags = -I$(LUA_INCDIR)
|
19
config.mk
Normal file
19
config.mk
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# Compiler and tools
|
||||||
|
CC = cc
|
||||||
|
LD = $(CC)
|
||||||
|
LUA = lua
|
||||||
|
PKGCONFIG = pkg-config
|
||||||
|
CP = cp
|
||||||
|
RM = rm
|
||||||
|
MKDIR = mkdir
|
||||||
|
RMDIR = rmdir
|
||||||
|
|
||||||
|
# Compilation flags
|
||||||
|
CFLAGS = -pipe -Os -fPIC -Wall -pedantic
|
||||||
|
# Linking options
|
||||||
|
LDFLAGS = -W -O1
|
||||||
|
|
||||||
|
# Lua setup
|
||||||
|
LUA_INCDIR = $(shell $(PKGCONFIG) --variable=includedir $(LUA))
|
||||||
|
LUA_LIBDIR = $(shell $(PKGCONFIG) --variable=libdir $(LUA))
|
||||||
|
LIBDIR = $(shell $(PKGCONFIG) --variable=INSTALL_CMOD $(LUA))
|
7
config.unix
Normal file
7
config.unix
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# Generic Unix configuration
|
||||||
|
LIB_EXTENSION = so
|
||||||
|
OBJ_EXTENSION = o
|
||||||
|
LIBFLAG = -shared
|
||||||
|
|
||||||
|
_src = dir_unix.c
|
||||||
|
_cflags = -I$(LUA_INCDIR)
|
9
config.win
Normal file
9
config.win
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# Windows MinGW configuration
|
||||||
|
LIB_EXTENSION = dll
|
||||||
|
OBJ_EXTENSION = o
|
||||||
|
LIBFLAG = -shared
|
||||||
|
LUALIB = lua$(shell $(PKGCONFIG) --variable=V $(LUA)).dll.a
|
||||||
|
|
||||||
|
_src = dir_win32.c
|
||||||
|
_cflags = -I$(LUA_INCDIR) -DDF_LUA_OSXLIB
|
||||||
|
_ldflags = $(LUA_LIBDIR)/$(LUALIB) -lm
|
27
dir_unix.c
Normal file
27
dir_unix.c
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
|
||||||
|
/* Trivial osx_dir.h implementation on Unix.
|
||||||
|
*
|
||||||
|
* Copyright: 2022, The DoubleFourteen Code Forge
|
||||||
|
* Author: Lorenzo Cogotti
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "xconf.h"
|
||||||
|
#include "osx_dir.h"
|
||||||
|
|
||||||
|
DF_OSXLIB_API df_os_dirhn os_opendir(const char *name)
|
||||||
|
{
|
||||||
|
return opendir(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
DF_OSXLIB_API char *os_readdir(df_os_dirhn hn)
|
||||||
|
{
|
||||||
|
struct dirent *ent = readdir(hn);
|
||||||
|
return ent ? ent->d_name : (char *) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DF_OSXLIB_API void os_closedir(df_os_dirhn hn)
|
||||||
|
{
|
||||||
|
(void) closedir(hn);
|
||||||
|
}
|
||||||
|
|
83
dir_win32.c
Normal file
83
dir_win32.c
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
|
||||||
|
/* osx_dir.h implementation for Windows.
|
||||||
|
*
|
||||||
|
* Copyright: 2022, The DoubleFourteen Code Forge
|
||||||
|
* Author: Lorenzo Cogotti
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "xconf.h"
|
||||||
|
#include "osx_dir.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
DF_OSXLIB_API df_os_dirhn os_opendir(const char *path)
|
||||||
|
{
|
||||||
|
if (*path == '\0') { // avoid generating \* search path
|
||||||
|
errno = ENOENT;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char buf[_MAX_PATH + 2 + 1];
|
||||||
|
int n = snprintf(buf, sizeof(buf), "%s\\*", path);
|
||||||
|
if (n < 0)
|
||||||
|
return NULL;
|
||||||
|
if ((size_t) n >= sizeof(buf)) {
|
||||||
|
errno = ERANGE;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
df_os_dirhn hn = malloc(sizeof(*hn));
|
||||||
|
if (!hn)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
hn->dirh = _findfirst(buf, &hn->data);
|
||||||
|
if (hn->dirh == -1) {
|
||||||
|
free(hn);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
hn->startflag = true;
|
||||||
|
hn->errflag = false;
|
||||||
|
hn->endflag = false;
|
||||||
|
|
||||||
|
return hn;
|
||||||
|
}
|
||||||
|
|
||||||
|
DF_OSXLIB_API char *os_readdir(df_os_dirhn hn)
|
||||||
|
{
|
||||||
|
if (hn->startflag) {
|
||||||
|
// Return first item found by _findfirst()
|
||||||
|
hn->startflag = false;
|
||||||
|
return hn->data.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset status flags and advance directory iterator
|
||||||
|
hn->errflag = false;
|
||||||
|
hn->endflag = false;
|
||||||
|
|
||||||
|
int err = errno;
|
||||||
|
|
||||||
|
if (_findnext(hn->dirh, &hn->data) == -1) {
|
||||||
|
if (errno == ENOENT) {
|
||||||
|
// End of directory, this is not an error, restore old errno
|
||||||
|
errno = err;
|
||||||
|
hn->endflag = true;
|
||||||
|
} else {
|
||||||
|
hn->errflag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hn->data.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
DF_OSXLIB_API void os_closedir(df_os_dirhn hn)
|
||||||
|
{
|
||||||
|
_findclose(hn->dirh);
|
||||||
|
free(hn);
|
||||||
|
}
|
51
luacompat.h
Normal file
51
luacompat.h
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
|
||||||
|
/* Compatibility layer with Lua 5.1/LuaJIT.
|
||||||
|
*
|
||||||
|
* Copyright: 2022, The DoubleFourteen Code Forge
|
||||||
|
* Author: Lorenzo Cogotti
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DF_LUA_LUACOMPAT_H_
|
||||||
|
#define DF_LUA_LUACOMPAT_H_
|
||||||
|
|
||||||
|
#include "lua.h"
|
||||||
|
#if LUA_VERSION_NUM < 502
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
FILE *f;
|
||||||
|
} luaL_Stream;
|
||||||
|
|
||||||
|
#define luaL_pushfail(L) lua_pushnil(L)
|
||||||
|
|
||||||
|
static inline void luaL_requiref(lua_State *L, const char *modname, lua_CFunction openf, int glb)
|
||||||
|
{
|
||||||
|
lua_pushstring(L, "_LOADED");
|
||||||
|
lua_gettable(L, LUA_REGISTRYINDEX);
|
||||||
|
if (lua_isnil(L, -1)) {
|
||||||
|
lua_pop(L, 1);
|
||||||
|
lua_createtable(L, 0, 1);
|
||||||
|
lua_pushstring(L, "_LOADED");
|
||||||
|
lua_pushvalue(L, -2);
|
||||||
|
lua_settable(L, LUA_REGISTRYINDEX);
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_getfield(L, -1, modname);
|
||||||
|
if (lua_isnil(L, -1)) {
|
||||||
|
lua_pop(L, 1);
|
||||||
|
lua_pushcfunction(L, openf);
|
||||||
|
lua_pushstring(L, modname);
|
||||||
|
lua_call(L, 1, 1);
|
||||||
|
lua_pushvalue(L, -1);
|
||||||
|
lua_setfield(L, -3, modname);
|
||||||
|
}
|
||||||
|
if (glb) {
|
||||||
|
lua_pushvalue(L, -1);
|
||||||
|
lua_setglobal(L, modname);
|
||||||
|
}
|
||||||
|
lua_replace(L, -2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif
|
567
osx.c
Normal file
567
osx.c
Normal file
@ -0,0 +1,567 @@
|
|||||||
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
|
||||||
|
/* OS extensions for Lua, module implementation.
|
||||||
|
*
|
||||||
|
* Copyright: 2022, The DoubleFourteen Code Forge
|
||||||
|
* Author: Lorenzo Cogotti
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "xconf.h"
|
||||||
|
#include "osx.h"
|
||||||
|
#include "osx_dir.h"
|
||||||
|
#include "luacompat.h"
|
||||||
|
|
||||||
|
#include "lua.h"
|
||||||
|
#include "lualib.h"
|
||||||
|
#include "lauxlib.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <direct.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#include <io.h>
|
||||||
|
#include <share.h>
|
||||||
|
|
||||||
|
typedef struct __stat64 os_stat_type;
|
||||||
|
|
||||||
|
#ifndef S_ISDIR
|
||||||
|
#define S_ISDIR(mode) ((mode)&_S_IFDIR)
|
||||||
|
#endif
|
||||||
|
#ifndef S_ISREG
|
||||||
|
#define S_ISREG(mode) ((mode)&_S_IFREG)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define fileno(fh) _fileno(fh)
|
||||||
|
#define stat(path, buf) _stat64(path, buf)
|
||||||
|
#define fstat(fd, buf) _fstat64(fd, buf)
|
||||||
|
#define mkdir(path, mode) _mkdir(path)
|
||||||
|
#define getcwd(buf, len) _getcwd(buf, len)
|
||||||
|
#define chdir(path) _chdir(path)
|
||||||
|
#define getdrive() _getdrive()
|
||||||
|
#define chdrive(drive) _chdrive(drive)
|
||||||
|
|
||||||
|
#ifndef _O_WTEXT
|
||||||
|
#define _O_WTEXT 0x10000
|
||||||
|
#endif
|
||||||
|
#ifndef _O_U16TEXT
|
||||||
|
#define _O_U16TEXT 0x20000
|
||||||
|
#endif
|
||||||
|
#ifndef _O_U8TEXT
|
||||||
|
#define _O_U8TEXT 0x40000
|
||||||
|
#endif
|
||||||
|
#define setmode(fd, mode) _setmode(fd, mode)
|
||||||
|
|
||||||
|
static int truncate(const char *path, __int64 size)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
if (_sopen_s(&fd, path, _O_WRONLY|_O_BINARY|_O_NOINHERIT, _SH_DENYRW, 0) != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
int ec = _chsize_s(fd, size);
|
||||||
|
_close(fd);
|
||||||
|
|
||||||
|
return ec;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ftruncate(fd, size) _chsize_s(fd, size)
|
||||||
|
#define fsync(fd) _commit(fd)
|
||||||
|
|
||||||
|
#else
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
typedef struct stat os_stat_type;
|
||||||
|
|
||||||
|
#define _O_BINARY 0
|
||||||
|
#define _O_TEXT 0
|
||||||
|
#define _O_WTEXT 0
|
||||||
|
#define _O_U16TEXT 0
|
||||||
|
#define _O_U8TEXT 0
|
||||||
|
|
||||||
|
static inline int getdrive(void) { return 0; }
|
||||||
|
|
||||||
|
static inline int chdrive(int drive)
|
||||||
|
{
|
||||||
|
(void) drive;
|
||||||
|
|
||||||
|
errno = ENOTSUP;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int setmode(int fd, int mode)
|
||||||
|
{
|
||||||
|
(void) fd, (void) mode;
|
||||||
|
|
||||||
|
errno = ENOTSUP;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
#define sys_posix_fadvise(fd, advice) posix_fadvise(fd, 0, 0, advice)
|
||||||
|
#else
|
||||||
|
// Stub posix_fadvise()
|
||||||
|
#define POSIX_FADV_NORMAL 0
|
||||||
|
#define POSIX_FADV_SEQUENTIAL 0
|
||||||
|
#define POSIX_FADV_RANDOM 0
|
||||||
|
#define POSIX_FADV_NOREUSE 0
|
||||||
|
|
||||||
|
static inline int sys_posix_fadvise(int fd, int advice)
|
||||||
|
{
|
||||||
|
(void) fd;
|
||||||
|
(void) advice;
|
||||||
|
|
||||||
|
errno = ENOTSUP;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int os_pusherror(lua_State *L, const char *path)
|
||||||
|
{
|
||||||
|
int err = errno;
|
||||||
|
|
||||||
|
lua_pushboolean(L, false);
|
||||||
|
|
||||||
|
if (path)
|
||||||
|
lua_pushfstring(L, "%s: %s", path, strerror(err));
|
||||||
|
else
|
||||||
|
lua_pushstring(L, strerror(err));
|
||||||
|
|
||||||
|
lua_pushinteger(L, err);
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int os_pushfail(lua_State *L, const char *path)
|
||||||
|
{
|
||||||
|
int err = errno;
|
||||||
|
|
||||||
|
luaL_pushfail(L);
|
||||||
|
|
||||||
|
if (path)
|
||||||
|
lua_pushfstring(L, "%s: %s", path, strerror(err));
|
||||||
|
else
|
||||||
|
lua_pushstring(L, strerror(err));
|
||||||
|
|
||||||
|
lua_pushinteger(L, err);
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int os_result(lua_State *L, int ec, const char *path)
|
||||||
|
{
|
||||||
|
if (ec == 0) {
|
||||||
|
lua_pushboolean(L, true);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return os_pusherror(L, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
static df_os_dir *todir(lua_State *L)
|
||||||
|
{
|
||||||
|
df_os_dir *dir = luaL_checkudata(L, 1, DF_LUA_DIRHANDLE);
|
||||||
|
if (dir->closeflag)
|
||||||
|
luaL_error(L, "attempt to use a closed directory");
|
||||||
|
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool os_dir_filter(lua_State *L, const char *name)
|
||||||
|
{
|
||||||
|
// Preserve errno across filter calls
|
||||||
|
int err = errno;
|
||||||
|
|
||||||
|
lua_pushvalue(L, 2);
|
||||||
|
lua_pushstring(L, name);
|
||||||
|
lua_call(L, 1, 1);
|
||||||
|
|
||||||
|
errno = err;
|
||||||
|
|
||||||
|
bool result = lua_toboolean(L, -1);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int os_dir_iter(lua_State *L);
|
||||||
|
|
||||||
|
static int os_dir(lua_State *L)
|
||||||
|
{
|
||||||
|
const char *path = luaL_checkstring(L, 1);
|
||||||
|
|
||||||
|
df_os_dir *dir = lua_newuserdata(L, sizeof(*dir));
|
||||||
|
|
||||||
|
dir->hn = os_opendir(path);
|
||||||
|
dir->closeflag = false;
|
||||||
|
if (!dir->hn)
|
||||||
|
luaL_error(L, "%s: %s", path, strerror(errno));
|
||||||
|
|
||||||
|
luaL_setmetatable(L, DF_LUA_DIRHANDLE);
|
||||||
|
|
||||||
|
lua_pushcclosure(L, os_dir_iter, 2);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int os_dir_iter(lua_State *L)
|
||||||
|
{
|
||||||
|
const char *path = lua_tostring(L, lua_upvalueindex(1));
|
||||||
|
df_os_dir *dir = lua_touserdata(L, lua_upvalueindex(2));
|
||||||
|
const char *filename;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
|
||||||
|
nextfilename:
|
||||||
|
filename = os_readdir(dir->hn);
|
||||||
|
if (!filename) {
|
||||||
|
// Error or end of directory
|
||||||
|
if (errno != 0)
|
||||||
|
luaL_error(L, lua_pushfstring(L, "%s: %s", path, strerror(errno)));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip dot and dotdot
|
||||||
|
if (strcmp(filename, ".") == 0 || strcmp(filename, "..") == 0)
|
||||||
|
goto nextfilename;
|
||||||
|
|
||||||
|
// New directory entry
|
||||||
|
lua_pushstring(L, filename);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int os_dir_read(lua_State *L)
|
||||||
|
{
|
||||||
|
df_os_dir *dir = todir(L);
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
|
||||||
|
const char *filename = os_readdir(dir->hn);
|
||||||
|
if (!filename)
|
||||||
|
return (errno == 0) ? 0 : os_pusherror(L, NULL);
|
||||||
|
|
||||||
|
lua_pushstring(L, filename);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int os_dir_close(lua_State *L)
|
||||||
|
{
|
||||||
|
df_os_dir *dir = todir(L);
|
||||||
|
|
||||||
|
os_closedir(dir->hn);
|
||||||
|
dir->closeflag = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int os_dir_gc(lua_State *L)
|
||||||
|
{
|
||||||
|
df_os_dir *dir = luaL_checkudata(L, 1, DF_LUA_DIRHANDLE);
|
||||||
|
|
||||||
|
if (!dir->closeflag)
|
||||||
|
os_dir_close(L);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int os_listfiles(lua_State *L)
|
||||||
|
{
|
||||||
|
const char *path = luaL_checkstring(L, 1);
|
||||||
|
bool dofilter = false;
|
||||||
|
|
||||||
|
if (!lua_isnoneornil(L, 2)) {
|
||||||
|
luaL_checktype(L, 2, LUA_TFUNCTION);
|
||||||
|
dofilter = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
df_os_dirhn hn = os_opendir(path);
|
||||||
|
if (!hn)
|
||||||
|
return os_pushfail(L, path);
|
||||||
|
|
||||||
|
lua_newtable(L);
|
||||||
|
|
||||||
|
const char *filename;
|
||||||
|
int i = 1;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
while ((filename = os_readdir(hn)) != NULL) {
|
||||||
|
if (strcmp(filename, ".") == 0 || strcmp(filename, "..") == 0)
|
||||||
|
continue;
|
||||||
|
if (dofilter && !os_dir_filter(L, filename))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
lua_pushinteger(L, i++);
|
||||||
|
lua_pushstring(L, filename);
|
||||||
|
lua_settable(L, -3);
|
||||||
|
}
|
||||||
|
err = errno;
|
||||||
|
|
||||||
|
os_closedir(hn);
|
||||||
|
if (err != 0)
|
||||||
|
return os_pushfail(L, path);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int os_stat(lua_State *L)
|
||||||
|
{
|
||||||
|
const char *path = NULL;
|
||||||
|
os_stat_type buf;
|
||||||
|
int ec;
|
||||||
|
|
||||||
|
if (lua_isstring(L, 1)) {
|
||||||
|
path = lua_tostring(L, 1);
|
||||||
|
ec = stat(path, &buf);
|
||||||
|
} else {
|
||||||
|
luaL_Stream *stream = luaL_checkudata(L, 1, LUA_FILEHANDLE);
|
||||||
|
ec = fstat(fileno(stream->f), &buf);
|
||||||
|
}
|
||||||
|
if (ec != 0)
|
||||||
|
return os_pushfail(L, path);
|
||||||
|
|
||||||
|
lua_createtable(L, 0, 3);
|
||||||
|
if (S_ISREG(buf.st_mode)) {
|
||||||
|
lua_pushliteral(L, "regular");
|
||||||
|
lua_setfield(L, -2, "type");
|
||||||
|
lua_pushinteger(L, buf.st_size);
|
||||||
|
lua_setfield(L, -2, "size");
|
||||||
|
lua_pushinteger(L, (lua_Integer) buf.st_mtime);
|
||||||
|
lua_setfield(L, -2, "mtime");
|
||||||
|
} else if (S_ISDIR(buf.st_mode)) {
|
||||||
|
lua_pushliteral(L, "directory");
|
||||||
|
lua_setfield(L, -2, "type");
|
||||||
|
lua_pushinteger(L, (lua_Integer) buf.st_mtime);
|
||||||
|
lua_setfield(L, -2, "mtime");
|
||||||
|
} else {
|
||||||
|
lua_pushstring(L, "other");
|
||||||
|
lua_setfield(L, -2, "type");
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int os_mkdir(lua_State *L)
|
||||||
|
{
|
||||||
|
const char *path = luaL_checkstring(L, 1);
|
||||||
|
|
||||||
|
int ec = mkdir(path, 0666);
|
||||||
|
return os_result(L, ec, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int os_getcwd(lua_State *L)
|
||||||
|
{
|
||||||
|
char *p = NULL;
|
||||||
|
size_t size = 128;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
char *np = realloc(p, size);
|
||||||
|
if (!np)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
p = np;
|
||||||
|
if (getcwd(p, size))
|
||||||
|
break; // got working directory
|
||||||
|
|
||||||
|
if (errno != ERANGE)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
size <<= 1;
|
||||||
|
if (size == 0) // PARANOID
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_pushstring(L, p);
|
||||||
|
free(p);
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
free(p);
|
||||||
|
|
||||||
|
return os_pusherror(L, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int os_chdir(lua_State *L)
|
||||||
|
{
|
||||||
|
const char *path = luaL_checkstring(L, 1);
|
||||||
|
|
||||||
|
int ec = chdir(path);
|
||||||
|
return os_result(L, ec, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int os_getdrive(lua_State *L)
|
||||||
|
{
|
||||||
|
errno = 0;
|
||||||
|
|
||||||
|
int drive = getdrive();
|
||||||
|
if (drive == 0) {
|
||||||
|
if (errno != 0)
|
||||||
|
return os_pusherror(L, NULL);
|
||||||
|
|
||||||
|
lua_pushliteral(L, "");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char letter = 'A' + drive - 1;
|
||||||
|
|
||||||
|
lua_pushlstring(L, &letter, 1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int os_chdrive(lua_State *L)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
const char *s = luaL_checklstring(L, 1, &len);
|
||||||
|
if (len != 1)
|
||||||
|
luaL_argerror(L, 1, "invalid drive");
|
||||||
|
|
||||||
|
int drive = *s - 'A' + 1;
|
||||||
|
if (drive < 1 || drive > 26)
|
||||||
|
luaL_argerror(L, 1, "invalid drive");
|
||||||
|
|
||||||
|
int ec = chdrive(drive);
|
||||||
|
return os_result(L, ec, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int os_setmode(lua_State *L)
|
||||||
|
{
|
||||||
|
static const char *modes[] = {
|
||||||
|
"binary",
|
||||||
|
"text",
|
||||||
|
"u8text",
|
||||||
|
"u16text",
|
||||||
|
"wtext",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
static const int imodes[] = {
|
||||||
|
_O_BINARY,
|
||||||
|
_O_TEXT,
|
||||||
|
_O_U8TEXT,
|
||||||
|
_O_U16TEXT,
|
||||||
|
_O_WTEXT
|
||||||
|
};
|
||||||
|
|
||||||
|
luaL_Stream *stream = luaL_checkudata(L, 1, LUA_FILEHANDLE);
|
||||||
|
int i = luaL_checkoption(L, 2, NULL, modes);
|
||||||
|
|
||||||
|
int ec = setmode(fileno(stream->f), imodes[i]);
|
||||||
|
return os_result(L, ec, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int os_chsize(lua_State *L)
|
||||||
|
{
|
||||||
|
lua_Integer size = luaL_checkinteger(L, 2);
|
||||||
|
if (size < 0)
|
||||||
|
size = 0;
|
||||||
|
|
||||||
|
const char *path = NULL;
|
||||||
|
int ec;
|
||||||
|
|
||||||
|
if (lua_isstring(L, 1)) {
|
||||||
|
path = lua_tostring(L, 1);
|
||||||
|
ec = truncate(path, size);
|
||||||
|
} else {
|
||||||
|
luaL_Stream *stream = luaL_checkudata(L, 1, LUA_FILEHANDLE);
|
||||||
|
ec = ftruncate(fileno(stream->f), size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return os_result(L, ec, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int os_fadvise(lua_State *L)
|
||||||
|
{
|
||||||
|
static const char *hints[] = {
|
||||||
|
"normal",
|
||||||
|
"sequential",
|
||||||
|
"random",
|
||||||
|
"noreuse",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
static const int ihints[] = {
|
||||||
|
POSIX_FADV_NORMAL,
|
||||||
|
POSIX_FADV_SEQUENTIAL,
|
||||||
|
POSIX_FADV_RANDOM,
|
||||||
|
POSIX_FADV_NOREUSE
|
||||||
|
};
|
||||||
|
|
||||||
|
luaL_Stream *stream = luaL_checkudata(L, 1, LUA_FILEHANDLE);
|
||||||
|
int i = luaL_checkoption(L, 2, NULL, hints);
|
||||||
|
|
||||||
|
int ec = sys_posix_fadvise(fileno(stream->f), ihints[i]);
|
||||||
|
return os_result(L, ec, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int os_commit(lua_State *L)
|
||||||
|
{
|
||||||
|
luaL_Stream *stream = luaL_checkudata(L, 1, LUA_FILEHANDLE);
|
||||||
|
|
||||||
|
int ec = fsync(fileno(stream->f));
|
||||||
|
return os_result(L, ec, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void createmeta(lua_State *L)
|
||||||
|
{
|
||||||
|
static const luaL_Reg metameth[] = {
|
||||||
|
{ "__index", NULL }, // placeholder
|
||||||
|
{ "__gc", os_dir_gc },
|
||||||
|
#if LUA_VERSION_NUM >= 504
|
||||||
|
{ "__close", os_dir_gc},
|
||||||
|
#endif
|
||||||
|
{ NULL, NULL }
|
||||||
|
};
|
||||||
|
static const luaL_Reg meth[] = {
|
||||||
|
{ "read", os_dir_read },
|
||||||
|
{ "close", os_dir_close },
|
||||||
|
{ NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
luaL_newmetatable(L, DF_LUA_DIRHANDLE);
|
||||||
|
luaL_setfuncs(L, metameth, 0);
|
||||||
|
luaL_newlibtable(L, meth);
|
||||||
|
luaL_setfuncs(L, meth, 0);
|
||||||
|
lua_setfield(L, -2, "__index");
|
||||||
|
lua_pop(L, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DF_OSXMOD_API int luaopen_osx(lua_State *L)
|
||||||
|
{
|
||||||
|
static const luaL_Reg funcs[] = {
|
||||||
|
{ "listfiles", os_listfiles },
|
||||||
|
{ "dir", os_dir },
|
||||||
|
{ "stat", os_stat },
|
||||||
|
{ "mkdir", os_mkdir },
|
||||||
|
{ "getcwd", os_getcwd },
|
||||||
|
{ "chdir", os_chdir },
|
||||||
|
{ "getdrive", os_getdrive },
|
||||||
|
{ "chdrive", os_chdrive },
|
||||||
|
{ "setmode", os_setmode },
|
||||||
|
{ "chsize", os_chsize },
|
||||||
|
{ "fadvise", os_fadvise },
|
||||||
|
{ "commit", os_commit },
|
||||||
|
{ NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
createmeta(L);
|
||||||
|
luaL_newlib(L, funcs);
|
||||||
|
|
||||||
|
lua_createtable(L, 0, 1);
|
||||||
|
luaL_requiref(L, LUA_OSLIBNAME, luaopen_os, false);
|
||||||
|
lua_setfield(L, -2, "__index");
|
||||||
|
lua_setmetatable(L, -2);
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
lua_pushliteral(L, "\\");
|
||||||
|
#else
|
||||||
|
lua_pushliteral(L, "/");
|
||||||
|
#endif
|
||||||
|
lua_setfield(L, -2, "sep");
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
36
osx.h
Normal file
36
osx.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
|
||||||
|
/* Lua OS extensions, low level system facilities.
|
||||||
|
*
|
||||||
|
* Copyright: 2022, The DoubleFourteen Code Forge
|
||||||
|
* Author: Lorenzo Cogotti
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DF_LUA_OSX_H_
|
||||||
|
#define DF_LUA_OSX_H_
|
||||||
|
|
||||||
|
#include "lua.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
#if defined(DF_LUA_OSXLIB)
|
||||||
|
#define DF_OSXMOD_API __declspec(dllexport)
|
||||||
|
#else
|
||||||
|
#define DF_OSXMOD_API __declspec(dllimport)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
#define DF_OSXMOD_API
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void *hn; // df_os_dirhn - see osx_dir.h
|
||||||
|
_Bool closeflag; // whether the directory has been closed
|
||||||
|
} df_os_dir;
|
||||||
|
|
||||||
|
#define DF_LUA_DIRHANDLE "DIR*"
|
||||||
|
#define DF_LUA_OSXLIBNAME "osx"
|
||||||
|
|
||||||
|
DF_OSXMOD_API int luaopen_osx(lua_State *L);
|
||||||
|
|
||||||
|
#endif
|
55
osx_dir.h
Normal file
55
osx_dir.h
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
|
||||||
|
/* Portable low level system directory access.
|
||||||
|
*
|
||||||
|
* Copyright: 2022, The DoubleFourteen Code Forge
|
||||||
|
* Author: Lorenzo Cogotti
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DF_LUA_OSXDIR_H_
|
||||||
|
#define DF_LUA_OSXDIR_H_
|
||||||
|
|
||||||
|
#include "lua.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <io.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
intptr_t dirh; // raw system directory handle
|
||||||
|
_Bool startflag; // whether data references the first directory entry
|
||||||
|
_Bool endflag; // whether we've made to the end of the directory
|
||||||
|
_Bool errflag; // whether last call encountered an error
|
||||||
|
struct _finddata_t data; // directory entry info
|
||||||
|
} *df_os_dirhn;
|
||||||
|
|
||||||
|
#ifdef DF_LUA_OSXLIB
|
||||||
|
#define DF_OSXLIB_API __declspec(dllexport)
|
||||||
|
#else
|
||||||
|
#define DF_OSXLIB_API __declspec(dllimport)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
#include <dirent.h>
|
||||||
|
|
||||||
|
typedef DIR *df_os_dirhn;
|
||||||
|
|
||||||
|
#define DF_OSXLIB_API
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Open directory at 'path' (not NULL).
|
||||||
|
* Returns opened directory handle on success, NULL on failure (sets errno).
|
||||||
|
*/
|
||||||
|
DF_OSXLIB_API df_os_dirhn os_opendir(const char *path);
|
||||||
|
|
||||||
|
/* Read next entry from opened directory handle 'hn' (not NULL).
|
||||||
|
* Returns:
|
||||||
|
* - next entry filename on success.
|
||||||
|
* - NULL leaving errno unchanged when no more entries are available.
|
||||||
|
* - NULL and sets errno on failure.
|
||||||
|
*/
|
||||||
|
DF_OSXLIB_API char *os_readdir(df_os_dirhn hn);
|
||||||
|
|
||||||
|
/* Close opened directory handle 'hn' (not NULL). */
|
||||||
|
DF_OSXLIB_API void os_closedir(df_os_dirhn hn);
|
||||||
|
|
||||||
|
#endif
|
26
xconf.h
Normal file
26
xconf.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
|
||||||
|
/* Cross platform configuration.
|
||||||
|
*
|
||||||
|
* Deals with platform and compiler specific definitions.
|
||||||
|
* Must be included first in every .c source.
|
||||||
|
*
|
||||||
|
* Copyright 2022, The DoubleFourteen Code Forge
|
||||||
|
* Author: Lorenzo Cogotti
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DF_LUA_PREFIX_H_
|
||||||
|
#define DF_LUA_PREFIX_H_
|
||||||
|
|
||||||
|
#ifdef __unix__
|
||||||
|
#define _POSIX_C_SOURCE 200809L
|
||||||
|
#ifdef _AIX
|
||||||
|
#define _LARGE_FILES 1
|
||||||
|
#else
|
||||||
|
#define _FILE_OFFSET_BITS 64
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define _LARGEFILE64_SOURCE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user