[njs] Added fs.mkdir(), fs.rmdir() and friends.
Dmitry Volyntsev
xeioex at nginx.com
Tue May 26 18:36:15 UTC 2020
details: https://hg.nginx.org/njs/rev/d6fb90ffe4c9
branches:
changeset: 1398:d6fb90ffe4c9
user: Artem S. Povalyukhin <artem.povaluhin at gmail.com>
date: Tue May 12 12:31:19 2020 +0300
description:
Added fs.mkdir(), fs.rmdir() and friends.
diffstat:
src/njs_fs.c | 210 +++++++++++++++++++++++++++++++++++++++++++++
test/js/fs_promises_005.js | 143 ++++++++++++++++++++++++++++++
test/njs_expect_test.exp | 5 +
3 files changed, 358 insertions(+), 0 deletions(-)
diffs (393 lines):
diff -r 1d0825906438 -r d6fb90ffe4c9 src/njs_fs.c
--- a/src/njs_fs.c Mon May 25 14:21:22 2020 +0000
+++ b/src/njs_fs.c Tue May 12 12:31:19 2020 +0300
@@ -729,6 +729,168 @@ done:
static njs_int_t
+njs_fs_mkdir(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
+ njs_index_t calltype)
+{
+ mode_t md;
+ njs_int_t ret;
+ const char *file_path;
+ njs_value_t mode, recursive, retval, *path, *callback, *options;
+
+ static const njs_value_t string_mode = njs_string("mode");
+ static const njs_value_t string_recursive = njs_string("recursive");
+
+ path = njs_arg(args, nargs, 1);
+ ret = njs_fs_path_arg(vm, &file_path, path, &njs_str_value("path"));
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
+ }
+
+ callback = NULL;
+ options = njs_arg(args, nargs, 2);
+
+ if (njs_slow_path(calltype == NJS_FS_CALLBACK)) {
+ callback = njs_arg(args, nargs, njs_min(nargs - 1, 3));
+ if (!njs_is_function(callback)) {
+ njs_type_error(vm, "\"callback\" must be a function");
+ return NJS_ERROR;
+ }
+ if (options == callback) {
+ options = njs_value_arg(&njs_value_undefined);
+ }
+ }
+
+ njs_set_undefined(&mode);
+ njs_set_false(&recursive);
+
+ switch (options->type) {
+ case NJS_NUMBER:
+ mode = *options;
+ break;
+
+ case NJS_UNDEFINED:
+ break;
+
+ default:
+ if (!njs_is_object(options)) {
+ njs_type_error(vm, "Unknown options type: \"%s\" "
+ "(a number or object required)",
+ njs_type_string(options->type));
+ return NJS_ERROR;
+ }
+
+ ret = njs_value_property(vm, options, njs_value_arg(&string_mode),
+ &mode);
+ if (njs_slow_path(ret == NJS_ERROR)) {
+ return ret;
+ }
+
+ ret = njs_value_property(vm, options, njs_value_arg(&string_recursive),
+ &recursive);
+ if (njs_slow_path(ret == NJS_ERROR)) {
+ return ret;
+ }
+ }
+
+ md = njs_fs_mode(vm, &mode, 0777);
+ if (njs_slow_path(md == (mode_t) -1)) {
+ return NJS_ERROR;
+ }
+
+ if (njs_is_true(&recursive)) {
+ njs_type_error(vm, "\"options.recursive\" is not supported");
+ return NJS_ERROR;
+ }
+
+ njs_set_undefined(&retval);
+
+ ret = mkdir(file_path, md);
+ if (njs_slow_path(ret != 0)) {
+ ret = njs_fs_error(vm, "mkdir", strerror(errno), path, errno,
+ &retval);
+ }
+
+ if (ret == NJS_OK) {
+ return njs_fs_result(vm, &retval, calltype, callback, 1);
+ }
+
+ return NJS_ERROR;
+}
+
+
+static njs_int_t
+njs_fs_rmdir(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
+ njs_index_t calltype)
+{
+ njs_int_t ret;
+ const char *file_path;
+ njs_value_t recursive, retval, *path, *callback, *options;
+
+ static const njs_value_t string_recursive = njs_string("recursive");
+
+ path = njs_arg(args, nargs, 1);
+ ret = njs_fs_path_arg(vm, &file_path, path, &njs_str_value("path"));
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
+ }
+
+ callback = NULL;
+ options = njs_arg(args, nargs, 2);
+
+ if (njs_slow_path(calltype == NJS_FS_CALLBACK)) {
+ callback = njs_arg(args, nargs, njs_min(nargs - 1, 3));
+ if (!njs_is_function(callback)) {
+ njs_type_error(vm, "\"callback\" must be a function");
+ return NJS_ERROR;
+ }
+ if (options == callback) {
+ options = njs_value_arg(&njs_value_undefined);
+ }
+ }
+
+ njs_set_false(&recursive);
+
+ switch (options->type) {
+ case NJS_UNDEFINED:
+ break;
+
+ default:
+ if (!njs_is_object(options)) {
+ njs_type_error(vm, "Unknown options type: \"%s\" "
+ "(an object required)",
+ njs_type_string(options->type));
+ return NJS_ERROR;
+ }
+
+ ret = njs_value_property(vm, options, njs_value_arg(&string_recursive),
+ &recursive);
+ if (njs_slow_path(ret == NJS_ERROR)) {
+ return ret;
+ }
+ }
+
+ if (njs_is_true(&recursive)) {
+ njs_type_error(vm, "\"options.recursive\" is not supported");
+ return NJS_ERROR;
+ }
+
+ njs_set_undefined(&retval);
+
+ ret = rmdir(file_path);
+ if (njs_slow_path(ret != 0)) {
+ ret = njs_fs_error(vm, "rmdir", strerror(errno), path, errno,
+ &retval);
+ }
+
+ if (ret == NJS_OK) {
+ return njs_fs_result(vm, &retval, calltype, callback, 1);
+ }
+
+ return NJS_ERROR;
+}
+
+
+static njs_int_t
njs_fs_fd_read(njs_vm_t *vm, int fd, njs_str_t *data)
{
u_char *p, *end, *start;
@@ -1103,6 +1265,22 @@ static const njs_object_prop_t njs_fs_p
{
.type = NJS_PROPERTY,
+ .name = njs_string("mkdir"),
+ .value = njs_native_function2(njs_fs_mkdir, 0, NJS_FS_PROMISE),
+ .writable = 1,
+ .configurable = 1,
+ },
+
+ {
+ .type = NJS_PROPERTY,
+ .name = njs_string("rmdir"),
+ .value = njs_native_function2(njs_fs_rmdir, 0, NJS_FS_PROMISE),
+ .writable = 1,
+ .configurable = 1,
+ },
+
+ {
+ .type = NJS_PROPERTY,
.name = njs_string("symlink"),
.value = njs_native_function2(njs_fs_symlink, 0, NJS_FS_PROMISE),
.writable = 1,
@@ -1330,6 +1508,38 @@ static const njs_object_prop_t njs_fs_o
.writable = 1,
.configurable = 1,
},
+
+ {
+ .type = NJS_PROPERTY,
+ .name = njs_string("mkdir"),
+ .value = njs_native_function2(njs_fs_mkdir, 0, NJS_FS_CALLBACK),
+ .writable = 1,
+ .configurable = 1,
+ },
+
+ {
+ .type = NJS_PROPERTY,
+ .name = njs_string("mkdirSync"),
+ .value = njs_native_function2(njs_fs_mkdir, 0, NJS_FS_DIRECT),
+ .writable = 1,
+ .configurable = 1,
+ },
+
+ {
+ .type = NJS_PROPERTY,
+ .name = njs_string("rmdir"),
+ .value = njs_native_function2(njs_fs_rmdir, 0, NJS_FS_CALLBACK),
+ .writable = 1,
+ .configurable = 1,
+ },
+
+ {
+ .type = NJS_PROPERTY,
+ .name = njs_string("rmdirSync"),
+ .value = njs_native_function2(njs_fs_rmdir, 0, NJS_FS_DIRECT),
+ .writable = 1,
+ .configurable = 1,
+ },
};
diff -r 1d0825906438 -r d6fb90ffe4c9 test/js/fs_promises_005.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/js/fs_promises_005.js Tue May 12 12:31:19 2020 +0300
@@ -0,0 +1,143 @@
+var fs = require('fs');
+var fsp = fs.promises;
+var rname = './build/test/';
+var dname = rname + 'fs_promises_005';
+var dname_utf8 = rname + 'fs_promises_αβγ_005';
+var fname = (d) => d + '/fs_promises_005_file';
+
+
+var testSync = () => new Promise((resolve, reject) => {
+ try {
+ try { fs.unlinkSync(fname(dname)); } catch (e) {}
+ try { fs.unlinkSync(fname(dname_utf8)); } catch (e) {}
+ try { fs.rmdirSync(dname); } catch (e) {}
+ try { fs.rmdirSync(dname_utf8); } catch (e) {}
+
+ fs.mkdirSync(dname);
+
+ try {
+ fs.mkdirSync(dname);
+
+ } catch (e) {
+ if (e.syscall != 'mkdir' || e.code != 'EEXIST') {
+ throw e;
+ }
+ }
+
+ fs.writeFileSync(fname(dname), fname(dname));
+
+ try {
+ fs.rmdirSync(dname);
+
+ } catch (e) {
+ if (e.syscall != 'rmdir'
+ || (e.code != 'ENOTEMPTY' && e.code != 'EEXIST'))
+ {
+ throw e;
+ }
+ }
+
+ fs.unlinkSync(fname(dname));
+
+ fs.rmdirSync(dname);
+
+ fs.mkdirSync(dname_utf8, 0o555);
+
+ try {
+ fs.writeFileSync(fname(dname_utf8), fname(dname_utf8));
+
+ } catch (e) {
+ if (e.syscall != 'open' || e.code != 'EACCES') {
+ throw e;
+ }
+ }
+
+ try {
+ fs.unlinkSync(dname_utf8);
+
+ } catch (e) {
+ if (e.syscall != 'unlink' || (e.code != 'EISDIR' && e.code != 'EPERM')) {
+ throw e;
+ }
+ }
+
+ fs.rmdirSync(dname_utf8);
+
+ resolve();
+
+ } catch (e) {
+ reject(e);
+ }
+});
+
+
+var testCallback = () => new Promise((resolve, reject) => {
+ try {
+ try { fs.unlinkSync(fname(dname)); } catch (e) {}
+ try { fs.unlinkSync(fname(dname_utf8)); } catch (e) {}
+ try { fs.rmdirSync(dname); } catch (e) {}
+ try { fs.rmdirSync(dname_utf8); } catch (e) {}
+
+ fs.mkdir(dname, (err) => {
+ if (err) {
+ reject(err);
+ }
+
+ fs.mkdir(dname, (err) => {
+ if (!err || err.code != 'EEXIST') {
+ reject(new Error('fs.mkdir error 1'));
+ }
+
+ fs.rmdir(dname, (err) => {
+ if (err) {
+ reject(err);
+ }
+
+ resolve();
+ });
+ });
+ });
+
+ } catch (e) {
+ reject(e);
+ }
+});
+
+
+Promise.resolve()
+.then(testSync)
+.then(() => {
+ console.log('test fs.mkdirSync');
+})
+.catch((e) => {
+ console.log('test fs.mkdirSync failed', JSON.stringify(e));
+})
+
+.then(testCallback)
+.then(() => {
+ console.log('test fs.mkdir');
+})
+.catch((e) => {
+ console.log('test fs.mkdir failed', JSON.stringify(e));
+})
+
+.then(() => {
+ try { fs.unlinkSync(fname(dname)); } catch (e) {}
+ try { fs.unlinkSync(fname(dname_utf8)); } catch (e) {}
+ try { fs.rmdirSync(dname); } catch (e) {}
+ try { fs.rmdirSync(dname_utf8); } catch (e) {}
+})
+.then(() => fsp.mkdir(dname))
+.then(() => fsp.mkdir(dname))
+.catch((e) => {
+ if (e.syscall != 'mkdir' || e.code != 'EEXIST') {
+ throw e;
+ }
+})
+.then(() => fsp.rmdir(dname))
+.then(() => {
+ console.log('test fsp.mkdir');
+})
+.catch((e) => {
+ console.log('test fsp.mkdir failed', JSON.stringify(e));
+});
diff -r 1d0825906438 -r d6fb90ffe4c9 test/njs_expect_test.exp
--- a/test/njs_expect_test.exp Mon May 25 14:21:22 2020 +0000
+++ b/test/njs_expect_test.exp Tue May 12 12:31:19 2020 +0300
@@ -1130,3 +1130,8 @@ njs_run {"./test/js/fs_promises_004.js"}
"test fs.symlinkSync
test fs.symlink
test fsp.symlink"
+
+njs_run {"./test/js/fs_promises_005.js"} \
+"test fs.mkdirSync
+test fs.mkdir
+test fsp.mkdir"
More information about the nginx-devel
mailing list