From: Artem S. Povalyukhin Date: Tue, 12 May 2020 09:31:19 +0000 (+0300) Subject: Added fs.mkdir(), fs.rmdir() and friends. X-Git-Tag: 0.4.2~60 X-Git-Url: http://git.kaiwu.me/postgresql/log/contrib/postgres_fdw/static/gitweb.js?a=commitdiff_plain;h=b11c38d0399e1f8780011bbb4ac48f8acbdf7334;p=njs.git Added fs.mkdir(), fs.rmdir() and friends. --- diff --git a/src/njs_fs.c b/src/njs_fs.c index 9d3b9cb7..7e0cbcaf 100644 --- a/src/njs_fs.c +++ b/src/njs_fs.c @@ -728,6 +728,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) { @@ -1101,6 +1263,22 @@ static const njs_object_prop_t njs_fs_promises_properties[] = .configurable = 1, }, + { + .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"), @@ -1330,6 +1508,38 @@ static const njs_object_prop_t njs_fs_object_properties[] = .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 --git a/test/js/fs_promises_005.js b/test/js/fs_promises_005.js new file mode 100644 index 00000000..544e2047 --- /dev/null +++ b/test/js/fs_promises_005.js @@ -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 --git a/test/njs_expect_test.exp b/test/njs_expect_test.exp index 6abc00ad..73614b45 100644 --- a/test/njs_expect_test.exp +++ b/test/njs_expect_test.exp @@ -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"