From 985b0b2f5a4034eb72411516ae0e47a1077cb6aa Mon Sep 17 00:00:00 2001 From: Cosmin Apreutesei Date: Mon, 24 Sep 2018 18:53:31 +0300 Subject: [PATCH] unimportant --- bundle.lua | 178 +++++++++++++++++++++++++++++--------------------- bundle_fs.lua | 66 +++++++++++++++++++ 2 files changed, 168 insertions(+), 76 deletions(-) create mode 100644 bundle_fs.lua diff --git a/bundle.lua b/bundle.lua index 7d2dcbd..1494fbb 100644 --- a/bundle.lua +++ b/bundle.lua @@ -12,6 +12,8 @@ local bundle = {} local dir = arg[0]:gsub('[/\\]?[^/\\]+$', '') or '' --remove file name dir = dir == '' and '.' or dir +--reading embedded blobs + local function getsym(sym) return ffi.C[sym] end @@ -19,7 +21,7 @@ local function blob_data(file) local sym = BBIN_PREFIX..file:gsub('[\\%-/%.]', '_') pcall(ffi.cdef, 'void '..sym..'()') local ok, p = pcall(getsym, sym) - if not ok then return end + if not ok then return nil end local p = ffi.cast('const uint32_t*', p) return ffi.cast('void*', p+1), p[0] end @@ -34,23 +36,108 @@ local function mmap_blob(file) return data and {data = data, size = size, close = function() end} end -function bundle.canopen(file) - local f = io.open(file, 'r') - if f then - f:close() - return true - end +local function canopen_blob(file) return blob_data(file) and true or false end +local function fs_open_blob(file) + local fs = require'fs' + local buf, sz = blob_data(file) + if not buf then return nil end + return fs.open_buffer(buf, sz) +end + +function bundle.open_dir_listing(dir, s) + local path = require'path' + local entries = s and assert(loadstring(s))() + local d = {} + local closed, name, ftype + local i = 1 + function d:next() + if closed then + return nil + end + if not entries then + closed = true + return false, 'not_found' + end + name = entries[i] + if not name then + closed = true + return nil + end + i = i + 1 + name, ftype = name:match'^(.-)([/]?)$' + if ftype == '/' then + ftype = 'dir' + else + ftype = 'file' + end + return name, d + end + function d:close() closed = true; return true; end + function d:closed() return closed end + function d:name() return name end + function d:dir() return dir end + function d:path() return path.combine(dir, name) end + function d:attr(attr) + if attr == 'type' then + return ftype + elseif not attr then + return {type = ftype} + else + return nil + end + end + function d:is(ftype1) return ftype == ftype1 end + return d.next, d +end + +local function fs_dir_blob(dir) + local fs = require'fs' + return bundle.open_dir_listing(dir, load_blob(dir)) +end + +--reading the filesystem + local function load_file(file) file = dir..'/'..file local f = io.open(file, 'rb') - if f then - local s = f:read'*a' - f:close() - return s - end + if not f then return nil end + local s = f:read'*a' + f:close() + return s +end + +local function mmap_file(file) + local s = load_file(file) + if not s then return end + --TODO: use fs.mmap() here + return {data = ffi.cast('const void*', s), size = #s, + close = function() local _ = s; end} +end + +local function canopen_file(file) + local f = io.open(file, 'r') + if f then f:close() end + return f and true or false +end + +function fs_open_file(file) + local fs = require'fs' + return (fs.open(file)) +end + +function fs_dir_file(dir) + local fs = require'fs' + if not fs.is(dir, 'dir') then return nil end + return fs.dir(dir) +end + +--user API + +function bundle.canopen(file) + return canopen_file(file) or canopen_blob(file) end function bundle.load(file) @@ -58,76 +145,15 @@ function bundle.load(file) end function bundle.mmap(file) - local s = load_file(file) - if s then - --TODO: use fs.mmap() here - return {data = ffi.cast('const void*', s), size = #s, - close = function() local _ = s; end} - else - return mmap_blob(file) - end + return mmap_file(file) or mmap_blob(file) end function bundle.fs_open(file) - local fs = require'fs' - local buf, sz = blob_data(file) - if not buf then - return fs.open(file) - else - return fs.open_buffer(buf, sz) - end + return fs_open_file(file) or fs_open_blob(file) end function bundle.fs_dir(dir) - local fs = require'fs' - local path = require'path' - if fs.is(dir, 'dir') then - return fs.dir(dir) - else - local s = load_blob(dir) - local entries = s and assert(loadstring(s))() - local d = {} - local closed, name, ftype - local i = 1 - function d:next() - if closed then - return nil - end - if not entries then - closed = true - return false, 'not_found' - end - name = entries[i] - if not name then - closed = true - return nil - end - i = i + 1 - name, ftype = name:match'^(.-)([/]?)$' - if ftype == '/' then - ftype = 'dir' - else - ftype = 'file' - end - return name, d - end - function d:close() closed = true; return true; end - function d:closed() return closed end - function d:name() return name end - function d:dir() return dir end - function d:path() return path.combine(dir, name) end - function d:attr(attr) - if attr == 'type' then - return ftype - elseif not attr then - return {type = ftype} - else - return nil - end - end - function d:is(ftype1) return ftype == ftype1 end - return d.next, d - end + return fs_dir_file(dir) or fs_dir_blob(dir) end local ok, ver = pcall(require, 'bundle_appversion') diff --git a/bundle_fs.lua b/bundle_fs.lua new file mode 100644 index 0000000..87f9be0 --- /dev/null +++ b/bundle_fs.lua @@ -0,0 +1,66 @@ + +--fs.dir() and fs.open() interfaces over mmapped tar-like files. +--Written by Cosmin Apreutesei. Public Domain. + +local ffi = require'ffi' +local fs = require'fs' +local bundle = require'bundle' + +local rat = {} + +function rat:build(dir, write) + --TODO: +end + +function rat:build_tofile(dir, file) + local f, err, errcode = fs.open(file, 'w') + if not f then + return nil, err, errcode + end + local function write(buf, sz) + return f:write(buf, sz) + end + local ok, err, errcode = rat:build(write) + f:close() + return ok, err, errcode +end + +local mountpoint = {} + +function rat:mount(buf, sz) + local mountpoint = { + data = ffi.cast('char*', buf), + size = sz, + _buffer = buf, --anchor it + __index = mountpoint, + } + local self = setmetatable(mountpoint, mountpoint) + self:init() + return self +end + +function mountpoint:find_entry(path) + --TODO: + local ftype, offset, size + return ftype, offset, size +end + +function mountpoint:init() + --TODO: +end + +function mountpoint:dir(dir) + local ftype, offset, size = self:find_entry(dir) + local entries + local s = ftype == 'dir' and ffi.string(self.data + offset, size) + return bundle.open_dir_listing(dir, s) +end + +function mountpoint:open(path, mode) + local ftype, offset, size = self:find_entry(path) + if not ftype then return nil, 'not_found' end + if ftype ~= 'file' then return nil, 'access_denied' end + return fs.open_buffer(self.data + offset, size) +end + +return rat