forked from enlightenment/efl
400 lines
12 KiB
Lua
400 lines
12 KiB
Lua
-- EFL LuaJIT bindings: Eina (file module)
|
|
-- For use with Elua
|
|
|
|
local ffi = require("ffi")
|
|
local C = ffi.C
|
|
|
|
local iterator = require("eina.iterator")
|
|
require("eina.xattr")
|
|
|
|
ffi.cdef [[
|
|
typedef unsigned char Eina_Bool;
|
|
typedef long time_t;
|
|
|
|
typedef struct _Eina_File_Direct_Info Eina_File_Direct_Info;
|
|
typedef struct _Eina_Stat Eina_Stat;
|
|
typedef struct _Eina_File_Line Eina_File_Line;
|
|
|
|
typedef void (*Eina_File_Dir_List_Cb)(const char *name, const char *path,
|
|
void *data);
|
|
|
|
typedef Eina_Bool (*Eina_File_Copy_Progress)(void *data,
|
|
unsigned long long done, unsigned long long total);
|
|
|
|
typedef enum {
|
|
EINA_FILE_UNKNOWN,
|
|
EINA_FILE_FIFO,
|
|
EINA_FILE_CHR,
|
|
EINA_FILE_DIR,
|
|
EINA_FILE_BLK,
|
|
EINA_FILE_REG,
|
|
EINA_FILE_LNK,
|
|
EINA_FILE_SOCK,
|
|
EINA_FILE_WHT
|
|
} Eina_File_Type;
|
|
|
|
typedef struct _Eina_File Eina_File;
|
|
|
|
typedef enum {
|
|
EINA_FILE_RANDOM,
|
|
EINA_FILE_SEQUENTIAL,
|
|
EINA_FILE_WILLNEED,
|
|
EINA_FILE_POPULATE,
|
|
EINA_FILE_DONTNEED,
|
|
EINA_FILE_REMOVE
|
|
} Eina_File_Populate;
|
|
|
|
struct _Eina_File_Direct_Info {
|
|
size_t path_length;
|
|
size_t name_length;
|
|
size_t name_start;
|
|
Eina_File_Type type;
|
|
char path[8192];
|
|
};
|
|
|
|
struct _Eina_Stat {
|
|
unsigned long int dev;
|
|
unsigned long int ino;
|
|
unsigned int mode;
|
|
unsigned int nlink;
|
|
unsigned int uid;
|
|
unsigned int gid;
|
|
unsigned long int rdev;
|
|
unsigned long int size;
|
|
unsigned long int blksize;
|
|
unsigned long int blocks;
|
|
unsigned long int atime;
|
|
unsigned long int atimensec;
|
|
unsigned long int mtime;
|
|
unsigned long int mtimensec;
|
|
unsigned long int ctime;
|
|
unsigned long int ctimensec;
|
|
};
|
|
|
|
struct _Eina_File_Line {
|
|
const char *start;
|
|
const char *end;
|
|
unsigned int index;
|
|
unsigned long long length;
|
|
};
|
|
|
|
Eina_Bool eina_file_dir_list(const char *dir, Eina_Bool recursive,
|
|
Eina_File_Dir_List_Cb cb, void *data);
|
|
Eina_Iterator *eina_file_ls(const char *dir);
|
|
Eina_Iterator *eina_file_stat_ls(const char *dir);
|
|
int eina_file_statat(void *container, Eina_File_Direct_Info *info,
|
|
Eina_Stat *buf);
|
|
Eina_Iterator *eina_file_direct_ls(const char *dir);
|
|
char *eina_file_path_sanitize(const char *path);
|
|
|
|
typedef enum {
|
|
EINA_FILE_COPY_DATA = 0,
|
|
EINA_FILE_COPY_PERMISSION = (1 << 0),
|
|
EINA_FILE_COPY_XATTR = (1 << 1)
|
|
} Eina_File_Copy_Flags;
|
|
|
|
Eina_Bool eina_file_copy(const char *src, const char *dst,
|
|
Eina_File_Copy_Flags flags, Eina_File_Copy_Progress cb,
|
|
const void *cb_data);
|
|
Eina_File *eina_file_open(const char *name, Eina_Bool shared);
|
|
Eina_Bool eina_file_unlink(const char *pathname);
|
|
Eina_File *eina_file_virtualize(const char *virtual_name,
|
|
const void *data, unsigned long long length, Eina_Bool copy);
|
|
Eina_Bool eina_file_virtual(Eina_File *file);
|
|
Eina_Bool eina_file_refresh(Eina_File *file);
|
|
Eina_File *eina_file_dup(const Eina_File *file);
|
|
void eina_file_close(Eina_File *file);
|
|
size_t eina_file_size_get(const Eina_File *file);
|
|
time_t eina_file_mtime_get(const Eina_File *file);
|
|
const char *eina_file_filename_get(const Eina_File *file);
|
|
Eina_Iterator *eina_file_xattr_get(Eina_File *file);
|
|
Eina_Iterator *eina_file_xattr_value_get(Eina_File *file);
|
|
void *eina_file_map_all(Eina_File *file, Eina_File_Populate rule);
|
|
void *eina_file_map_new(Eina_File *file, Eina_File_Populate rule,
|
|
unsigned long int offset, unsigned long int length);
|
|
void eina_file_map_free(Eina_File *file, void *map);
|
|
void eina_file_map_populate(Eina_File *file, Eina_File_Populate rule,
|
|
const void *map, unsigned long int offset, unsigned long int length);
|
|
Eina_Iterator *eina_file_map_lines(Eina_File *file);
|
|
Eina_Bool eina_file_map_faulted(Eina_File *file, void *map);
|
|
|
|
void eina_stringshare_del (const char *str);
|
|
int eina_stringshare_strlen(const char *str);
|
|
|
|
char *strerror(int);
|
|
void free(void*);
|
|
]]
|
|
|
|
local cutil = require("cutil")
|
|
local util = require("util")
|
|
|
|
local Object = util.Object
|
|
|
|
local M = {}
|
|
|
|
local eina
|
|
|
|
local init = function()
|
|
eina = util.lib_load("eina")
|
|
end
|
|
|
|
local shutdown = function()
|
|
util.lib_unload("eina")
|
|
end
|
|
|
|
cutil.init_module(init, shutdown)
|
|
|
|
M.dir_list = function(dir, recursive, cb)
|
|
if not cb or not dir then return false end
|
|
local cbp = ffi.cast("Eina_File_Dir_List_Cb", function(name, path, data)
|
|
return cb(name, path)
|
|
end)
|
|
local v = eina.eina_file_dir_list(dir, recursive or false, cbp, nil)
|
|
cbp:free()
|
|
return v ~= 0
|
|
end
|
|
|
|
local Iterator = iterator.Iterator
|
|
|
|
local Ls_Iterator = Iterator:clone {
|
|
__ctor = function(self, selfmt, dir)
|
|
return Iterator.__ctor(self, selfmt, eina.eina_file_ls(dir))
|
|
end,
|
|
|
|
next = function(self)
|
|
local v = Iterator.next(self)
|
|
if not v then return nil end
|
|
local r = ffi.string(v, eina.eina_stringshare_strlen(v))
|
|
eina.eina_stringshare_del(v)
|
|
return r
|
|
end
|
|
}
|
|
|
|
M.ls = function(dir) return Ls_Iterator(dir) end
|
|
|
|
local file_type_map = {
|
|
[C.EINA_FILE_UNKNOWN] = "unknown",
|
|
[C.EINA_FILE_FIFO] = "fifo",
|
|
[C.EINA_FILE_CHR] = "chr",
|
|
[C.EINA_FILE_DIR] = "dir",
|
|
[C.EINA_FILE_BLK] = "blk",
|
|
[C.EINA_FILE_REG] = "reg",
|
|
[C.EINA_FILE_LNK] = "lnk",
|
|
[C.EINA_FILE_SOCK] = "sock",
|
|
[C.EINA_FILE_WHT] = "wht",
|
|
}
|
|
|
|
local Direct_Info = Object:clone {
|
|
__ctor = function(self, path, name_start, name_length, tp)
|
|
self.path = path
|
|
self.name_start = name_start
|
|
self.name_length = name_length
|
|
self.type = tp
|
|
end,
|
|
|
|
statat = function(self, container)
|
|
if not container then return false, "invalid container" end
|
|
local info = ffi.new("Eina_File_Direct_Info", #self.path,
|
|
self.name_length, self.name_start - 1,
|
|
C["EINA_FILE_" .. self.type:upper()], self.path)
|
|
local buf = ffi.new("Eina_Stat")
|
|
if eina.eina_file_statat(container, info, buf) ~= 0 then
|
|
return false, ffi.string(C.strerror(ffi.errno()))
|
|
end
|
|
return buf
|
|
end
|
|
}
|
|
|
|
local direct_info_iterator_next = function(self)
|
|
local v = Iterator.next(self)
|
|
if not v then return nil end
|
|
local s = ffi.cast("Eina_File_Direct_Info*", v)
|
|
local path = ffi.string(s.path, s.path_length)
|
|
local ns = tonumber(s.name_start)
|
|
local nl = tonumber(s.name_length)
|
|
local tp = file_type_map[s.type]
|
|
return Direct_Info(path, ns, nl, tp), self:container_get()
|
|
end
|
|
|
|
local Stat_Ls_Iterator = Iterator:clone {
|
|
__ctor = function(self, selfmt, dir)
|
|
return Iterator.__ctor(self, selfmt, eina.eina_file_stat_ls(dir))
|
|
end,
|
|
next = direct_info_iterator_next
|
|
}
|
|
|
|
M.stat_ls = function(dir) return Stat_Ls_Iterator(dir) end
|
|
|
|
local Direct_Ls_Iterator = Iterator:clone {
|
|
__ctor = function(self, selfmt, dir)
|
|
return Iterator.__ctor(self, selfmt, eina.eina_file_direct_ls(dir))
|
|
end,
|
|
next = direct_info_iterator_next
|
|
}
|
|
|
|
M.direct_ls = function(dir) return Direct_Ls_Iterator(dir) end
|
|
|
|
M.path_sanitize = function(path)
|
|
local v = eina.eina_file_path_sanitize(path)
|
|
if v == ffi.nullptr then return nil end
|
|
local r = ffi.string(v)
|
|
C.free(v)
|
|
return r
|
|
end
|
|
|
|
M.copy_flags = {
|
|
DATA = 0, PERMISION = 1, XATTR = 2
|
|
}
|
|
|
|
M.copy = function(source, destination, flags, cb)
|
|
if not source or not destination then return false end
|
|
flags = flags or 0
|
|
local cbp
|
|
if cb then
|
|
cbp = ffi.cast("Eina_File_Copy_Progress", function(data, done, total)
|
|
return not not cb(done, total)
|
|
end)
|
|
end
|
|
local v = eina.eina_file_copy(source, destination, flags, cbp, nil)
|
|
if cbp then cbp:free() end
|
|
return v ~= 0
|
|
end
|
|
|
|
local Xattr_Iterator = Iterator:clone {
|
|
__ctor = function(self, selfmt, file)
|
|
return Iterator.__ctor(self, selfmt, eina.eina_file_xattr_get(file))
|
|
end,
|
|
next = function(self)
|
|
local v = Iterator.next(self)
|
|
if not v then return nil end
|
|
return ffi.string(v)
|
|
end
|
|
}
|
|
|
|
local Xattr_Value_Iterator = Iterator:clone {
|
|
__ctor = function(self, selfmt, file)
|
|
return Iterator.__ctor(self, selfmt,
|
|
eina.eina_file_xattr_value_get(file))
|
|
end,
|
|
next = function(self)
|
|
local v = Iterator.next(self)
|
|
if not v then return nil end
|
|
v = ffi.cast(v, "Eina_Xattr*")
|
|
return ffi.string(v.name), ffi.string(v.value, v.length)
|
|
end
|
|
}
|
|
|
|
M.populate = {
|
|
RANDOM = 0,
|
|
SEQUENTIAL = 1,
|
|
WILLNEED = 2,
|
|
POPULATE = 3,
|
|
DONTNEED = 4,
|
|
REMOVE = 5
|
|
}
|
|
|
|
local Line_Iterator = Iterator:clone {
|
|
__ctor = function(self, selfmt, file)
|
|
return Iterator.__ctor(self, selfmt, eina.eina_file_map_lines(file))
|
|
end,
|
|
next = function(self)
|
|
local v = Iterator.next(self)
|
|
if not v then return nil end
|
|
v = ffi.cast(v, "Eina_File_Line*")
|
|
return ffi.string(v.start, v.length), tonumber(v.index)
|
|
end
|
|
}
|
|
|
|
M.File = ffi.metatype("Eina_File", {
|
|
__new = function(self, name, shared)
|
|
return self.open(name, shared)
|
|
end,
|
|
__len = function(self)
|
|
return self:size_get()
|
|
end,
|
|
__index = {
|
|
open = function(name, shared)
|
|
return eina.eina_file_open(name, shared)
|
|
end,
|
|
|
|
unlink = function(self)
|
|
return eina.eina_file_unlink(pathname)
|
|
end,
|
|
|
|
virtualize = function(vname, data, length, copy)
|
|
return eina.eina_file_virtualize(vname, data, length,
|
|
copy or false)
|
|
end,
|
|
|
|
close = function(self)
|
|
return eina.eina_file_close(self)
|
|
end,
|
|
|
|
dup = function(self)
|
|
return eina.eina_file_dup(self)
|
|
end,
|
|
|
|
is_virtual = function(self)
|
|
return eina.eina_file_virtual(self) ~= 0
|
|
end,
|
|
refresh = function(self)
|
|
return eina.eina_file_refresh(self) ~= 0
|
|
end,
|
|
|
|
size_get = function(self)
|
|
return tonumber(eina.eina_file_size_get(self))
|
|
end,
|
|
|
|
mtime_get = function(self)
|
|
return tonumber(eina.eina_file_mtime_get(self))
|
|
end,
|
|
|
|
filename_get = function(self)
|
|
return ffi.string(eina.eina_file_filename_get(self))
|
|
end,
|
|
|
|
xattr_get = function(self) return Xattr_Iterator(self) end,
|
|
xattr_value_get = function(self) Xattr_Value_Iterator(self) end,
|
|
|
|
map_all = function(self, rule, raw)
|
|
local v = ffi.cast("char*", eina.eina_file_map_all(self, rule or 0))
|
|
if v == ffi.nullptr then return nil end
|
|
if not raw then
|
|
local r = ffi.string(v)
|
|
self:map_free(v)
|
|
return r
|
|
end
|
|
return v
|
|
end,
|
|
|
|
map_new = function(self, rule, offset, length, raw)
|
|
local v = ffi.cast("char*", eina.eina_file_map_new(self, rule or 0,
|
|
offset or 0, length))
|
|
if v == ffi.nullptr then return nil end
|
|
if not raw then
|
|
local r = ffi.string(v, length)
|
|
self:map_free(v)
|
|
return r
|
|
end
|
|
return v
|
|
end,
|
|
|
|
map_free = function(self, map)
|
|
return eina.eina_file_map_free(self, map)
|
|
end,
|
|
|
|
map_populate = function(self, rule, map, offset, length)
|
|
return eina.eina_file_map_populate(self, rule or 0, offset or 0,
|
|
length)
|
|
end,
|
|
|
|
map_faulted = function(self, map)
|
|
return eina.eina_file_map_faulted(self, map) ~= 0
|
|
end,
|
|
|
|
lines = function(self) return Line_Iterator(self) end
|
|
}
|
|
})
|
|
|
|
return M
|