LuajLFS is a port of the C based LuaFileSystem library to luaj.
LuajLFS tries to use the same OS syscalls that C based LuaFileSystem uses whenever possible. On supported operating systems compatibility should be very high.
For more information on LuaFileSystem and a documentation of the Lua API see: https://github.com/keplerproject/luafilesystem/
LuajLFS is released under the GNU Lesser General Public License Version 3.
A copy of the GNU Lesser General Public License Version 3 can be found in the COPYING & COPYING.LESSER files.
- Java 7 or newer
- LuaJ 3.0.1
Maven:
<dependency>
<groupId>io.github.alexanderschuetz97</groupId>
<artifactId>LuajLFS</artifactId>
<version>1.3</version>
</dependency>
In Java:
Globals globals = JsePlatform.standardGlobals();
globals.load(new LuajLFSLib());
//.... (Standart LuaJ from this point)
globals.load(new InputStreamReader(new FileInputStream("test.lua")), "test.lua").call();
In test.lua:
local lfs = require('lfs')
for file in lfs.dir(".") do
print(file)
end
LuajLFS uses LuajFSHook to access the filesystem. (see https://github.com/AlexanderSchuetz97/LuajFSHook)
TLDR:
If LuajFSHook is not loaded prior to calling 'globals.load(new LuajLFSLib())' then
LuajLFS will load LuajFSHook and this will overwrite the io table and some entries in the os table.
If you use a custom IOLib or custom os functions you will have to load LuajFSHook before loading your libraries.
Since LuaJ supports running multiple concurrent Lua environments that should NOT affect each other calling the native methods "chdir" or "SetCurrentDirectory" would break this principle since all Lua Environments would affect each other's work directory. Not to mention that this is heavily discouraged by the JVM specification. To solve this the work directory is purely virtual and tracked inside a variable in java. This means if Lua changes the work directory and calls a Java method (via luajava for example) that then does new File(".") then said File Object would not be in the work directory that lua set, but rather in the work directory that the entire JVM uses. Same goes for any calls made to C based JNI libraries.
If you have any other JavaLib that relies on relative paths consider using LuajFSHook to resolve paths and modify/get the work directory.
As mentioned before LuaJ allows for multiple concurrent Lua Environments. Unfortunately the OS/JVM that manages FileLocks is unaware of this and will assign the locks to the JVM Process. This means all locks on files are always shared between all Lua Environments running in the same JVM Process.
C based LuaFileSystem uses the _locking syscall to lock files. (lua method: lfs.lock) Unfortunately windows has 2 different methods of interacting with files: HANDLE's and FD's. C based lua uses FD's and the JVM (tested with OpenJDK 8) uses HANDLES's. The syscalls to lock a file are different and behave different:
- _locking uses FD's
- LockFileEx + UnlockFileEx uses HANDLE's
LuajLFS will detect which way the JVM uses to implement the RandomAccessFile and will use the appropriate syscall to lock the file depending on the JVM implementation. Due to this, the methods may not behave identical to C based LuaFileSystem depending on how the JVM implemented RandomAccessFile. The main difference is that _locking allows the user to place a lock above a lock already owned by the process replacing the old lock with a new lock. LockFileEx does not permit this.
By default LuajLFS has 3 different modes of operation:
- Windows mode Vista and newer (amd64 & i386)
- Linux mode (amd64 & i386 & armhf & aarch64)
- Unsupported OS mode
For more information in regard to which GLIBC version is required for Linux mode see: https://github.com/AlexanderSchuetz97/JavaNativeUtils
If for some reason your system does not meet the requirements for Linux or Windows mode LuajLFS will automatically fall back to Unsupported OS mode.
In Windows and Linux mode LuajLFS should behave nearly identical to C based LuaFileSystem. (Some error messages & codes in some corner cases may be different since I was not able to reproduce them, this holds especially true for Windows)
In Unsupported OS mode the method lfs.lock file uses the java.nio.FileLock mechanism to lock files rather than OS syscalls. Any locks obtained by this mechanism will not be visible by non-Java applications. This means that if you run LuajLFS on for example Mac and want to obtain a lock on a file then this lock will not be "visible" to a non-Java application (such as for example a C based Lua script locking the same file using C Based LuaFileSystem)
In Unsupported OS mode the methods lfs.attributes and lfs.symlinkattributes will return only the information which is available by using the JSE Standard operations. Check java.nio.file.attribute.BasicFileAttributes for more info. Any other information is set to 0 or an appropriate default value.