如何使用ffi.C.lstat?

时间:2014-04-25 07:27:06

标签: nginx lua ffi

我想在我的ngx_lua程序中使用lstat函数获取文件的基本信息。 init.lua的内容为休闲:

local ffi = require "ffi"
local ffi_C = ffi.C
local ffi_new = ffi.new

ffi.cdef[[
    typedef long long time_t;
    typedef struct timespec {
        time_t  tv_sec;
        long    tv_nsec;
        ...;
    };
    typedef struct stat {
        struct timespec st_mtim;
        ...;
    };

    int lstat(const char *path, struct stat *buf);
]]

buf = ffi_new("struct stat *")

function checkfile (filename, buf)
    ffi_C.lstat(filename, buf)
end

当我启动我的nginx时,会发生一些错误。内容如下:

  • 2014/04/25 15:00:39 [错误] 26396#0:lua入口线程中止: 运行时错误:/home/nginx/conf/cop/init.lua:42: /usr/local/lib/libluajit-5.1.so.2:未定义的符号:lstat    堆栈追溯:    协程0:            [C]:在函数' __ index'            /home/nginx/conf/cop/init.lua:42:在函数' checkfile'            /home/nginx/conf/cop/check1.lua:37:在函数中,上下文:ngx.timer

2 个答案:

答案 0 :(得分:0)

buf = ffi_new("struct stat *")struct stat对象创建一个新的指针;它没有分配实际的struct stat实例。您想要ffi_new("struct stat")

在尝试使用FFI之前,请确保您熟悉C的内存模型,因为使用LuaJIT的FFI基本上是用C语言编写的。它不会保护您免受解除引用NULL等等。

此外,buf是一个全球性的,您可能不想要。请务必将其local

答案 1 :(得分:0)

除了上面那些类型的问题,还有一个更乏味的问题: 使用glibc,stat()和friends(lstat(),fstat(),...)通常是解析为__xstat()等的宏。

__ xstat()需要3个args,第一个指定你想要哪个版本的struct stat作为缓冲区,但布局似乎非常依赖于libc版本。

(例如在c and LD_PRELOAD. open and open64 calls intercepted, but not stat64中提到)

为luaJIT的FFI解决这个问题,使用stat的数量(即arm32和x86_64上的106)发出syscall()似乎是最可靠的,并从内核获取struct stat定义(相同的x86和arm32,x86_64不同。

您还可以使用我没有尝试的ljsyscall(https://github.com/justincormack/ljsyscall)。