-
-
Save drsm/342c4300b17b90cf749f3e316fc3b403 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 1594817466 -10800 | |
# Wed Jul 15 15:51:06 2020 +0300 | |
# Node ID f8f8ad5c4e4fbe57d9fa5b3c992ad7b3071f28ed | |
# Parent 3dc7a53d9f007734a68588457b70768b41256038 | |
Improved fs.mkdir() to support recursive directory creation. | |
diff -r 3dc7a53d9f00 -r f8f8ad5c4e4f src/njs_fs.c | |
--- a/src/njs_fs.c Tue Jul 14 17:21:53 2020 +0000 | |
+++ b/src/njs_fs.c Wed Jul 15 15:51:06 2020 +0300 | |
@@ -70,6 +70,9 @@ static njs_int_t njs_fs_error(njs_vm_t * | |
static njs_int_t njs_fs_result(njs_vm_t *vm, njs_value_t *result, | |
njs_index_t calltype, const njs_value_t* callback, njs_uint_t nargs); | |
+static njs_int_t njs_fs_make_path(njs_vm_t *vm, char *path, mode_t md, | |
+ njs_value_t *retval); | |
+ | |
static int njs_fs_flags(njs_vm_t *vm, njs_value_t *value, int default_flags); | |
static mode_t njs_fs_mode(njs_vm_t *vm, njs_value_t *value, | |
mode_t default_mode); | |
@@ -829,16 +832,16 @@ njs_fs_mkdir(njs_vm_t *vm, njs_value_t * | |
} | |
if (njs_is_true(&recursive)) { | |
- njs_type_error(vm, "\"options.recursive\" is not supported"); | |
- return NJS_ERROR; | |
- } | |
+ ret = njs_fs_make_path(vm, (char *) file_path, md, &retval); | |
+ | |
+ } else { | |
+ njs_set_undefined(&retval); | |
- 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); | |
+ 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) { | |
@@ -1138,6 +1141,85 @@ njs_fs_fd_read(njs_vm_t *vm, int fd, njs | |
} | |
+static njs_int_t | |
+njs_fs_make_path(njs_vm_t *vm, char *path, mode_t md, njs_value_t *retval) | |
+{ | |
+ char *p; | |
+ size_t size; | |
+ ssize_t length; | |
+ njs_int_t ret; | |
+ njs_value_t value; | |
+ struct stat sb; | |
+ | |
+ njs_set_undefined(retval); | |
+ | |
+ ret = stat(path, &sb); | |
+ if (ret == 0) { | |
+ if (S_ISDIR(sb.st_mode) == 0) { | |
+ errno = ENOTDIR; | |
+ goto failed; | |
+ } | |
+ | |
+ return NJS_OK; | |
+ } | |
+ | |
+ if (errno != ENOENT) { | |
+ goto failed; | |
+ } | |
+ | |
+ p = path; | |
+ while (*p == '/') { | |
+ p++; | |
+ } | |
+ | |
+ while ((p = strchr(p, '/'))) { | |
+ *p = '\0'; | |
+ | |
+ ret = stat(path, &sb); | |
+ if (ret == 0) { | |
+ if (S_ISDIR(sb.st_mode) == 0) { | |
+ errno = ENOTDIR; | |
+ goto failed; | |
+ } | |
+ | |
+ } else { | |
+ ret = mkdir(path, md); | |
+ if (ret != 0) { | |
+ goto failed; | |
+ } | |
+ } | |
+ | |
+ *p++ = '/'; | |
+ while (*p == '/') { | |
+ p++; | |
+ } | |
+ } | |
+ | |
+ ret = mkdir(path, md); | |
+ if (ret != 0 && errno != EEXIST) { | |
+ goto failed; | |
+ } | |
+ | |
+ return NJS_OK; | |
+ | |
+failed: | |
+ | |
+ size = njs_strlen(path); | |
+ length = njs_utf8_length((u_char *) path, size); | |
+ if (njs_slow_path(length < 0)) { | |
+ length = 0; | |
+ } | |
+ | |
+ ret = njs_string_new(vm, &value, (u_char *) path, size, length); | |
+ if (ret != NJS_OK) { | |
+ return NJS_ERROR; | |
+ } | |
+ | |
+ return njs_fs_error(vm, "mkdir", strerror(errno), &value, errno, | |
+ retval); | |
+} | |
+ | |
+ | |
static int | |
njs_fs_flags(njs_vm_t *vm, njs_value_t *value, int default_flags) | |
{ | |
diff -r 3dc7a53d9f00 -r f8f8ad5c4e4f test/js/fs_promises_008.js | |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 | |
+++ b/test/js/fs_promises_008.js Wed Jul 15 15:51:06 2020 +0300 | |
@@ -0,0 +1,79 @@ | |
+var fs = require('fs'); | |
+var fsp = fs.promises; | |
+var dname = './build/test/fs_promises_αβγ_008/'; | |
+var path = 'one/two/three/αβγ'; | |
+ | |
+var wipePath = (root, path, nofail) => { | |
+ path | |
+ .split('/') | |
+ .map((x, i, a) => { | |
+ return root + a.slice(0, i + 1).join('/'); | |
+ }) | |
+ .reverse() | |
+ .map((dir) => { | |
+ try { | |
+ fs.rmdirSync(dir); | |
+ } catch (e) { | |
+ if (!nofail) { | |
+ throw e; | |
+ } | |
+ } | |
+ }); | |
+}; | |
+ | |
+var testSync = () => new Promise((resolve, reject) => { | |
+ try { | |
+ wipePath(dname, path + '/' + path, true); | |
+ fs.rmdirSync(dname); | |
+ } catch (e) { | |
+ } | |
+ | |
+ try { | |
+ fs.mkdirSync(dname); | |
+ | |
+ fs.mkdirSync(dname, { recursive: true }); | |
+ fs.mkdirSync(dname + '/', { recursive: true }); | |
+ fs.mkdirSync(dname + '////', { recursive: true }); | |
+ | |
+ fs.mkdirSync(dname + path, { recursive: true }); | |
+ wipePath(dname, path); | |
+ | |
+ fs.mkdirSync(dname + '////' + path + '////' + path + '////', { recursive: true }); | |
+ wipePath(dname, path + '/' + path); | |
+ | |
+ try { | |
+ fs.mkdirSync(dname + path, { recursive: true, mode: 0 }); | |
+ } catch (e) { | |
+ if (e.code != 'EACCES') { | |
+ reject(e); | |
+ } | |
+ } | |
+ wipePath(dname, path, true); | |
+ | |
+ try { | |
+ fs.mkdirSync(dname + path, { recursive: true }); | |
+ fs.writeFileSync(dname + path + '/one', 'not dir'); | |
+ fs.mkdirSync(dname + path + '/' + path, { recursive: true }); | |
+ } catch (e) { | |
+ if (e.code != 'ENOTDIR') { | |
+ reject(e); | |
+ } | |
+ } | |
+ fs.unlinkSync(dname + path + '/one'); | |
+ wipePath(dname, path); | |
+ | |
+ fs.rmdirSync(dname); | |
+ resolve(); | |
+ } catch (e) { | |
+ reject(e); | |
+ } | |
+}); | |
+ | |
+Promise.resolve() | |
+.then(testSync) | |
+.then(() => { | |
+ console.log('test recursive fs.mkdirSync'); | |
+}) | |
+.catch((e) => { | |
+ console.log('test failed recursive fs.mkdirSync', JSON.stringify(e)); | |
+}) | |
diff -r 3dc7a53d9f00 -r f8f8ad5c4e4f test/njs_expect_test.exp | |
--- a/test/njs_expect_test.exp Tue Jul 14 17:21:53 2020 +0000 | |
+++ b/test/njs_expect_test.exp Wed Jul 15 15:51:06 2020 +0300 | |
@@ -1140,3 +1140,6 @@ njs_run {"./test/js/fs_promises_007.js"} | |
"test fs.readdirSync | |
test fs.readdir | |
test fsp.readdir" | |
+ | |
+njs_run {"./test/js/fs_promises_008.js"} \ | |
+"test recursive fs.mkdirSync" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment