Skip to content
Permalink
Browse files

fs, feat: support custom zip fs.

  • Loading branch information...
xicilion committed Jul 9, 2018
1 parent bd3a4b8 commit 70c117a6929344d775995ebccdf4e6af93884d5c
Showing with 135 additions and 6 deletions.
  1. +36 −1 fibjs/include/ifs/fs.h
  2. +55 −0 fibjs/src/fs/fs.cpp
  3. +9 −3 idl/zh-cn/fs.idl
  4. +35 −2 test/fs_test.js
@@ -68,6 +68,8 @@ class fs_base : public object_base {
static result_t writeTextFile(exlib::string fname, exlib::string txt, AsyncEvent* ac);
static result_t writeFile(exlib::string fname, Buffer_base* data, AsyncEvent* ac);
static result_t appendFile(exlib::string fname, Buffer_base* data, AsyncEvent* ac);
static result_t setZipFS(exlib::string fname, Buffer_base* data);
static result_t clearZipFS(exlib::string fname);

public:
static void s__new(const v8::FunctionCallbackInfo<v8::Value>& args)
@@ -116,6 +118,8 @@ class fs_base : public object_base {
static void s_writeTextFile(const v8::FunctionCallbackInfo<v8::Value>& args);
static void s_writeFile(const v8::FunctionCallbackInfo<v8::Value>& args);
static void s_appendFile(const v8::FunctionCallbackInfo<v8::Value>& args);
static void s_setZipFS(const v8::FunctionCallbackInfo<v8::Value>& args);
static void s_clearZipFS(const v8::FunctionCallbackInfo<v8::Value>& args);

public:
ASYNC_STATICVALUE2(fs_base, exists, exlib::string, bool);
@@ -229,7 +233,9 @@ inline ClassInfo& fs_base::class_info()
{ "writeFile", s_writeFile, true },
{ "writeFileSync", s_writeFile, true },
{ "appendFile", s_appendFile, true },
{ "appendFileSync", s_appendFile, true }
{ "appendFileSync", s_appendFile, true },
{ "setZipFS", s_setZipFS, true },
{ "clearZipFS", s_clearZipFS, true }
};

static ClassData::ClassProperty s_property[] = {
@@ -927,6 +933,35 @@ inline void fs_base::s_appendFile(const v8::FunctionCallbackInfo<v8::Value>& arg

METHOD_VOID();
}

inline void fs_base::s_setZipFS(const v8::FunctionCallbackInfo<v8::Value>& args)
{
METHOD_NAME("fs.setZipFS");
METHOD_ENTER();

METHOD_OVER(2, 2);

ARG(exlib::string, 0);
ARG(obj_ptr<Buffer_base>, 1);

hr = setZipFS(v0, v1);

METHOD_VOID();
}

inline void fs_base::s_clearZipFS(const v8::FunctionCallbackInfo<v8::Value>& args)
{
METHOD_NAME("fs.clearZipFS");
METHOD_ENTER();

METHOD_OVER(1, 0);

OPT_ARG(exlib::string, 0, "");

hr = clearZipFS(v0);

METHOD_VOID();
}
}

#endif
@@ -36,6 +36,61 @@ class cache_node : public obj_base {
static std::list<obj_ptr<cache_node>> s_cache;
static exlib::spinlock s_cachelock;

result_t fs_base::setZipFS(exlib::string fname, Buffer_base* data)
{
result_t hr;
std::list<obj_ptr<cache_node>>::iterator it;
obj_ptr<ZipFile_base> zfile;
obj_ptr<cache_node> _node;

hr = zip_base::cc_open(data, "r", zip_base::_ZIP_DEFLATED, zfile);
if (hr < 0)
return hr;

obj_ptr<NArray> list;
hr = zfile->cc_readAll("", list);
if (hr < 0)
return hr;

_node = new cache_node();
_node->m_name = fname;
_node->m_list = list;
_node->m_date = INFINITY;
_node->m_mtime.now();

s_cachelock.lock();
for (it = s_cache.begin(); it != s_cache.end(); ++it)
if ((*it)->m_name == fname) {
*it = _node;
break;
}
if (it == s_cache.end())
s_cache.push_back(_node);
s_cachelock.unlock();
return 0;
}

result_t fs_base::clearZipFS(exlib::string fname)
{
if (fname.empty()) {
s_cachelock.lock();
s_cache.clear();
s_cachelock.unlock();
} else {
std::list<obj_ptr<cache_node>>::iterator it;

s_cachelock.lock();
for (it = s_cache.begin(); it != s_cache.end(); ++it)
if ((*it)->m_name == fname) {
s_cache.erase(it);
break;
}
s_cachelock.unlock();
}

return 0;
}

result_t fs_base::openFile(exlib::string fname, exlib::string flags,
obj_ptr<SeekableStream_base>& retVal, AsyncEvent* ac)
{
@@ -257,8 +257,14 @@ module fs
*/
static appendFile(String fname, Buffer data) async;

/*! @brief 创建二进制文件,并写入内容,是 appendFile 的同步版兼容接口
@param fname 指定文件名
@param data 指定要写入的二进制数据
/*! @brief 设置 zip 虚拟文件映射
@param fname 指定映射路径
@param data 指定映射的 zip 文件数据
*/
static setZipFS(String fname, Buffer data);

/*! @brief 清除 zip 虚拟文件映射
@param fname 指定映射路径,缺省清除全部缓存
*/
static clearZipFS(String fname = "");
};
@@ -3,6 +3,7 @@ var coroutine = require('coroutine');
var path = require('path');
var fs = require('fs');
var zip = require('zip');
var io = require('io');

test.setup();

@@ -12,7 +13,7 @@ var isWin32 = process.platform === 'win32';
function unlink(pathname) {
try {
fs.rmdir(pathname);
} catch (e) { }
} catch (e) {}
}

var pathname = 'test_dir' + vmid;
@@ -30,7 +31,7 @@ describe('fs', () => {
after(() => {
try {
fs.unlink(path.join(__dirname, 'unzip_test.zip'));
} catch (e) { }
} catch (e) {}
});

it("stat", () => {
@@ -347,6 +348,38 @@ describe('fs', () => {
test_zip(2);
});

it("zip data", () => {
function save_zip(n) {
var stream = new io.MemoryStream();
var zipfile = zip.open(stream, "w");
zipfile.write(new Buffer('test ' + n), 'test.txt');
zipfile.close();

stream.rewind();
fs.setZipFS("/unzip_test.zip", stream.readAll());
}

function test_zip(n) {
assert.equal(fs.readTextFile(path.join("/unzip_test.zip$", "test.txt")),
"test " + n);
}

save_zip(1);
test_zip(1);

save_zip(2);
test_zip(2);

coroutine.sleep(4000);
test_zip(2);

fs.clearZipFS("/unzip_test.zip");

assert.throws(() => {
test_zip(2);
});
});

describe('read', () => {
var fd;
before(() => fd = fs.open(path.join(__dirname, 'fs_files', 'read.txt')));

0 comments on commit 70c117a

Please sign in to comment.
You can’t perform that action at this time.