[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