1 Commits

Author SHA1 Message Date
Hisham Muhammad
f7eea62957 Fix memory leak in case of realloc failure.
Fixes #101.
2017-11-26 16:49:39 -02:00
29 changed files with 1023 additions and 832 deletions

View File

@@ -6,6 +6,7 @@ env:
- LUA="lua 5.1"
- LUA="lua 5.2"
- LUA="lua 5.3"
- LUA="luajit 2.0"
- LUA="luajit 2.1"
before_install:
@@ -19,7 +20,7 @@ before_install:
- luarocks install luacov-coveralls --server=https://luarocks.org/dev --deps-mode=none
install:
- luarocks make CFLAGS="-O2 -fPIC -ftest-coverage -fprofile-arcs" LIBFLAG="-shared --coverage"
- luarocks make rockspecs/luafilesystem-cvs-3.rockspec CFLAGS="-O2 -fPIC -ftest-coverage -fprofile-arcs" LIBFLAG="-shared --coverage"
script:
- lua -lluacov tests/test.lua

View File

@@ -12,7 +12,7 @@ OBJS= src/$T.o
lib: src/lfs.so
src/lfs.so: $(OBJS)
MACOSX_DEPLOYMENT_TARGET=$(MACOSX_DEPLOYMENT_TARGET); export MACOSX_DEPLOYMENT_TARGET; $(CC) $(LIB_OPTION) -o src/lfs.so $(OBJS)
MACOSX_DEPLOYMENT_TARGET="10.3"; export MACOSX_DEPLOYMENT_TARGET; $(CC) $(LIB_OPTION) -o src/lfs.so $(OBJS)
test: lib
LUA_CPATH=./src/?.so lua tests/test.lua

View File

@@ -5,7 +5,7 @@
# LuaFileSystem - File System Library for Lua
Copyright 2003-2020 Kepler Project
Copyright 2003-2017 Kepler Project
https://keplerproject.github.io/luafilesystem

View File

@@ -11,6 +11,7 @@ environment:
- LUA: "lua 5.1"
- LUA: "lua 5.2 --compat none"
- LUA: "lua 5.3 --compat none"
- LUA: "luajit 2.0"
- LUA: "luajit 2.1"
# Abuse this section so we can have a matrix with different Compiler versions
@@ -29,7 +30,7 @@ before_build:
- echo "Installing external deps"
build_script:
- luarocks make
- luarocks make rockspecs/luafilesystem-cvs-3.rockspec
before_test:

12
config
View File

@@ -3,25 +3,21 @@
# Default installation prefix
PREFIX=/usr/local
LUA_VERSION = 5.1
# System's libraries directory (where binary libraries are installed)
LUA_LIBDIR= $(PREFIX)/lib/lua/$(LUA_VERSION)
LUA_LIBDIR= $(PREFIX)/lib/lua/5.1
# Lua includes directory
LUA_INC += -I$(PREFIX)/include
LUA_INC += -I/usr/include/lua$(LUA_VERSION) -I/usr/include/lua/$(LUA_VERSION)
LUA_INC= $(PREFIX)/include
# OS dependent
LIB_OPTION= -shared #for Linux
#LIB_OPTION= -bundle -undefined dynamic_lookup #for MacOS X
# Minimum runtime OS version on macOS
MACOSX_DEPLOYMENT_TARGET= 10.5
LIBNAME= $T.so.$V
# Compilation directives
WARN= -O2 -Wall -fPIC -W -Waggregate-return -Wcast-align -Wmissing-prototypes -Wnested-externs -Wshadow -Wwrite-strings -pedantic
INCS= $(LUA_INC)
INCS= -I$(LUA_INC)
CFLAGS= $(WARN) $(INCS)
CC= gcc

View File

@@ -1,14 +1,14 @@
LUA_VERSION= 5.1
# Installation directories
# System's libraries directory (where binary libraries are installed)
LUA_LIBDIR= "c:\lua$(LUA_VERSION)"
LUA_LIBDIR= "c:\lua5.1"
# Lua includes directory
LUA_INC= "c:\lua$(LUA_VERSION)\include"
LUA_INC= "c:\lua5.1\include"
# Lua library
LUA_LIB= "c:\lua$(LUA_VERSION)\lua$(LUA_VERSION).lib"
LUA_LIB= "c:\lua5.1\lua5.1.lib"
LIBNAME= $T.dll
# Compilation directives
WARN= /O2

View File

@@ -70,7 +70,7 @@ the underlying directory structure and file attributes.</p>
<h2><a name="status"></a>Status</h2>
<p>Current version is 1.8.0. It works with Lua 5.1, 5.2, 5.3 and 5.4, and it runs on various
<p>Current version is 1.7.0. It works with Lua 5.1, 5.2 and 5.3, and it runs on various
flavors of Unix (including Linux, BSDs, macOS) and Windows.</p>
<h2><a name="download"></a>Download</h2>
@@ -86,15 +86,6 @@ $ luarocks install luafilesystem
<h2><a name="history"></a>History</h2>
<dl class="history">
<dt><strong>Version 1.8.0</strong> [22/Apr/2020]</dt>
<dd><ul>
<li>Lua 5.4 support</li>
<li>lfs.link and lfs.symlinkattributes now work on Windows</li>
<li>MACOSX_DEPLOYMENT_TARGET is configurable in the Makefile</li>
<li>Fallback to _POSIX_PATH_MAX when MAXPATHLEN is not avaliable</li>
<li>Fixed memory leak in case of realloc failure</li>
</ul></dd>
<dt><strong>Version 1.7.0</strong> [15/Sep/2017]</dt>
<dd><ul>
<li>symlinkattributes function now provides 'target' field, containing name of the file that the symlink points to.</li>

View File

@@ -84,7 +84,7 @@ Ierusalimschy, Andr&eacute; Carregal and Tom&aacute;s Guisasola.
The implementation is not derived from licensed software.</p>
<hr/>
<p>Copyright &copy; 2003 - 2020 Kepler Project.</p>
<p>Copyright &copy; 2003 - 2017 Kepler Project.</p>
<p>Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation

View File

@@ -102,15 +102,15 @@ LuaFileSystem offers the following functions:
</p>
<dl class="reference">
<dt><a name="attributes"></a><strong><code>lfs.attributes (filepath [, request_name | result_table])</code></strong></dt>
<dt><a name="attributes"></a><strong><code>lfs.attributes (filepath [, aname | atable])</code></strong></dt>
<dd>Returns a table with the file attributes corresponding to
<code>filepath</code> (or <code>nil</code> followed by an error message and a system-dependent error code
in case of error).
If the second optional argument is given and is a string, then only the value of the
named attribute is returned (this use is equivalent to
<code>lfs.attributes(filepath)[request_name]</code>, but the table is not created
<code>lfs.attributes(filepath)[aname]</code>, but the table is not created
and only one attribute is retrieved from the O.S.).
if a table is passed as the second argument, it (<code>result_table</code>) is filled with attributes and returned instead of a new table.
if a table is passed as the second argument, it is filled with attributes and returned instead of a new table.
The attributes are described as follows;
attribute <code>mode</code> is a string, all the others are numbers,
and the time related attributes use the same time reference of
@@ -239,7 +239,7 @@ LuaFileSystem offers the following functions:
setting the mode has no effect, and the mode is always returned as <code>binary</code>.
</dd>
<dt><a name="symlinkattributes"></a><strong><code>lfs.symlinkattributes (filepath [, request_name])</code></strong></dt>
<dt><a name="symlinkattributes"></a><strong><code>lfs.symlinkattributes (filepath [, aname])</code></strong></dt>
<dd>Identical to <a href="#attributes">lfs.attributes</a> except that
it obtains information about the link itself (not the file it refers to).
It also adds a <strong><code>target</code></strong> field, containing

View File

@@ -0,0 +1,27 @@
package = "LuaFileSystem"
version = "1.3.0-1"
source = {
url = "http://luaforge.net/frs/download.php/2679/luafilesystem-1.3.0.tar.gz"
}
description = {
summary = "File System Library for the Lua Programming Language",
detailed = [[
LuaFileSystem is a Lua library developed to complement the set of
functions related to file systems offered by the standard Lua
distribution. LuaFileSystem offers a portable way to access the
underlying directory structure and file attributes.
]]
}
dependencies = {
"lua >= 5.1"
}
build = {
type = "make",
build_variables = {
LUA_INC = "$(LUA_INCDIR)",
LIB_OPTION = "$(LIBFLAG)"
},
install_variables = {
LUA_LIBDIR = "$(LIBDIR)"
}
}

View File

@@ -0,0 +1,27 @@
package = "LuaFileSystem"
version = "1.4.0-1"
source = {
url = "http://luaforge.net/frs/download.php/3158/luafilesystem-1.4.0.tar.gz"
}
description = {
summary = "File System Library for the Lua Programming Language",
detailed = [[
LuaFileSystem is a Lua library developed to complement the set of
functions related to file systems offered by the standard Lua
distribution. LuaFileSystem offers a portable way to access the
underlying directory structure and file attributes.
]]
}
dependencies = {
"lua >= 5.1"
}
build = {
type = "make",
build_variables = {
LUA_INC = "$(LUA_INCDIR)",
LIB_OPTION = "$(LIBFLAG)"
},
install_variables = {
LUA_LIBDIR = "$(LIBDIR)"
}
}

View File

@@ -0,0 +1,43 @@
package = "LuaFileSystem"
version = "1.4.0-2"
source = {
url = "http://luaforge.net/frs/download.php/3158/luafilesystem-1.4.0.tar.gz"
}
description = {
summary = "File System Library for the Lua Programming Language",
detailed = [[
LuaFileSystem is a Lua library developed to complement the set of
functions related to file systems offered by the standard Lua
distribution. LuaFileSystem offers a portable way to access the
underlying directory structure and file attributes.
]]
}
dependencies = {
"lua >= 5.1"
}
build = {
platforms = {
unix = {
type = "make",
build_variables = {
LIB_OPTION = "$(LIBFLAG)",
CFLAGS = "$(CFLAGS) -I$(LUA_INCDIR)",
},
install_variables = {
LUA_LIBDIR = "$(LIBDIR)"
}
},
win32 = {
type = "make",
build_variables = {
LUA_LIB = "$(LUA_LIBDIR)\\lua5.1.lib",
CFLAGS = "/MD $(CFLAGS) /I$(LUA_INCDIR)",
},
install_variables = {
LUA_LIBDIR = "$(LIBDIR)",
LUA_DIR = "$(LUADIR)",
BIN_DIR = "$(BINDIR)"
}
}
}
}

View File

@@ -0,0 +1,43 @@
package = "LuaFileSystem"
version = "1.4.1-1"
source = {
url = "http://luaforge.net/frs/download.php/3345/luafilesystem-1.4.1.tar.gz",
}
description = {
summary = "File System Library for the Lua Programming Language",
detailed = [[
LuaFileSystem is a Lua library developed to complement the set of
functions related to file systems offered by the standard Lua
distribution. LuaFileSystem offers a portable way to access the
underlying directory structure and file attributes.
]]
}
dependencies = {
"lua >= 5.1"
}
build = {
platforms = {
unix = {
type = "make",
build_variables = {
LIB_OPTION = "$(LIBFLAG)",
CFLAGS = "$(CFLAGS) -I$(LUA_INCDIR) $(STAT64)",
},
install_variables = {
LUA_LIBDIR = "$(LIBDIR)"
}
},
win32 = {
type = "make",
build_variables = {
LUA_LIB = "$(LUA_LIBDIR)\\lua5.1.lib",
CFLAGS = "/MD $(CFLAGS) /I$(LUA_INCDIR)",
},
install_variables = {
LUA_LIBDIR = "$(LIBDIR)",
LUA_DIR = "$(LUADIR)",
BIN_DIR = "$(BINDIR)"
}
}
}
}

View File

@@ -0,0 +1,43 @@
package = "LuaFileSystem"
version = "1.4.1rc1-1"
source = {
url = "http://luafilesystem.luaforge.net/luafilesystem-1.4.1rc1.tar.gz",
}
description = {
summary = "File System Library for the Lua Programming Language",
detailed = [[
LuaFileSystem is a Lua library developed to complement the set of
functions related to file systems offered by the standard Lua
distribution. LuaFileSystem offers a portable way to access the
underlying directory structure and file attributes.
]]
}
dependencies = {
"lua >= 5.1"
}
build = {
platforms = {
unix = {
type = "make",
build_variables = {
LIB_OPTION = "$(LIBFLAG)",
CFLAGS = "$(CFLAGS) -I$(LUA_INCDIR) $(STAT64)",
},
install_variables = {
LUA_LIBDIR = "$(LIBDIR)"
}
},
win32 = {
type = "make",
build_variables = {
LUA_LIB = "$(LUA_LIBDIR)\\lua5.1.lib",
CFLAGS = "/MD $(CFLAGS) /I$(LUA_INCDIR)",
},
install_variables = {
LUA_LIBDIR = "$(LIBDIR)",
LUA_DIR = "$(LUADIR)",
BIN_DIR = "$(BINDIR)"
}
}
}
}

View File

@@ -0,0 +1,26 @@
package = "LuaFileSystem"
version = "1.4.2-1"
source = {
url = "http://luaforge.net/frs/download.php/3931/luafilesystem-1.4.2.tar.gz",
}
description = {
summary = "File System Library for the Lua Programming Language",
detailed = [[
LuaFileSystem is a Lua library developed to complement the set of
functions related to file systems offered by the standard Lua
distribution. LuaFileSystem offers a portable way to access the
underlying directory structure and file attributes.
]]
}
dependencies = {
"lua >= 5.1"
}
build = {
type = "module",
modules = { lfs = "src/lfs.c" }
}

View File

@@ -0,0 +1,27 @@
package = "LuaFileSystem"
version = "1.5.0-1"
source = {
url = "http://cloud.github.com/downloads/keplerproject/luafilesystem/luafilesystem-1.5.0.tar.gz",
}
description = {
summary = "File System Library for the Lua Programming Language",
detailed = [[
LuaFileSystem is a Lua library developed to complement the set of
functions related to file systems offered by the standard Lua
distribution. LuaFileSystem offers a portable way to access the
underlying directory structure and file attributes.
]]
}
dependencies = {
"lua >= 5.1"
}
build = {
type = "module",
modules = { lfs = "src/lfs.c" },
copy_directories = { "doc", "tests" }
}

View File

@@ -0,0 +1,27 @@
package = "LuaFileSystem"
version = "1.6.0-1"
source = {
url = "https://github.com/downloads/keplerproject/luafilesystem/luafilesystem-1.6.0.tar.gz",
}
description = {
summary = "File System Library for the Lua Programming Language",
detailed = [[
LuaFileSystem is a Lua library developed to complement the set of
functions related to file systems offered by the standard Lua
distribution. LuaFileSystem offers a portable way to access the
underlying directory structure and file attributes.
]]
}
dependencies = {
"lua >= 5.1"
}
build = {
type = "builtin",
modules = { lfs = "src/lfs.c" },
copy_directories = { "doc", "tests" }
}

View File

@@ -0,0 +1,27 @@
package = "LuaFileSystem"
version = "1.6.1-1"
source = {
url = "https://github.com/downloads/keplerproject/luafilesystem/luafilesystem-1.6.1.tar.gz",
}
description = {
summary = "File System Library for the Lua Programming Language",
detailed = [[
LuaFileSystem is a Lua library developed to complement the set of
functions related to file systems offered by the standard Lua
distribution. LuaFileSystem offers a portable way to access the
underlying directory structure and file attributes.
]]
}
dependencies = {
"lua >= 5.1"
}
build = {
type = "builtin",
modules = { lfs = "src/lfs.c" },
copy_directories = { "doc", "tests" }
}

View File

@@ -0,0 +1,27 @@
package = "LuaFileSystem"
version = "1.6.2-1"
source = {
url = "https://github.com/downloads/keplerproject/luafilesystem/luafilesystem-1.6.2.tar.gz",
}
description = {
summary = "File System Library for the Lua Programming Language",
detailed = [[
LuaFileSystem is a Lua library developed to complement the set of
functions related to file systems offered by the standard Lua
distribution. LuaFileSystem offers a portable way to access the
underlying directory structure and file attributes.
]]
}
dependencies = {
"lua >= 5.1"
}
build = {
type = "builtin",
modules = { lfs = "src/lfs.c" },
copy_directories = { "doc", "tests" }
}

View File

@@ -0,0 +1,28 @@
package = "LuaFileSystem"
version = "1.6.3-1"
source = {
url = "git://github.com/keplerproject/luafilesystem",
tag = "v_1_6_3",
}
description = {
summary = "File System Library for the Lua Programming Language",
detailed = [[
LuaFileSystem is a Lua library developed to complement the set of
functions related to file systems offered by the standard Lua
distribution. LuaFileSystem offers a portable way to access the
underlying directory structure and file attributes.
]],
license = "MIT/X11",
}
dependencies = {
"lua >= 5.1"
}
build = {
type = "builtin",
modules = {
lfs = "src/lfs.c"
},
copy_directories = {
"doc", "tests"
}
}

View File

@@ -1,7 +1,8 @@
package = "luafilesystem"
version = "scm-1"
package = "LuaFileSystem"
version = "1.7.0-1"
source = {
url = "git://github.com/keplerproject/luafilesystem"
url = "git://github.com/keplerproject/luafilesystem",
tag = "v1_7_0",
}
description = {
summary = "File System Library for the Lua Programming Language",
@@ -11,7 +12,7 @@ description = {
distribution. LuaFileSystem offers a portable way to access the
underlying directory structure and file attributes.
]],
license = "MIT/X11"
license = "MIT/X11",
}
dependencies = {
"lua >= 5.1"
@@ -22,7 +23,6 @@ build = {
lfs = "src/lfs.c"
},
copy_directories = {
"doc",
"tests"
"doc", "tests"
}
}

View File

@@ -0,0 +1,28 @@
package = "LuaFileSystem"
version = "1.7.0-2"
source = {
url = "git://github.com/keplerproject/luafilesystem",
tag = "v1_7_0_2",
}
description = {
summary = "File System Library for the Lua Programming Language",
detailed = [[
LuaFileSystem is a Lua library developed to complement the set of
functions related to file systems offered by the standard Lua
distribution. LuaFileSystem offers a portable way to access the
underlying directory structure and file attributes.
]],
license = "MIT/X11",
}
dependencies = {
"lua >= 5.1"
}
build = {
type = "builtin",
modules = {
lfs = "src/lfs.c"
},
copy_directories = {
"doc", "tests"
}
}

View File

@@ -0,0 +1,44 @@
package = "LuaFileSystem"
version = "cvs-1"
source = {
url = "cvs://:pserver:anonymous:@cvs.luaforge.net:/cvsroot/luafilesystem",
cvs_tag = "HEAD"
}
description = {
summary = "File System Library for the Lua Programming Language",
detailed = [[
LuaFileSystem is a Lua library developed to complement the set of
functions related to file systems offered by the standard Lua
distribution. LuaFileSystem offers a portable way to access the
underlying directory structure and file attributes.
]]
}
dependencies = {
"lua >= 5.1"
}
build = {
platforms = {
unix = {
type = "make",
build_variables = {
LIB_OPTION = "$(LIBFLAG)",
CFLAGS = "$(CFLAGS) -I$(LUA_INCDIR)",
},
install_variables = {
LUA_LIBDIR = "$(LIBDIR)"
}
},
win32 = {
type = "make",
build_variables = {
LUA_LIB = "$(LUA_LIBDIR)\\lua5.1.lib",
CFLAGS = "$(CFLAGS) /I$(LUA_INCDIR)",
},
install_variables = {
LUA_LIBDIR = "$(LIBDIR)",
LUA_DIR = "$(LUADIR)",
BIN_DIR = "$(BINDIR)"
}
}
}
}

View File

@@ -0,0 +1,26 @@
package = "LuaFileSystem"
version = "cvs-2"
source = {
url = "git://github.com/keplerproject/luafilesystem.git",
}
description = {
summary = "File System Library for the Lua Programming Language",
detailed = [[
LuaFileSystem is a Lua library developed to complement the set of
functions related to file systems offered by the standard Lua
distribution. LuaFileSystem offers a portable way to access the
underlying directory structure and file attributes.
]]
}
dependencies = {
"lua >= 5.1"
}
build = {
type = "module",
modules = { lfs = "src/lfs.c" }
}

View File

@@ -0,0 +1,27 @@
package = "LuaFileSystem"
version = "cvs-3"
source = {
url = "git://github.com/keplerproject/luafilesystem.git",
}
description = {
summary = "File System Library for the Lua Programming Language",
detailed = [[
LuaFileSystem is a Lua library developed to complement the set of
functions related to file systems offered by the standard Lua
distribution. LuaFileSystem offers a portable way to access the
underlying directory structure and file attributes.
]]
}
dependencies = {
"lua >= 5.1, < 5.4"
}
build = {
type = "builtin",
modules = { lfs = "src/lfs.c" },
copy_directories = { "doc", "tests" }
}

525
src/lfs.c
View File

@@ -1,7 +1,6 @@
/*
** LuaFileSystem
** Copyright Kepler Project 2003 - 2020
** (http://keplerproject.github.io/luafilesystem)
** Copyright Kepler Project 2003 - 2017 (http://keplerproject.github.io/luafilesystem)
**
** File system manipulation library.
** This library offers these functions:
@@ -30,10 +29,6 @@
#endif
#endif
#ifdef _WIN32
#define _WIN32_WINNT 0x600
#endif
#ifndef LFS_DO_NOT_USE_LARGE_FILE
#define _LARGEFILE64_SOURCE
#endif
@@ -46,39 +41,26 @@
#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>
/* MAX_PATH seems to be 260. Seems kind of small. Is there a better one? */
#define LFS_MAXPATHLEN MAX_PATH
#else
#include <unistd.h>
#include <dirent.h>
#include <fcntl.h>
#include <sys/types.h>
#include <utime.h>
#include <sys/param.h> /* for MAXPATHLEN */
#ifdef MAXPATHLEN
#define LFS_MAXPATHLEN MAXPATHLEN
#else
#include <limits.h> /* for _POSIX_PATH_MAX */
#define LFS_MAXPATHLEN _POSIX_PATH_MAX
#endif
#endif
#include <lua.h>
@@ -87,10 +69,10 @@
#include "lfs.h"
#define LFS_VERSION "1.8.0"
#define LFS_VERSION "1.7.0"
#define LFS_LIBNAME "lfs"
#if LUA_VERSION_NUM >= 503 /* Lua 5.3+ */
#if LUA_VERSION_NUM >= 503 /* Lua 5.3 */
#ifndef luaL_optlong
#define luaL_optlong luaL_optinteger
@@ -123,7 +105,6 @@ typedef struct dir_data {
#define LOCK_METATABLE "lock metatable"
#ifdef _WIN32
#ifdef __BORLANDC__
#define lfs_setmode(file, m) (setmode(_fileno(file), m))
#define STAT_STRUCT struct stati64
@@ -131,45 +112,15 @@ typedef struct dir_data {
#define lfs_setmode(file, m) (_setmode(_fileno(file), m))
#define STAT_STRUCT struct _stati64
#endif
#ifndef _S_IFLNK
#define _S_IFLNK 0x400
#endif
#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) (mode&_S_IFLNK)
#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
#define STAT_FUNC _stati64
#define LSTAT_FUNC lfs_win32_lstat
#define LSTAT_FUNC STAT_FUNC
#else
#define _O_TEXT 0
#define _O_BINARY 0
#define lfs_setmode(file, m) ((void)file, (void)m, 0)
#define STAT_STRUCT struct stat
#define STAT_FUNC stat
#define LSTAT_FUNC lstat
#endif
#ifdef _WIN32
@@ -179,55 +130,6 @@ typedef struct dir_data {
S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IXOTH))
#endif
#ifdef _WIN32
int lfs_win32_pusherror(lua_State * L)
{
int en = GetLastError();
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;
}
#define TICKS_PER_SECOND 10000000
#define EPOCH_DIFFERENCE 11644473600LL
time_t windowsToUnixTime(FILETIME ft)
{
ULARGE_INTEGER uli;
uli.LowPart = ft.dwLowDateTime;
uli.HighPart = ft.dwHighDateTime;
return (time_t) (uli.QuadPart / TICKS_PER_SECOND - EPOCH_DIFFERENCE);
}
int lfs_win32_lstat(const char *path, STAT_STRUCT * buffer)
{
WIN32_FILE_ATTRIBUTE_DATA win32buffer;
if (GetFileAttributesEx(path, GetFileExInfoStandard, &win32buffer)) {
if (!(win32buffer.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
return STAT_FUNC(path, buffer);
}
buffer->st_mode = _S_IFLNK;
buffer->st_dev = 0;
buffer->st_ino = 0;
buffer->st_nlink = 0;
buffer->st_uid = 0;
buffer->st_gid = 0;
buffer->st_rdev = 0;
buffer->st_atime = windowsToUnixTime(win32buffer.ftLastAccessTime);
buffer->st_mtime = windowsToUnixTime(win32buffer.ftLastWriteTime);
buffer->st_ctime = windowsToUnixTime(win32buffer.ftCreationTime);
buffer->st_size = 0;
return 0;
} else {
return 1;
}
}
#endif
/*
** Utility functions
*/
@@ -242,8 +144,7 @@ static int pusherror(lua_State * L, const char *info)
return 3;
}
static int pushresult(lua_State * L, int res, const char *info)
{
static int pushresult(lua_State *L, int res, const char *info) {
if (res == -1) {
return pusherror(L, info);
} else {
@@ -256,8 +157,7 @@ static int pushresult(lua_State * L, int res, const char *info)
/*
** This function changes the working (current) directory
*/
static int change_dir(lua_State * L)
{
static int change_dir (lua_State *L) {
const char *path = luaL_checkstring(L, 1);
if (chdir(path)) {
lua_pushnil (L);
@@ -275,21 +175,19 @@ static int change_dir(lua_State * L)
** If unable to get the current directory, it returns nil
** and a string describing the error
*/
static int get_dir(lua_State * L)
{
static int get_dir (lua_State *L) {
#ifdef NO_GETCWD
lua_pushnil(L);
lua_pushstring(L, "Function 'getcwd' not provided by system");
return 2;
#else
char *path = NULL;
/* Passing (NULL, 0) is not guaranteed to work.
Use a temp buffer and size instead. */
/* Passing (NULL, 0) is not guaranteed to work. Use a temp buffer and size instead. */
size_t size = LFS_MAXPATHLEN; /* initial buffer size */
int result;
while (1) {
char* path2 = realloc(path, size);
if (!path2) { /* failed to allocate */
if (!path2) /* failed to allocate */ {
result = pusherror(L, "get_dir realloc() failed");
break;
}
@@ -315,8 +213,7 @@ static int get_dir(lua_State * L)
/*
** 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)
{
static FILE *check_file (lua_State *L, int idx, const char *funcname) {
#if LUA_VERSION_NUM == 501
FILE **fh = (FILE **)luaL_checkudata (L, idx, "FILE*");
if (*fh == NULL) {
@@ -324,7 +221,7 @@ static FILE *check_file(lua_State * L, int idx, const char *funcname)
return 0;
} else
return *fh;
#elif LUA_VERSION_NUM >= 502 && LUA_VERSION_NUM <= 504
#elif LUA_VERSION_NUM >= 502 && LUA_VERSION_NUM <= 503
luaL_Stream *fh = (luaL_Stream *)luaL_checkudata (L, idx, "FILE*");
if (fh->closef == 0 || fh->f == NULL) {
luaL_error (L, "%s: closed file", funcname);
@@ -340,41 +237,26 @@ static FILE *check_file(lua_State * L, int idx, const char *funcname)
/*
**
*/
static int _file_lock(lua_State * L, FILE * fh, const char *mode,
const long start, long len, const char *funcname)
{
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_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.
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.
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);
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);
@@ -389,17 +271,10 @@ static int _file_lock(lua_State * L, FILE * fh, const char *mode,
#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);
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;
@@ -413,37 +288,35 @@ static int _file_lock(lua_State * L, FILE * fh, const char *mode,
typedef struct lfs_Lock {
HANDLE fd;
} lfs_Lock;
static int lfs_lock_dir(lua_State * L)
{
size_t pathl;
HANDLE fd;
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));
lua_pushnil(L); lua_pushstring(L, strerror(errno)); return 2;
}
strcpy(ln, path); strcat(ln, lockfile);
if((fd = CreateFile(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;
}
strcpy(ln, path);
strcat(ln, lockfile);
fd = CreateFile(ln, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL);
free(ln);
if (fd == INVALID_HANDLE_VALUE) {
return lfs_win32_pusherror(L);
}
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)
{
static int lfs_unlock_dir(lua_State *L) {
lfs_Lock *lock = (lfs_Lock *)luaL_checkudata(L, 1, LOCK_METATABLE);
if(lock->fd != INVALID_HANDLE_VALUE) {
CloseHandle(lock->fd);
@@ -455,8 +328,7 @@ static int lfs_unlock_dir(lua_State * L)
typedef struct lfs_Lock {
char *ln;
} lfs_Lock;
static int lfs_lock_dir(lua_State * L)
{
static int lfs_lock_dir(lua_State *L) {
lfs_Lock *lock;
size_t pathl;
char *ln;
@@ -465,26 +337,19 @@ static int lfs_lock_dir(lua_State * L)
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;
lua_pushnil(L); lua_pushstring(L, strerror(errno)); return 2;
}
strcpy(ln, path);
strcat(ln, lockfile);
strcpy(ln, path); strcat(ln, lockfile);
if(symlink("lock", ln) == -1) {
free(ln);
lua_pushnil(L);
lua_pushstring(L, strerror(errno));
return 2;
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)
{
static int lfs_unlock_dir(lua_State *L) {
lfs_Lock *lock = (lfs_Lock *)luaL_checkudata(L, 1, LOCK_METATABLE);
if(lock->ln) {
unlink(lock->ln);
@@ -495,8 +360,7 @@ static int lfs_unlock_dir(lua_State * L)
}
#endif
static int lfs_g_setmode(lua_State * L, FILE * f, int arg)
{
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);
@@ -517,8 +381,7 @@ static int lfs_g_setmode(lua_State * L, FILE * f, int arg)
}
}
static int lfs_f_setmode(lua_State * L)
{
static int lfs_f_setmode(lua_State *L) {
return lfs_g_setmode(L, check_file(L, 1, "setmode"), 2);
}
@@ -529,8 +392,7 @@ static int lfs_f_setmode(lua_State * L)
** @param #3 Number with start position (optional).
** @param #4 Number with length (optional).
*/
static int file_lock(lua_State * L)
{
static int file_lock (lua_State *L) {
FILE *fh = check_file (L, 1, "lock");
const char *mode = luaL_checkstring (L, 2);
const long start = (long) luaL_optinteger (L, 3, 0);
@@ -552,8 +414,7 @@ static int file_lock(lua_State * L)
** @param #2 Number with start position (optional).
** @param #3 Number with length (optional).
*/
static int file_unlock(lua_State * L)
{
static int file_unlock (lua_State *L) {
FILE *fh = check_file (L, 1, "unlock");
const long start = (long) luaL_optinteger (L, 2, 0);
long len = (long) luaL_optinteger (L, 3, 0);
@@ -574,40 +435,20 @@ static int file_unlock(lua_State * L)
** @param #2 Name of link.
** @param #3 True if link is symbolic (optional).
*/
static int make_link(lua_State * L)
{
static int make_link (lua_State *L) {
#ifndef _WIN32
const char *oldpath = luaL_checkstring(L, 1);
const char *newpath = luaL_checkstring(L, 2);
#ifndef _WIN32
return pushresult(L,
(lua_toboolean(L, 3) ? symlink : link) (oldpath,
newpath),
NULL);
#else
int symbolic = lua_toboolean(L, 3);
STAT_STRUCT oldpathinfo;
int is_dir = 0;
if (STAT_FUNC(oldpath, &oldpathinfo) == 0) {
is_dir = S_ISDIR(oldpathinfo.st_mode) != 0;
}
if (!symbolic && is_dir) {
lua_pushnil(L);
lua_pushstring(L,
"hard links to directories are not supported on Windows");
return 2;
}
int result = symbolic ? CreateSymbolicLink(newpath, oldpath, is_dir)
: CreateHardLink(newpath, oldpath, NULL);
if (result) {
return pushresult(L, result, NULL);
int res = (lua_toboolean(L,3) ? symlink : link)(oldpath, newpath);
if (res == -1) {
return pusherror(L, NULL);
} else {
lua_pushnil(L);
lua_pushstring(L, symbolic ? "make_link CreateSymbolicLink() failed"
: "make_link CreateHardLink() failed");
return 2;
lua_pushinteger(L, 0);
return 1;
}
#else
errno = ENOSYS; /* = "Function not implemented" */
return pushresult(L, -1, "make_link is not supported on Windows");
#endif
}
@@ -616,8 +457,7 @@ static int make_link(lua_State * L)
** Creates a directory.
** @param #1 Directory path.
*/
static int make_dir(lua_State * L)
{
static int make_dir (lua_State *L) {
const char *path = luaL_checkstring(L, 1);
return pushresult(L, lfs_mkdir(path), NULL);
}
@@ -627,8 +467,7 @@ static int make_dir(lua_State * L)
** Removes a directory.
** @param #1 Directory path.
*/
static int remove_dir(lua_State * L)
{
static int remove_dir (lua_State *L) {
const char *path = luaL_checkstring(L, 1);
return pushresult(L, rmdir(path), NULL);
}
@@ -637,8 +476,7 @@ static int remove_dir(lua_State * L)
/*
** Directory iterator
*/
static int dir_iter(lua_State * L)
{
static int dir_iter (lua_State *L) {
#ifdef _WIN32
struct _finddata_t c_file;
#else
@@ -685,8 +523,7 @@ static int dir_iter(lua_State * L)
/*
** Closes directory iterators
*/
static int dir_close(lua_State * L)
{
static int dir_close (lua_State *L) {
dir_data *d = (dir_data *)lua_touserdata (L, 1);
#ifdef _WIN32
if (!d->closed && d->hFile) {
@@ -705,8 +542,7 @@ static int dir_close(lua_State * L)
/*
** Factory of directory iterators
*/
static int dir_iter_factory(lua_State * L)
{
static int dir_iter_factory (lua_State *L) {
const char *path = luaL_checkstring (L, 1);
dir_data *d;
lua_pushcfunction (L, dir_iter);
@@ -725,21 +561,14 @@ static int dir_iter_factory(lua_State * L)
if (d->dir == NULL)
luaL_error (L, "cannot open %s: %s", path, strerror (errno));
#endif
#if LUA_VERSION_NUM >= 504
lua_pushnil(L);
lua_pushvalue(L, -2);
return 4;
#else
return 2;
#endif
}
/*
** Creates directory metatable.
*/
static int dir_create_meta(lua_State * L)
{
static int dir_create_meta (lua_State *L) {
luaL_newmetatable (L, DIR_METATABLE);
/* Method table */
@@ -753,11 +582,6 @@ static int dir_create_meta(lua_State * L)
lua_setfield(L, -2, "__index");
lua_pushcfunction (L, dir_close);
lua_setfield (L, -2, "__gc");
#if LUA_VERSION_NUM >= 504
lua_pushcfunction(L, dir_close);
lua_setfield(L, -2, "__close");
#endif
return 1;
}
@@ -765,8 +589,7 @@ static int dir_create_meta(lua_State * L)
/*
** Creates lock metatable.
*/
static int lock_create_meta(lua_State * L)
{
static int lock_create_meta (lua_State *L) {
luaL_newmetatable (L, LOCK_METATABLE);
/* Method table */
@@ -782,15 +605,36 @@ static int lock_create_meta(lua_State * L)
}
#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)
{
static const char *mode2string (unsigned short mode) {
#else
static const char *mode2string(mode_t mode)
{
static const char *mode2string (mode_t mode) {
#endif
if ( S_ISREG(mode) )
return "file";
@@ -817,8 +661,7 @@ static const char *mode2string(mode_t mode)
** @param #2 Access time in seconds, current time is used if missing.
** @param #3 Modification time in seconds, access time is used if missing.
*/
static int file_utime(lua_State * L)
{
static int file_utime (lua_State *L) {
const char *file = luaL_checkstring(L, 1);
struct utimbuf utb, *buf;
@@ -835,81 +678,56 @@ static int file_utime(lua_State * L)
/* inode protection mode */
static void push_st_mode(lua_State * L, STAT_STRUCT * info)
{
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)
{
static void push_st_dev (lua_State *L, STAT_STRUCT *info) {
lua_pushinteger (L, (lua_Integer) info->st_dev);
}
/* inode's number */
static void push_st_ino(lua_State * L, STAT_STRUCT * info)
{
static void push_st_ino (lua_State *L, STAT_STRUCT *info) {
lua_pushinteger (L, (lua_Integer) info->st_ino);
}
/* number of hard links to the file */
static void push_st_nlink(lua_State * L, STAT_STRUCT * info)
{
static void push_st_nlink (lua_State *L, STAT_STRUCT *info) {
lua_pushinteger (L, (lua_Integer)info->st_nlink);
}
/* user-id of owner */
static void push_st_uid(lua_State * L, STAT_STRUCT * info)
{
static void push_st_uid (lua_State *L, STAT_STRUCT *info) {
lua_pushinteger (L, (lua_Integer)info->st_uid);
}
/* group-id of owner */
static void push_st_gid(lua_State * L, STAT_STRUCT * info)
{
static void push_st_gid (lua_State *L, STAT_STRUCT *info) {
lua_pushinteger (L, (lua_Integer)info->st_gid);
}
/* device type, for special file inode */
static void push_st_rdev(lua_State * L, STAT_STRUCT * info)
{
static void push_st_rdev (lua_State *L, STAT_STRUCT *info) {
lua_pushinteger (L, (lua_Integer) info->st_rdev);
}
/* time of last access */
static void push_st_atime(lua_State * L, STAT_STRUCT * info)
{
static void push_st_atime (lua_State *L, STAT_STRUCT *info) {
lua_pushinteger (L, (lua_Integer) info->st_atime);
}
/* time of last data modification */
static void push_st_mtime(lua_State * L, STAT_STRUCT * info)
{
static void push_st_mtime (lua_State *L, STAT_STRUCT *info) {
lua_pushinteger (L, (lua_Integer) info->st_mtime);
}
/* time of last file status change */
static void push_st_ctime(lua_State * L, STAT_STRUCT * info)
{
static void push_st_ctime (lua_State *L, STAT_STRUCT *info) {
lua_pushinteger (L, (lua_Integer) info->st_ctime);
}
/* file size, in bytes */
static void push_st_size(lua_State * L, STAT_STRUCT * info)
{
static void push_st_size (lua_State *L, STAT_STRUCT *info) {
lua_pushinteger (L, (lua_Integer)info->st_size);
}
#ifndef _WIN32
/* blocks allocated for file */
static void push_st_blocks(lua_State * L, STAT_STRUCT * info)
{
static void push_st_blocks (lua_State *L, STAT_STRUCT *info) {
lua_pushinteger (L, (lua_Integer)info->st_blocks);
}
/* optimal file system I/O blocksize */
static void push_st_blksize(lua_State * L, STAT_STRUCT * info)
{
static void push_st_blksize (lua_State *L, STAT_STRUCT *info) {
lua_pushinteger (L, (lua_Integer)info->st_blksize);
}
#endif
@@ -919,61 +737,38 @@ static void push_st_blksize(lua_State * L, STAT_STRUCT * info)
*/
#ifdef _WIN32
static const char *perm2string(unsigned short mode)
{
static const char *perm2string (unsigned short mode) {
static char perms[10] = "---------";
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';
}
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 const char *perm2string (mode_t mode) {
static char perms[10] = "---------";
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';
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)
{
static void push_st_perm (lua_State *L, STAT_STRUCT *info) {
lua_pushstring (L, perm2string (info->st_mode));
}
@@ -1007,17 +802,14 @@ struct _stat_members members[] = {
/*
** Get file or symbolic link information
*/
static int _file_info_(lua_State * L,
int (*st)(const char *, STAT_STRUCT *))
{
static int _file_info_ (lua_State *L, int (*st)(const char*, STAT_STRUCT*)) {
STAT_STRUCT info;
const char *file = luaL_checkstring (L, 1);
int i;
if (st(file, &info)) {
lua_pushnil(L);
lua_pushfstring(L, "cannot obtain information from file '%s': %s",
file, strerror(errno));
lua_pushfstring(L, "cannot obtain information from file '%s': %s", file, strerror(errno));
lua_pushinteger(L, errno);
return 3;
}
@@ -1051,8 +843,7 @@ static int _file_info_(lua_State * L,
/*
** Get file information using stat.
*/
static int file_info(lua_State * L)
{
static int file_info (lua_State *L) {
return _file_info_ (L, STAT_FUNC);
}
@@ -1063,63 +854,42 @@ static int file_info(lua_State * L)
** Returns 1 if successful (with the target on top of the stack),
** 0 on failure (with stack unchanged, and errno set).
*/
static int push_link_target(lua_State * L)
{
const char *file = luaL_checkstring(L, 1);
static int push_link_target(lua_State *L) {
#ifdef _WIN32
HANDLE h = CreateFile(file, GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (h == INVALID_HANDLE_VALUE) {
return lfs_win32_pusherror(L);
}
#endif
errno = ENOSYS;
return 0;
#else
const char *file = luaL_checkstring(L, 1);
char *target = NULL;
int tsize, size = 256; /* size = initial buffer capacity */
int ok = 0;
while (!ok) {
while (1) {
char* target2 = realloc(target, size);
if (!target2) { /* failed to allocate */
break;
free(target);
return 0;
}
target = target2;
#ifdef _WIN32
tsize = GetFinalPathNameByHandle(h, target, size, FILE_NAME_OPENED);
#else
tsize = readlink(file, target, size);
#endif
if (tsize < 0) { /* a readlink() error occurred */
free(target);
return 0;
}
if (tsize < size)
break;
}
if (tsize < size) {
#ifdef _WIN32
if (tsize > 4 && strncmp(target, "\\\\?\\", 4) == 0) {
memmove_s(target, tsize - 3, target + 4, tsize - 3);
tsize -= 4;
}
#endif
ok = 1;
break;
}
/* possibly truncated readlink() result, double size and retry */
size *= 2;
}
if (ok) {
target[tsize] = '\0';
lua_pushlstring(L, target, tsize);
}
#ifdef _WIN32
CloseHandle(h);
#endif
free(target);
return ok;
return 1;
#endif
}
/*
** Get symbolic link information using lstat.
*/
static int link_info(lua_State * L)
{
static int link_info (lua_State *L) {
int ret;
if (lua_isstring (L, 2) && (strcmp(lua_tostring(L, 2), "target") == 0)) {
int ok = push_link_target(L);
@@ -1139,14 +909,10 @@ static int link_info(lua_State * L)
/*
** Assumes the table is on top of the stack.
*/
static void set_info(lua_State * L)
{
static void set_info (lua_State *L) {
lua_pushliteral(L, "Copyright (C) 2003-2017 Kepler Project");
lua_setfield(L, -2, "_COPYRIGHT");
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_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_setfield(L, -2, "_DESCRIPTION");
lua_pushliteral(L, "LuaFileSystem " LFS_VERSION);
lua_setfield(L, -2, "_VERSION");
@@ -1170,8 +936,7 @@ static const struct luaL_Reg fslib[] = {
{NULL, NULL},
};
LFS_EXPORT int luaopen_lfs(lua_State * L)
{
LFS_EXPORT int luaopen_lfs (lua_State *L) {
dir_create_meta (L);
lock_create_meta (L);
new_lib (L, fslib);

View File

@@ -1,4 +1,4 @@
LIBRARY lfs.dll
VERSION 1.8
VERSION 1.7
EXPORTS
luaopen_lfs

View File

@@ -1,7 +1,6 @@
/*
** LuaFileSystem
** Copyright Kepler Project 2003 - 2020
** (http://keplerproject.github.io/luafilesystem)
** Copyright Kepler Project 2003 - 2017 (http://keplerproject.github.io/luafilesystem)
*/
/* Define 'chdir' for systems that do not implement it */

View File

@@ -4,8 +4,6 @@ local tmp = "/tmp"
local sep = string.match (package.config, "[^\n]+")
local upper = ".."
local is_unix = package.config:sub(1,1) == "/"
local lfs = require"lfs"
print (lfs._VERSION)
@@ -62,8 +60,6 @@ if not attrib then
error ("could not get attributes of file `"..tmpdir.."':\n"..errmsg)
end
local f = io.open(tmpfile, "w")
local data = "hello, file!"
f:write(data)
f:close()
io.write(".")
@@ -91,42 +87,14 @@ assert (new_att.modification == testdate1, "could not set modification time")
io.write(".")
io.flush()
-- Checking link (does not work on Windows)
if lfs.link (tmpfile, "_a_link_for_test_", true) then
assert (lfs.attributes"_a_link_for_test_".mode == "file")
assert (lfs.symlinkattributes"_a_link_for_test_".mode == "link")
assert (lfs.symlinkattributes"_a_link_for_test_".target == tmpfile)
assert (lfs.symlinkattributes("_a_link_for_test_", "target") == tmpfile)
assert (lfs.symlinkattributes(tmpfile).mode == "file")
assert (lfs.link (tmpfile, "_a_hard_link_for_test_"))
assert (lfs.symlinkattributes"_a_hard_link_for_test_".mode == "file")
local fd = io.open(tmpfile)
assert(fd:read("*a") == data)
fd:close()
fd = io.open("_a_link_for_test_")
assert(fd:read("*a") == data)
fd:close()
fd = io.open("_a_hard_link_for_test_")
assert(fd:read("*a") == data)
fd:close()
fd = io.open("_a_hard_link_for_test_", "w+")
local data2 = "write in hard link"
fd:write(data2)
fd:close()
fd = io.open(tmpfile)
assert(fd:read("*a") == data2)
fd:close()
if is_unix then
assert (lfs.attributes (tmpfile, "nlink") == 2)
end
assert (os.remove"_a_link_for_test_")
assert (os.remove"_a_hard_link_for_test_")
end