[*] First commit.

This commit is contained in:
Lorenzo Cogotti 2022-12-11 18:58:11 +01:00
parent d0d88a62a1
commit 7c36f77dfa
12 changed files with 944 additions and 0 deletions

57
Makefile Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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