-
-
Save drsm/4785ae96a8b1ccee27a56c2919d6ba18 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# HG changeset patch | |
# User Artem S. Povalyukhin <artem.povaluhin@gmail.com> | |
# Date 1589275879 -10800 | |
# Tue May 12 12:31:19 2020 +0300 | |
# Node ID b4a7540f94e52eedb48e0a76f040a759557866dd | |
# Parent 3f2c209222753066505f35b994fea3600311c2fb | |
Added fs.mkdir(), fs.rmdir() and friends. | |
diff -r 3f2c20922275 -r b4a7540f94e5 src/njs_fs.c | |
--- a/src/njs_fs.c Mon May 11 09:58:28 2020 +0300 | |
+++ b/src/njs_fs.c Tue May 12 12:31:19 2020 +0300 | |
@@ -729,6 +729,175 @@ done: | |
static njs_int_t | |
+njs_fs_mkdir(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, | |
+ njs_index_t calltype) | |
+{ | |
+ njs_int_t ret; | |
+ mode_t md; | |
+ 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; | |
+ } | |
+ | |
+ ret = mkdir(file_path, md); | |
+ if (njs_slow_path(ret != 0)) { | |
+ ret = njs_fs_error(vm, "mkdir", strerror(errno), path, errno, | |
+ &retval); | |
+ goto done; | |
+ } | |
+ | |
+ njs_set_undefined(&retval); | |
+ | |
+done: | |
+ | |
+ 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; | |
+ } | |
+ | |
+ ret = rmdir(file_path); | |
+ if (njs_slow_path(ret != 0)) { | |
+ ret = njs_fs_error(vm, "rmdir", strerror(errno), path, errno, | |
+ &retval); | |
+ goto done; | |
+ } | |
+ | |
+ njs_set_undefined(&retval); | |
+ | |
+done: | |
+ | |
+ 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; | |
@@ -1457,6 +1626,22 @@ static const njs_object_prop_t njs_fs_p | |
.writable = 1, | |
.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, | |
+ }, | |
}; | |
@@ -1663,6 +1848,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 3f2c20922275 -r b4a7540f94e5 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,141 @@ | |
+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') { | |
+ 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') { | |
+ 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', e); | |
+}) | |
+ | |
+.then(testCallback) | |
+.then(() => { | |
+ console.log('test fs.mkdir'); | |
+}) | |
+.catch((e) => { | |
+ console.log('test fs.mkdir failed', 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', e); | |
+}); | |
diff -r 3f2c20922275 -r b4a7540f94e5 test/njs_expect_test.exp | |
--- a/test/njs_expect_test.exp Mon May 11 09:58:28 2020 +0300 | |
+++ 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" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment