Skip to content

Commit 70c117a

Browse files
committed
fs, feat: support custom zip fs.
1 parent bd3a4b8 commit 70c117a

File tree

4 files changed

+135
-6
lines changed

4 files changed

+135
-6
lines changed

fibjs/include/ifs/fs.h

+36-1
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ class fs_base : public object_base {
6868
static result_t writeTextFile(exlib::string fname, exlib::string txt, AsyncEvent* ac);
6969
static result_t writeFile(exlib::string fname, Buffer_base* data, AsyncEvent* ac);
7070
static result_t appendFile(exlib::string fname, Buffer_base* data, AsyncEvent* ac);
71+
static result_t setZipFS(exlib::string fname, Buffer_base* data);
72+
static result_t clearZipFS(exlib::string fname);
7173

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

120124
public:
121125
ASYNC_STATICVALUE2(fs_base, exists, exlib::string, bool);
@@ -229,7 +233,9 @@ inline ClassInfo& fs_base::class_info()
229233
{ "writeFile", s_writeFile, true },
230234
{ "writeFileSync", s_writeFile, true },
231235
{ "appendFile", s_appendFile, true },
232-
{ "appendFileSync", s_appendFile, true }
236+
{ "appendFileSync", s_appendFile, true },
237+
{ "setZipFS", s_setZipFS, true },
238+
{ "clearZipFS", s_clearZipFS, true }
233239
};
234240

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

928934
METHOD_VOID();
929935
}
936+
937+
inline void fs_base::s_setZipFS(const v8::FunctionCallbackInfo<v8::Value>& args)
938+
{
939+
METHOD_NAME("fs.setZipFS");
940+
METHOD_ENTER();
941+
942+
METHOD_OVER(2, 2);
943+
944+
ARG(exlib::string, 0);
945+
ARG(obj_ptr<Buffer_base>, 1);
946+
947+
hr = setZipFS(v0, v1);
948+
949+
METHOD_VOID();
950+
}
951+
952+
inline void fs_base::s_clearZipFS(const v8::FunctionCallbackInfo<v8::Value>& args)
953+
{
954+
METHOD_NAME("fs.clearZipFS");
955+
METHOD_ENTER();
956+
957+
METHOD_OVER(1, 0);
958+
959+
OPT_ARG(exlib::string, 0, "");
960+
961+
hr = clearZipFS(v0);
962+
963+
METHOD_VOID();
964+
}
930965
}
931966

932967
#endif

fibjs/src/fs/fs.cpp

+55
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,61 @@ class cache_node : public obj_base {
3636
static std::list<obj_ptr<cache_node>> s_cache;
3737
static exlib::spinlock s_cachelock;
3838

39+
result_t fs_base::setZipFS(exlib::string fname, Buffer_base* data)
40+
{
41+
result_t hr;
42+
std::list<obj_ptr<cache_node>>::iterator it;
43+
obj_ptr<ZipFile_base> zfile;
44+
obj_ptr<cache_node> _node;
45+
46+
hr = zip_base::cc_open(data, "r", zip_base::_ZIP_DEFLATED, zfile);
47+
if (hr < 0)
48+
return hr;
49+
50+
obj_ptr<NArray> list;
51+
hr = zfile->cc_readAll("", list);
52+
if (hr < 0)
53+
return hr;
54+
55+
_node = new cache_node();
56+
_node->m_name = fname;
57+
_node->m_list = list;
58+
_node->m_date = INFINITY;
59+
_node->m_mtime.now();
60+
61+
s_cachelock.lock();
62+
for (it = s_cache.begin(); it != s_cache.end(); ++it)
63+
if ((*it)->m_name == fname) {
64+
*it = _node;
65+
break;
66+
}
67+
if (it == s_cache.end())
68+
s_cache.push_back(_node);
69+
s_cachelock.unlock();
70+
return 0;
71+
}
72+
73+
result_t fs_base::clearZipFS(exlib::string fname)
74+
{
75+
if (fname.empty()) {
76+
s_cachelock.lock();
77+
s_cache.clear();
78+
s_cachelock.unlock();
79+
} else {
80+
std::list<obj_ptr<cache_node>>::iterator it;
81+
82+
s_cachelock.lock();
83+
for (it = s_cache.begin(); it != s_cache.end(); ++it)
84+
if ((*it)->m_name == fname) {
85+
s_cache.erase(it);
86+
break;
87+
}
88+
s_cachelock.unlock();
89+
}
90+
91+
return 0;
92+
}
93+
3994
result_t fs_base::openFile(exlib::string fname, exlib::string flags,
4095
obj_ptr<SeekableStream_base>& retVal, AsyncEvent* ac)
4196
{

idl/zh-cn/fs.idl

+9-3
Original file line numberDiff line numberDiff line change
@@ -257,8 +257,14 @@ module fs
257257
*/
258258
static appendFile(String fname, Buffer data) async;
259259

260-
/*! @brief 创建二进制文件,并写入内容,是 appendFile 的同步版兼容接口
261-
@param fname 指定文件名
262-
@param data 指定要写入的二进制数据
260+
/*! @brief 设置 zip 虚拟文件映射
261+
@param fname 指定映射路径
262+
@param data 指定映射的 zip 文件数据
263+
*/
264+
static setZipFS(String fname, Buffer data);
265+
266+
/*! @brief 清除 zip 虚拟文件映射
267+
@param fname 指定映射路径,缺省清除全部缓存
263268
*/
269+
static clearZipFS(String fname = "");
264270
};

test/fs_test.js

+35-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ var coroutine = require('coroutine');
33
var path = require('path');
44
var fs = require('fs');
55
var zip = require('zip');
6+
var io = require('io');
67

78
test.setup();
89

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

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

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

351+
it("zip data", () => {
352+
function save_zip(n) {
353+
var stream = new io.MemoryStream();
354+
var zipfile = zip.open(stream, "w");
355+
zipfile.write(new Buffer('test ' + n), 'test.txt');
356+
zipfile.close();
357+
358+
stream.rewind();
359+
fs.setZipFS("/unzip_test.zip", stream.readAll());
360+
}
361+
362+
function test_zip(n) {
363+
assert.equal(fs.readTextFile(path.join("/unzip_test.zip$", "test.txt")),
364+
"test " + n);
365+
}
366+
367+
save_zip(1);
368+
test_zip(1);
369+
370+
save_zip(2);
371+
test_zip(2);
372+
373+
coroutine.sleep(4000);
374+
test_zip(2);
375+
376+
fs.clearZipFS("/unzip_test.zip");
377+
378+
assert.throws(() => {
379+
test_zip(2);
380+
});
381+
});
382+
350383
describe('read', () => {
351384
var fd;
352385
before(() => fd = fs.open(path.join(__dirname, 'fs_files', 'read.txt')));

0 commit comments

Comments
 (0)