#define njs_fs_magic(calltype, mode) \
(((mode) << 2) | calltype)
+#define njs_fs_magic2(field, type) \
+ (((type) << 4) | field)
+
typedef enum {
NJS_FS_DIRECT,
njs_ftw_type_t);
+static njs_int_t njs_fs_access(njs_vm_t *vm, njs_value_t *args,
+ njs_uint_t nargs, njs_index_t calltype);
+static njs_int_t njs_fs_mkdir(njs_vm_t *vm, njs_value_t *args,
+ njs_uint_t nargs, njs_index_t calltype);
+static njs_int_t njs_fs_read(njs_vm_t *vm, njs_value_t *args,
+ njs_uint_t nargs, njs_index_t calltype);
+static njs_int_t njs_fs_readdir(njs_vm_t *vm, njs_value_t *args,
+ njs_uint_t nargs, njs_index_t calltype);
+static njs_int_t njs_fs_realpath(njs_vm_t *vm, njs_value_t *args,
+ njs_uint_t nargs, njs_index_t calltype);
+static njs_int_t njs_fs_rename(njs_vm_t *vm, njs_value_t *args,
+ njs_uint_t nargs, njs_index_t calltype);
+static njs_int_t njs_fs_rmdir(njs_vm_t *vm, njs_value_t *args,
+ njs_uint_t nargs, njs_index_t calltype);
+static njs_int_t njs_fs_stat(njs_vm_t *vm, njs_value_t *args,
+ njs_uint_t nargs, njs_index_t calltype);
+static njs_int_t njs_fs_symlink(njs_vm_t *vm, njs_value_t *args,
+ njs_uint_t nargs, njs_index_t calltype);
+static njs_int_t njs_fs_unlink(njs_vm_t *vm, njs_value_t *args,
+ njs_uint_t nargs, njs_index_t calltype);
+static njs_int_t njs_fs_write(njs_vm_t *vm, njs_value_t *args,
+ njs_uint_t nargs, njs_index_t calltype);
+
+static njs_int_t njs_fs_constants(njs_vm_t *vm, njs_object_prop_t *prop,
+ njs_value_t *value, njs_value_t *unused, njs_value_t *retval);
+static njs_int_t njs_fs_promises(njs_vm_t *vm, njs_object_prop_t *prop,
+ njs_value_t *value, njs_value_t *unused, njs_value_t *retval);
+
+static njs_int_t njs_fs_dirent_constructor(njs_vm_t *vm, njs_value_t *args,
+ njs_uint_t nargs, njs_index_t unused);
+static njs_int_t njs_fs_dirent_test(njs_vm_t *vm, njs_value_t *args,
+ njs_uint_t nargs, njs_index_t testtype);
+
+static njs_int_t njs_fs_stats_test(njs_vm_t *vm, njs_value_t *args,
+ njs_uint_t nargs, njs_index_t testtype);
+static njs_int_t njs_fs_stats_prop(njs_vm_t *vm, njs_object_prop_t *prop,
+ njs_value_t *value, njs_value_t *setval, njs_value_t *retval);
+static njs_int_t njs_fs_stats_create(njs_vm_t *vm, struct stat *st,
+ njs_value_t *retval);
+
static njs_int_t njs_fs_fd_read(njs_vm_t *vm, int fd, njs_str_t *data);
static njs_int_t njs_fs_error(njs_vm_t *vm, const char *syscall,
static njs_int_t njs_fs_dirent_create(njs_vm_t *vm, njs_value_t *name,
njs_value_t *type, njs_value_t *retval);
-static njs_int_t njs_fs_stats_create(njs_vm_t *vm, struct stat *st,
- njs_value_t *retval);
+
+static njs_int_t njs_fs_init(njs_vm_t *vm);
+
+
+static const njs_value_t string_flag = njs_string("flag");
+static const njs_value_t string_mode = njs_string("mode");
+static const njs_value_t string_buffer = njs_string("buffer");
+static const njs_value_t string_encoding = njs_string("encoding");
+static const njs_value_t string_recursive = njs_string("recursive");
+
static njs_fs_entry_t njs_flags_table[] = {
{ njs_str("a"), O_APPEND | O_CREAT | O_WRONLY },
};
-static const njs_value_t string_flag = njs_string("flag");
-static const njs_value_t string_mode = njs_string("mode");
-static const njs_value_t string_buffer = njs_string("buffer");
-static const njs_value_t string_encoding = njs_string("encoding");
-static const njs_value_t string_recursive = njs_string("recursive");
+static njs_external_t njs_ext_fs[] = {
+ {
+ .flags = NJS_EXTERN_METHOD,
+ .name.string = njs_str("access"),
+ .writable = 1,
+ .configurable = 1,
+ .u.method = {
+ .native = njs_fs_access,
+ .magic8 = NJS_FS_CALLBACK,
+ }
+ },
-static njs_int_t
-njs_fs_read_file(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
- njs_index_t calltype)
-{
- int fd, flags;
- njs_str_t data;
- njs_int_t ret;
- const char *path;
- njs_value_t flag, encode, retval, *callback, *options;
- struct stat sb;
- const njs_buffer_encoding_t *encoding;
- char path_buf[NJS_MAX_PATH + 1];
+ {
+ .flags = NJS_EXTERN_METHOD,
+ .name.string = njs_str("accessSync"),
+ .writable = 1,
+ .configurable = 1,
+ .u.method = {
+ .native = njs_fs_access,
+ .magic8 = NJS_FS_DIRECT,
+ }
+ },
- path = njs_fs_path(vm, path_buf, njs_arg(args, nargs, 1), "path");
- if (njs_slow_path(path == NULL)) {
- return NJS_ERROR;
- }
+ {
+ .flags = NJS_EXTERN_METHOD,
+ .name.string = njs_str("appendFile"),
+ .writable = 1,
+ .configurable = 1,
+ .u.method = {
+ .native = njs_fs_write,
+ .magic8 = njs_fs_magic(NJS_FS_CALLBACK, NJS_FS_APPEND),
+ }
+ },
- callback = NULL;
+ {
+ .flags = NJS_EXTERN_METHOD,
+ .name.string = njs_str("appendFileSync"),
+ .writable = 1,
+ .configurable = 1,
+ .u.method = {
+ .native = njs_fs_write,
+ .magic8 = njs_fs_magic(NJS_FS_DIRECT, NJS_FS_APPEND),
+ }
+ },
- options = njs_arg(args, nargs, 2);
+ {
+ .flags = NJS_EXTERN_PROPERTY,
+ .name.string = njs_str("constants"),
+ .enumerable = 1,
+ .u.property = {
+ .handler = njs_fs_constants,
+ }
+ },
- if (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;
+ {
+ .flags = NJS_EXTERN_METHOD,
+ .name.string = njs_str("Dirent"),
+ .writable = 1,
+ .configurable = 1,
+ .u.method = {
+ .native = njs_fs_dirent_constructor,
+ .ctor = 1,
}
+ },
- if (options == callback) {
- options = njs_value_arg(&njs_value_undefined);
+ {
+ .flags = NJS_EXTERN_METHOD,
+ .name.string = njs_str("lstat"),
+ .writable = 1,
+ .configurable = 1,
+ .u.method = {
+ .native = njs_fs_stat,
+ .magic8 = njs_fs_magic(NJS_FS_CALLBACK, NJS_FS_LSTAT),
}
- }
+ },
- njs_set_undefined(&flag);
- njs_set_undefined(&encode);
+ {
+ .flags = NJS_EXTERN_METHOD,
+ .name.string = njs_str("lstatSync"),
+ .writable = 1,
+ .configurable = 1,
+ .u.method = {
+ .native = njs_fs_stat,
+ .magic8 = njs_fs_magic(NJS_FS_DIRECT, NJS_FS_LSTAT),
+ }
+ },
- switch (options->type) {
- case NJS_STRING:
- encode = *options;
- break;
+ {
+ .flags = NJS_EXTERN_METHOD,
+ .name.string = njs_str("mkdir"),
+ .writable = 1,
+ .configurable = 1,
+ .u.method = {
+ .native = njs_fs_mkdir,
+ .magic8 = NJS_FS_CALLBACK,
+ }
+ },
- case NJS_UNDEFINED:
- break;
+ {
+ .flags = NJS_EXTERN_METHOD,
+ .name.string = njs_str("mkdirSync"),
+ .writable = 1,
+ .configurable = 1,
+ .u.method = {
+ .native = njs_fs_mkdir,
+ .magic8 = NJS_FS_DIRECT,
+ }
+ },
- default:
- if (!njs_is_object(options)) {
- njs_type_error(vm, "Unknown options type: \"%s\" "
- "(a string or object required)",
- njs_type_string(options->type));
- return NJS_ERROR;
+ {
+ .flags = NJS_EXTERN_PROPERTY,
+ .name.string = njs_str("promises"),
+ .enumerable = 1,
+ .u.property = {
+ .handler = njs_fs_promises,
}
+ },
- ret = njs_value_property(vm, options, njs_value_arg(&string_flag),
- &flag);
- if (njs_slow_path(ret == NJS_ERROR)) {
- return ret;
+ {
+ .flags = NJS_EXTERN_METHOD,
+ .name.string = njs_str("readdir"),
+ .writable = 1,
+ .configurable = 1,
+ .u.method = {
+ .native = njs_fs_readdir,
+ .magic8 = NJS_FS_CALLBACK,
}
+ },
- ret = njs_value_property(vm, options, njs_value_arg(&string_encoding),
- &encode);
- if (njs_slow_path(ret == NJS_ERROR)) {
- return ret;
+ {
+ .flags = NJS_EXTERN_METHOD,
+ .name.string = njs_str("readdirSync"),
+ .writable = 1,
+ .configurable = 1,
+ .u.method = {
+ .native = njs_fs_readdir,
+ .magic8 = NJS_FS_DIRECT,
}
- }
+ },
- flags = njs_fs_flags(vm, &flag, O_RDONLY);
- if (njs_slow_path(flags == -1)) {
- return NJS_ERROR;
- }
+ {
+ .flags = NJS_EXTERN_METHOD,
+ .name.string = njs_str("readFile"),
+ .writable = 1,
+ .configurable = 1,
+ .u.method = {
+ .native = njs_fs_read,
+ .magic8 = NJS_FS_CALLBACK,
+ }
+ },
- encoding = NULL;
- if (njs_is_defined(&encode)) {
- encoding = njs_buffer_encoding(vm, &encode);
- if (njs_slow_path(encoding == NULL)) {
- return NJS_ERROR;
+ {
+ .flags = NJS_EXTERN_METHOD,
+ .name.string = njs_str("readFileSync"),
+ .writable = 1,
+ .configurable = 1,
+ .u.method = {
+ .native = njs_fs_read,
+ .magic8 = NJS_FS_DIRECT,
}
- }
+ },
- fd = open(path, flags);
- if (njs_slow_path(fd < 0)) {
- ret = njs_fs_error(vm, "open", strerror(errno), path, errno, &retval);
- goto done;
- }
+ {
+ .flags = NJS_EXTERN_METHOD,
+ .name.string = njs_str("realpath"),
+ .writable = 1,
+ .configurable = 1,
+ .u.method = {
+ .native = njs_fs_realpath,
+ .magic8 = NJS_FS_CALLBACK,
+ }
+ },
- ret = fstat(fd, &sb);
- if (njs_slow_path(ret == -1)) {
- ret = njs_fs_error(vm, "stat", strerror(errno), path, errno, &retval);
- goto done;
- }
+ {
+ .flags = NJS_EXTERN_METHOD,
+ .name.string = njs_str("realpathSync"),
+ .writable = 1,
+ .configurable = 1,
+ .u.method = {
+ .native = njs_fs_realpath,
+ .magic8 = NJS_FS_DIRECT,
+ }
+ },
- if (njs_slow_path(!S_ISREG(sb.st_mode))) {
- ret = njs_fs_error(vm, "stat", "File is not regular", path, 0, &retval);
- goto done;
- }
+ {
+ .flags = NJS_EXTERN_METHOD,
+ .name.string = njs_str("rename"),
+ .writable = 1,
+ .configurable = 1,
+ .u.method = {
+ .native = njs_fs_rename,
+ .magic8 = NJS_FS_CALLBACK,
+ }
+ },
- data.start = NULL;
- data.length = sb.st_size;
+ {
+ .flags = NJS_EXTERN_METHOD,
+ .name.string = njs_str("renameSync"),
+ .writable = 1,
+ .configurable = 1,
+ .u.method = {
+ .native = njs_fs_rename,
+ .magic8 = NJS_FS_DIRECT,
+ }
+ },
- ret = njs_fs_fd_read(vm, fd, &data);
- if (njs_slow_path(ret != NJS_OK)) {
- if (ret == NJS_DECLINED) {
- ret = njs_fs_error(vm, "read", strerror(errno), path, errno,
- &retval);
+ {
+ .flags = NJS_EXTERN_METHOD,
+ .name.string = njs_str("rmdir"),
+ .writable = 1,
+ .configurable = 1,
+ .u.method = {
+ .native = njs_fs_rmdir,
+ .magic8 = NJS_FS_CALLBACK,
}
+ },
- goto done;
- }
+ {
+ .flags = NJS_EXTERN_METHOD,
+ .name.string = njs_str("rmdirSync"),
+ .writable = 1,
+ .configurable = 1,
+ .u.method = {
+ .native = njs_fs_rmdir,
+ .magic8 = NJS_FS_DIRECT,
+ }
+ },
- if (encoding == NULL) {
- ret = njs_buffer_set(vm, &retval, data.start, data.length);
+ {
+ .flags = NJS_EXTERN_METHOD,
+ .name.string = njs_str("stat"),
+ .writable = 1,
+ .configurable = 1,
+ .u.method = {
+ .native = njs_fs_stat,
+ .magic8 = njs_fs_magic(NJS_FS_CALLBACK, NJS_FS_STAT),
+ }
+ },
- } else {
- ret = encoding->encode(vm, &retval, &data);
- njs_mp_free(vm->mem_pool, data.start);
- }
+ {
+ .flags = NJS_EXTERN_METHOD,
+ .name.string = njs_str("statSync"),
+ .writable = 1,
+ .configurable = 1,
+ .u.method = {
+ .native = njs_fs_stat,
+ .magic8 = njs_fs_magic(NJS_FS_DIRECT, NJS_FS_STAT),
+ }
+ },
-done:
+ {
+ .flags = NJS_EXTERN_METHOD,
+ .name.string = njs_str("symlink"),
+ .writable = 1,
+ .configurable = 1,
+ .u.method = {
+ .native = njs_fs_symlink,
+ .magic8 = NJS_FS_CALLBACK,
+ }
+ },
- if (fd != -1) {
- (void) close(fd);
- }
+ {
+ .flags = NJS_EXTERN_METHOD,
+ .name.string = njs_str("symlinkSync"),
+ .writable = 1,
+ .configurable = 1,
+ .u.method = {
+ .native = njs_fs_symlink,
+ .magic8 = NJS_FS_DIRECT,
+ }
+ },
- if (ret == NJS_OK) {
- return njs_fs_result(vm, &retval, calltype, callback, 2);
- }
+ {
+ .flags = NJS_EXTERN_METHOD,
+ .name.string = njs_str("unlink"),
+ .writable = 1,
+ .configurable = 1,
+ .u.method = {
+ .native = njs_fs_unlink,
+ .magic8 = NJS_FS_CALLBACK,
+ }
+ },
- return NJS_ERROR;
-}
+ {
+ .flags = NJS_EXTERN_METHOD,
+ .name.string = njs_str("unlinkSync"),
+ .writable = 1,
+ .configurable = 1,
+ .u.method = {
+ .native = njs_fs_unlink,
+ .magic8 = NJS_FS_DIRECT,
+ }
+ },
+ {
+ .flags = NJS_EXTERN_METHOD,
+ .name.string = njs_str("writeFile"),
+ .writable = 1,
+ .configurable = 1,
+ .u.method = {
+ .native = njs_fs_write,
+ .magic8 = njs_fs_magic(NJS_FS_CALLBACK, NJS_FS_TRUNC),
+ }
+ },
-static njs_int_t
-njs_fs_write_file(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
- njs_index_t magic)
-{
- int fd, flags;
- u_char *p, *end;
- mode_t md;
- ssize_t n;
- njs_str_t content;
- njs_int_t ret;
- const char *path;
- njs_value_t flag, mode, encode, retval, *data, *callback,
- *options;
- njs_typed_array_t *array;
- njs_fs_calltype_t calltype;
- njs_array_buffer_t *buffer;
- const njs_buffer_encoding_t *encoding;
- char path_buf[NJS_MAX_PATH + 1];
+ {
+ .flags = NJS_EXTERN_METHOD,
+ .name.string = njs_str("writeFileSync"),
+ .writable = 1,
+ .configurable = 1,
+ .u.method = {
+ .native = njs_fs_write,
+ .magic8 = njs_fs_magic(NJS_FS_DIRECT, NJS_FS_TRUNC),
+ }
+ },
+
+};
+
+
+static njs_external_t njs_ext_dirent[] = {
+
+ {
+ .flags = NJS_EXTERN_PROPERTY | NJS_EXTERN_SYMBOL,
+ .name.symbol = NJS_SYMBOL_TO_STRING_TAG,
+ .u.property = {
+ .value = "Dirent",
+ }
+ },
+
+ {
+ .flags = NJS_EXTERN_METHOD,
+ .name.string = njs_str("constructor"),
+ .writable = 1,
+ .configurable = 1,
+ .u.method = {
+ .native = njs_fs_dirent_constructor,
+ }
+ },
+
+ {
+ .flags = NJS_EXTERN_METHOD,
+ .name.string = njs_str("isBlockDevice"),
+ .writable = 1,
+ .configurable = 1,
+ .u.method = {
+ .native = njs_fs_dirent_test,
+ .magic8 = DT_BLK,
+ }
+ },
+
+ {
+ .flags = NJS_EXTERN_METHOD,
+ .name.string = njs_str("isCharacterDevice"),
+ .writable = 1,
+ .configurable = 1,
+ .u.method = {
+ .native = njs_fs_dirent_test,
+ .magic8 = DT_CHR,
+ }
+ },
+
+ {
+ .flags = NJS_EXTERN_METHOD,
+ .name.string = njs_str("isDirectory"),
+ .writable = 1,
+ .configurable = 1,
+ .u.method = {
+ .native = njs_fs_dirent_test,
+ .magic8 = DT_DIR,
+ }
+ },
+
+ {
+ .flags = NJS_EXTERN_METHOD,
+ .name.string = njs_str("isFIFO"),
+ .writable = 1,
+ .configurable = 1,
+ .u.method = {
+ .native = njs_fs_dirent_test,
+ .magic8 = DT_FIFO,
+ }
+ },
+
+ {
+ .flags = NJS_EXTERN_METHOD,
+ .name.string = njs_str("isFile"),
+ .writable = 1,
+ .configurable = 1,
+ .u.method = {
+ .native = njs_fs_dirent_test,
+ .magic8 = DT_REG,
+ }
+ },
+
+ {
+ .flags = NJS_EXTERN_METHOD,
+ .name.string = njs_str("isSocket"),
+ .writable = 1,
+ .configurable = 1,
+ .u.method = {
+ .native = njs_fs_dirent_test,
+ .magic8 = DT_SOCK,
+ }
+ },
+
+ {
+ .flags = NJS_EXTERN_METHOD,
+ .name.string = njs_str("isSymbolicLink"),
+ .writable = 1,
+ .configurable = 1,
+ .u.method = {
+ .native = njs_fs_dirent_test,
+ .magic8 = DT_LNK,
+ }
+ },
+};
+
+
+static njs_external_t njs_ext_stats[] = {
+
+ {
+ .flags = NJS_EXTERN_PROPERTY | NJS_EXTERN_SYMBOL,
+ .name.symbol = NJS_SYMBOL_TO_STRING_TAG,
+ .u.property = {
+ .value = "Stats",
+ }
+ },
+
+ {
+ .flags = NJS_EXTERN_PROPERTY,
+ .name.string = njs_str("atime"),
+ .enumerable = 1,
+ .u.property = {
+ .handler = njs_fs_stats_prop,
+ .magic32 = njs_fs_magic2(NJS_FS_STAT_ATIME, NJS_DATE),
+ }
+ },
+
+ {
+ .flags = NJS_EXTERN_PROPERTY,
+ .name.string = njs_str("atimeMs"),
+ .enumerable = 1,
+ .u.property = {
+ .handler = njs_fs_stats_prop,
+ .magic32 = njs_fs_magic2(NJS_FS_STAT_ATIME, NJS_NUMBER),
+ }
+ },
+
+ {
+ .flags = NJS_EXTERN_PROPERTY,
+ .name.string = njs_str("birthtime"),
+ .enumerable = 1,
+ .u.property = {
+ .handler = njs_fs_stats_prop,
+ .magic32 = njs_fs_magic2(NJS_FS_STAT_BIRTHTIME, NJS_DATE),
+ }
+ },
+
+ {
+ .flags = NJS_EXTERN_PROPERTY,
+ .name.string = njs_str("birthtimeMs"),
+ .enumerable = 1,
+ .u.property = {
+ .handler = njs_fs_stats_prop,
+ .magic32 = njs_fs_magic2(NJS_FS_STAT_BIRTHTIME, NJS_NUMBER),
+ }
+ },
+
+ {
+ .flags = NJS_EXTERN_PROPERTY,
+ .name.string = njs_str("ctime"),
+ .enumerable = 1,
+ .u.property = {
+ .handler = njs_fs_stats_prop,
+ .magic32 = njs_fs_magic2(NJS_FS_STAT_CTIME, NJS_DATE),
+ }
+ },
+
+ {
+ .flags = NJS_EXTERN_PROPERTY,
+ .name.string = njs_str("ctimeMs"),
+ .enumerable = 1,
+ .u.property = {
+ .handler = njs_fs_stats_prop,
+ .magic32 = njs_fs_magic2(NJS_FS_STAT_CTIME, NJS_NUMBER),
+ }
+ },
+
+ {
+ .flags = NJS_EXTERN_PROPERTY,
+ .name.string = njs_str("blksize"),
+ .enumerable = 1,
+ .u.property = {
+ .handler = njs_fs_stats_prop,
+ .magic32 = njs_fs_magic2(NJS_FS_STAT_BLKSIZE, NJS_NUMBER),
+ }
+ },
+
+ {
+ .flags = NJS_EXTERN_PROPERTY,
+ .name.string = njs_str("blocks"),
+ .enumerable = 1,
+ .u.property = {
+ .handler = njs_fs_stats_prop,
+ .magic32 = njs_fs_magic2(NJS_FS_STAT_BLOCKS, NJS_NUMBER),
+ }
+ },
+
+ {
+ .flags = NJS_EXTERN_PROPERTY,
+ .name.string = njs_str("dev"),
+ .enumerable = 1,
+ .u.property = {
+ .handler = njs_fs_stats_prop,
+ .magic32 = njs_fs_magic2(NJS_FS_STAT_DEV, NJS_NUMBER),
+ }
+ },
+
+ {
+ .flags = NJS_EXTERN_PROPERTY,
+ .name.string = njs_str("gid"),
+ .enumerable = 1,
+ .u.property = {
+ .handler = njs_fs_stats_prop,
+ .magic32 = njs_fs_magic2(NJS_FS_STAT_GID, NJS_NUMBER),
+ }
+ },
+
+ {
+ .flags = NJS_EXTERN_PROPERTY,
+ .name.string = njs_str("ino"),
+ .enumerable = 1,
+ .u.property = {
+ .handler = njs_fs_stats_prop,
+ .magic32 = njs_fs_magic2(NJS_FS_STAT_INO, NJS_NUMBER),
+ }
+ },
+
+ {
+ .flags = NJS_EXTERN_PROPERTY,
+ .name.string = njs_str("mode"),
+ .enumerable = 1,
+ .u.property = {
+ .handler = njs_fs_stats_prop,
+ .magic32 = njs_fs_magic2(NJS_FS_STAT_MODE, NJS_NUMBER),
+ }
+ },
+
+ {
+ .flags = NJS_EXTERN_PROPERTY,
+ .name.string = njs_str("mtime"),
+ .enumerable = 1,
+ .u.property = {
+ .handler = njs_fs_stats_prop,
+ .magic32 = njs_fs_magic2(NJS_FS_STAT_MTIME, NJS_DATE),
+ }
+ },
+
+ {
+ .flags = NJS_EXTERN_PROPERTY,
+ .name.string = njs_str("mtimeMs"),
+ .enumerable = 1,
+ .u.property = {
+ .handler = njs_fs_stats_prop,
+ .magic32 = njs_fs_magic2(NJS_FS_STAT_MTIME, NJS_NUMBER),
+ }
+ },
+
+ {
+ .flags = NJS_EXTERN_PROPERTY,
+ .name.string = njs_str("nlink"),
+ .enumerable = 1,
+ .u.property = {
+ .handler = njs_fs_stats_prop,
+ .magic32 = njs_fs_magic2(NJS_FS_STAT_NLINK, NJS_NUMBER),
+ }
+ },
+
+ {
+ .flags = NJS_EXTERN_PROPERTY,
+ .name.string = njs_str("rdev"),
+ .enumerable = 1,
+ .u.property = {
+ .handler = njs_fs_stats_prop,
+ .magic32 = njs_fs_magic2(NJS_FS_STAT_RDEV, NJS_NUMBER),
+ }
+ },
+
+ {
+ .flags = NJS_EXTERN_PROPERTY,
+ .name.string = njs_str("size"),
+ .enumerable = 1,
+ .u.property = {
+ .handler = njs_fs_stats_prop,
+ .magic32 = njs_fs_magic2(NJS_FS_STAT_SIZE, NJS_NUMBER),
+ }
+ },
+
+ {
+ .flags = NJS_EXTERN_PROPERTY,
+ .name.string = njs_str("uid"),
+ .enumerable = 1,
+ .u.property = {
+ .handler = njs_fs_stats_prop,
+ .magic32 = njs_fs_magic2(NJS_FS_STAT_UID, NJS_NUMBER),
+ }
+ },
+
+ {
+ .flags = NJS_EXTERN_METHOD,
+ .name.string = njs_str("isBlockDevice"),
+ .writable = 1,
+ .configurable = 1,
+ .u.method = {
+ .native = njs_fs_stats_test,
+ .magic8 = DT_BLK,
+ }
+ },
+
+ {
+ .flags = NJS_EXTERN_METHOD,
+ .name.string = njs_str("isCharacterDevice"),
+ .writable = 1,
+ .configurable = 1,
+ .u.method = {
+ .native = njs_fs_stats_test,
+ .magic8 = DT_CHR,
+ }
+ },
+
+ {
+ .flags = NJS_EXTERN_METHOD,
+ .name.string = njs_str("isDirectory"),
+ .writable = 1,
+ .configurable = 1,
+ .u.method = {
+ .native = njs_fs_stats_test,
+ .magic8 = DT_DIR,
+ }
+ },
+
+ {
+ .flags = NJS_EXTERN_METHOD,
+ .name.string = njs_str("isFIFO"),
+ .writable = 1,
+ .configurable = 1,
+ .u.method = {
+ .native = njs_fs_stats_test,
+ .magic8 = DT_FIFO,
+ }
+ },
+
+ {
+ .flags = NJS_EXTERN_METHOD,
+ .name.string = njs_str("isFile"),
+ .writable = 1,
+ .configurable = 1,
+ .u.method = {
+ .native = njs_fs_stats_test,
+ .magic8 = DT_REG,
+ }
+ },
+
+ {
+ .flags = NJS_EXTERN_METHOD,
+ .name.string = njs_str("isSocket"),
+ .writable = 1,
+ .configurable = 1,
+ .u.method = {
+ .native = njs_fs_stats_test,
+ .magic8 = DT_SOCK,
+ }
+ },
+
+ {
+ .flags = NJS_EXTERN_METHOD,
+ .name.string = njs_str("isSymbolicLink"),
+ .writable = 1,
+ .configurable = 1,
+ .u.method = {
+ .native = njs_fs_stats_test,
+ .magic8 = DT_LNK,
+ }
+ },
+
+};
+
+
+static njs_int_t njs_fs_stats_proto_id;
+static njs_int_t njs_fs_dirent_proto_id;
+
+
+njs_module_t njs_fs_module = {
+ .name = njs_str("fs"),
+ .init = njs_fs_init,
+};
+
+
+static njs_int_t
+njs_fs_access(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
+ njs_index_t calltype)
+{
+ int md;
+ njs_int_t ret;
+ const char *path;
+ njs_value_t retval, *callback, *mode;
+ char path_buf[NJS_MAX_PATH + 1];
path = njs_fs_path(vm, path_buf, njs_arg(args, nargs, 1), "path");
if (njs_slow_path(path == NULL)) {
}
callback = NULL;
- calltype = magic & 3;
- options = njs_arg(args, nargs, 3);
+ mode = njs_arg(args, nargs, 2);
if (calltype == NJS_FS_CALLBACK) {
- callback = njs_arg(args, nargs, njs_min(nargs - 1, 4));
+ 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 (mode == callback) {
+ mode = njs_value_arg(&njs_value_undefined);
+ }
+ }
+
+ switch (mode->type) {
+ case NJS_UNDEFINED:
+ md = F_OK;
+ break;
+
+ case NJS_NUMBER:
+ md = njs_number(mode);
+ break;
+
+ default:
+ njs_type_error(vm, "\"mode\" must be a number");
+ return NJS_ERROR;
+ }
+
+ njs_set_undefined(&retval);
+
+ ret = access(path, md);
+ if (njs_slow_path(ret != 0)) {
+ ret = njs_fs_error(vm, "access", 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_mkdir(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
+ njs_index_t calltype)
+{
+ char *path;
+ mode_t md;
+ njs_int_t ret;
+ njs_value_t mode, recursive, retval, *callback, *options;
+ char path_buf[NJS_MAX_PATH + 1];
+
+ path = (char *) njs_fs_path(vm, path_buf, njs_arg(args, nargs, 1), "path");
+ if (njs_slow_path(path == NULL)) {
+ return NJS_ERROR;
+ }
+
+ 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(&flag);
njs_set_undefined(&mode);
- njs_set_undefined(&encode);
+ njs_set_false(&recursive);
switch (options->type) {
- case NJS_STRING:
- encode = *options;
+ case NJS_NUMBER:
+ mode = *options;
break;
case NJS_UNDEFINED:
default:
if (!njs_is_object(options)) {
njs_type_error(vm, "Unknown options type: \"%s\" "
- "(a string or object required)",
+ "(a number or object required)",
njs_type_string(options->type));
return NJS_ERROR;
}
- ret = njs_value_property(vm, options, njs_value_arg(&string_flag),
- &flag);
- if (njs_slow_path(ret == NJS_ERROR)) {
- return ret;
- }
-
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_encoding),
- &encode);
+ ret = njs_value_property(vm, options, njs_value_arg(&string_recursive),
+ &recursive);
if (njs_slow_path(ret == NJS_ERROR)) {
return ret;
}
}
- data = njs_arg(args, nargs, 2);
+ md = njs_fs_mode(vm, &mode, 0777);
+ if (njs_slow_path(md == (mode_t) -1)) {
+ return NJS_ERROR;
+ }
- switch (data->type) {
- case NJS_TYPED_ARRAY:
- case NJS_DATA_VIEW:
- array = njs_typed_array(data);
- buffer = array->buffer;
- if (njs_slow_path(njs_is_detached_buffer(buffer))) {
- njs_type_error(vm, "detached buffer");
+ ret = njs_fs_make_path(vm, path, md, njs_is_true(&recursive), &retval);
+
+ if (ret == NJS_OK) {
+ return njs_fs_result(vm, &retval, calltype, callback, 1);
+ }
+
+ return NJS_ERROR;
+}
+
+
+static njs_int_t
+njs_fs_read(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
+ njs_index_t calltype)
+{
+ int fd, flags;
+ njs_str_t data;
+ njs_int_t ret;
+ const char *path;
+ njs_value_t flag, encode, retval, *callback, *options;
+ struct stat sb;
+ const njs_buffer_encoding_t *encoding;
+ char path_buf[NJS_MAX_PATH + 1];
+
+ path = njs_fs_path(vm, path_buf, njs_arg(args, nargs, 1), "path");
+ if (njs_slow_path(path == NULL)) {
+ return NJS_ERROR;
+ }
+
+ callback = NULL;
+
+ options = njs_arg(args, nargs, 2);
+
+ if (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;
}
- content.start = &buffer->u.u8[array->offset];
- content.length = array->byte_length;
- break;
+ if (options == callback) {
+ options = njs_value_arg(&njs_value_undefined);
+ }
+ }
+ njs_set_undefined(&flag);
+ njs_set_undefined(&encode);
+
+ switch (options->type) {
case NJS_STRING:
+ encode = *options;
+ break;
+
+ case NJS_UNDEFINED:
+ break;
+
default:
- encoding = njs_buffer_encoding(vm, &encode);
- if (njs_slow_path(encoding == NULL)) {
+ if (!njs_is_object(options)) {
+ njs_type_error(vm, "Unknown options type: \"%s\" "
+ "(a string or object required)",
+ njs_type_string(options->type));
return NJS_ERROR;
}
- ret = njs_value_to_string(vm, &retval, data);
- if (njs_slow_path(ret != NJS_OK)) {
- return NJS_ERROR;
+ ret = njs_value_property(vm, options, njs_value_arg(&string_flag),
+ &flag);
+ if (njs_slow_path(ret == NJS_ERROR)) {
+ return ret;
}
- ret = njs_buffer_decode_string(vm, &retval, &retval, encoding);
- if (njs_slow_path(ret != NJS_OK)) {
- return NJS_ERROR;
+ ret = njs_value_property(vm, options, njs_value_arg(&string_encoding),
+ &encode);
+ if (njs_slow_path(ret == NJS_ERROR)) {
+ return ret;
}
-
- njs_string_get(&retval, &content);
- break;
}
- flags = njs_fs_flags(vm, &flag, O_CREAT | O_WRONLY);
+ flags = njs_fs_flags(vm, &flag, O_RDONLY);
if (njs_slow_path(flags == -1)) {
return NJS_ERROR;
}
- flags |= ((magic >> 2) == NJS_FS_APPEND) ? O_APPEND : O_TRUNC;
-
- md = njs_fs_mode(vm, &mode, 0666);
- if (njs_slow_path(md == (mode_t) -1)) {
- return NJS_ERROR;
+ encoding = NULL;
+ if (njs_is_defined(&encode)) {
+ encoding = njs_buffer_encoding(vm, &encode);
+ if (njs_slow_path(encoding == NULL)) {
+ return NJS_ERROR;
+ }
}
- fd = open(path, flags, md);
+ fd = open(path, flags);
if (njs_slow_path(fd < 0)) {
ret = njs_fs_error(vm, "open", strerror(errno), path, errno, &retval);
goto done;
}
- p = content.start;
- end = p + content.length;
-
- while (p < end) {
- n = write(fd, p, end - p);
- if (njs_slow_path(n == -1)) {
- if (errno == EINTR) {
- continue;
- }
-
- ret = njs_fs_error(vm, "write", strerror(errno), path, errno,
- &retval);
- goto done;
- }
-
- p += n;
- }
-
- ret = NJS_OK;
- njs_set_undefined(&retval);
-
-done:
-
- if (fd != -1) {
- (void) close(fd);
+ ret = fstat(fd, &sb);
+ if (njs_slow_path(ret == -1)) {
+ ret = njs_fs_error(vm, "stat", strerror(errno), path, errno, &retval);
+ goto done;
}
- if (ret == NJS_OK) {
- return njs_fs_result(vm, &retval, calltype, callback, 1);
+ if (njs_slow_path(!S_ISREG(sb.st_mode))) {
+ ret = njs_fs_error(vm, "stat", "File is not regular", path, 0, &retval);
+ goto done;
}
- return NJS_ERROR;
-}
-
-
-static njs_int_t
-njs_fs_rename(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
- njs_index_t calltype)
-{
- njs_int_t ret;
- const char *path, *newpath;
- njs_value_t retval, *callback;
- char path_buf[NJS_MAX_PATH + 1], newpath_buf[NJS_MAX_PATH + 1];
-
- callback = NULL;
+ data.start = NULL;
+ data.length = sb.st_size;
- if (calltype == NJS_FS_CALLBACK) {
- callback = njs_arg(args, nargs, 3);
- if (!njs_is_function(callback)) {
- njs_type_error(vm, "\"callback\" must be a function");
- return NJS_ERROR;
+ ret = njs_fs_fd_read(vm, fd, &data);
+ if (njs_slow_path(ret != NJS_OK)) {
+ if (ret == NJS_DECLINED) {
+ ret = njs_fs_error(vm, "read", strerror(errno), path, errno,
+ &retval);
}
- }
- path = njs_fs_path(vm, path_buf, njs_arg(args, nargs, 1), "oldPath");
- if (njs_slow_path(path == NULL)) {
- return NJS_ERROR;
+ goto done;
}
- newpath = njs_fs_path(vm, newpath_buf, njs_arg(args, nargs, 2), "newPath");
- if (njs_slow_path(newpath == NULL)) {
- return NJS_ERROR;
+ if (encoding == NULL) {
+ ret = njs_buffer_set(vm, &retval, data.start, data.length);
+
+ } else {
+ ret = encoding->encode(vm, &retval, &data);
+ njs_mp_free(vm->mem_pool, data.start);
}
- njs_set_undefined(&retval);
+done:
- ret = rename(path, newpath);
- if (njs_slow_path(ret != 0)) {
- ret = njs_fs_error(vm, "rename", strerror(errno), NULL, errno, &retval);
+ if (fd != -1) {
+ (void) close(fd);
}
if (ret == NJS_OK) {
- return njs_fs_result(vm, &retval, calltype, callback, 1);
+ return njs_fs_result(vm, &retval, calltype, callback, 2);
}
return NJS_ERROR;
static njs_int_t
-njs_fs_access(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
+njs_fs_readdir(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
njs_index_t calltype)
{
- int md;
- njs_int_t ret;
- const char *path;
- njs_value_t retval, *callback, *mode;
- char path_buf[NJS_MAX_PATH + 1];
+ DIR *dir;
+ njs_str_t s;
+ njs_int_t ret;
+ const char *path;
+ njs_value_t encode, types, ename, etype, retval,
+ *callback, *options, *value;
+ njs_array_t *results;
+ struct dirent *entry;
+ const njs_buffer_encoding_t *encoding;
+ char path_buf[NJS_MAX_PATH + 1];
+
+ static const njs_value_t string_types = njs_string("withFileTypes");
path = njs_fs_path(vm, path_buf, njs_arg(args, nargs, 1), "path");
if (njs_slow_path(path == NULL)) {
}
callback = NULL;
- mode = njs_arg(args, nargs, 2);
+ options = njs_arg(args, nargs, 2);
- if (calltype == NJS_FS_CALLBACK) {
+ 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 (mode == callback) {
- mode = njs_value_arg(&njs_value_undefined);
+ if (options == callback) {
+ options = njs_value_arg(&njs_value_undefined);
}
}
- switch (mode->type) {
- case NJS_UNDEFINED:
- md = F_OK;
+ njs_set_false(&types);
+ njs_set_undefined(&encode);
+
+ switch (options->type) {
+ case NJS_STRING:
+ encode = *options;
break;
- case NJS_NUMBER:
- md = njs_number(mode);
+ case NJS_UNDEFINED:
break;
default:
- njs_type_error(vm, "\"mode\" must be a number");
- return NJS_ERROR;
- }
+ if (!njs_is_object(options)) {
+ njs_type_error(vm, "Unknown options type: \"%s\" "
+ "(a string or object required)",
+ njs_type_string(options->type));
+ return NJS_ERROR;
+ }
- njs_set_undefined(&retval);
+ ret = njs_value_property(vm, options, njs_value_arg(&string_encoding),
+ &encode);
+ if (njs_slow_path(ret == NJS_ERROR)) {
+ return ret;
+ }
- ret = access(path, md);
- if (njs_slow_path(ret != 0)) {
- ret = njs_fs_error(vm, "access", strerror(errno), path, errno, &retval);
+ ret = njs_value_property(vm, options, njs_value_arg(&string_types),
+ &types);
+ if (njs_slow_path(ret == NJS_ERROR)) {
+ return ret;
+ }
}
- if (ret == NJS_OK) {
- return njs_fs_result(vm, &retval, calltype, callback, 1);
+ encoding = NULL;
+ if (!njs_is_string(&encode) || !njs_string_eq(&encode, &string_buffer)) {
+ encoding = njs_buffer_encoding(vm, &encode);
+ if (njs_slow_path(encoding == NULL)) {
+ return NJS_ERROR;
+ }
}
- return NJS_ERROR;
-}
-
-
-static njs_int_t
-njs_fs_symlink(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
- njs_index_t calltype)
-{
- njs_int_t ret;
- const char *target, *path;
- njs_value_t retval, *callback, *type;
- char target_buf[NJS_MAX_PATH + 1], path_buf[NJS_MAX_PATH + 1];
-
- target = njs_fs_path(vm, target_buf, njs_arg(args, nargs, 1), "target");
- if (njs_slow_path(target == NULL)) {
+ results = njs_array_alloc(vm, 1, 0, NJS_ARRAY_SPARE);
+ if (njs_slow_path(results == NULL)) {
return NJS_ERROR;
}
- path = njs_fs_path(vm, path_buf, njs_arg(args, nargs, 2), "path");
- if (njs_slow_path(path == NULL)) {
- return NJS_ERROR;
+ njs_set_array(&retval, results);
+
+ dir = opendir(path);
+ if (njs_slow_path(dir == NULL)) {
+ ret = njs_fs_error(vm, "opendir", strerror(errno), path, errno,
+ &retval);
+ goto done;
}
- callback = NULL;
- type = njs_arg(args, nargs, 3);
+ ret = NJS_OK;
- if (calltype == NJS_FS_CALLBACK) {
- callback = njs_arg(args, nargs, njs_min(nargs - 1, 4));
- if (!njs_is_function(callback)) {
- njs_type_error(vm, "\"callback\" must be a function");
- return NJS_ERROR;
- }
+ for ( ;; ) {
+ errno = 0;
+ entry = readdir(dir);
+ if (njs_slow_path(entry == NULL)) {
+ if (errno != 0) {
+ ret = njs_fs_error(vm, "readdir", strerror(errno), path, errno,
+ &retval);
+ }
- if (type == callback) {
- type = njs_value_arg(&njs_value_undefined);
+ goto done;
}
- }
-
- if (njs_slow_path(!njs_is_undefined(type) && !njs_is_string(type))) {
- njs_type_error(vm, "\"type\" must be a string");
- return NJS_ERROR;
- }
- njs_set_undefined(&retval);
+ s.start = (u_char *) entry->d_name;
+ s.length = njs_strlen(s.start);
- ret = symlink(target, path);
- if (njs_slow_path(ret != 0)) {
- ret = njs_fs_error(vm, "symlink", strerror(errno), path, errno,
- &retval);
- }
+ if ((s.length == 1 && s.start[0] == '.')
+ || (s.length == 2 && (s.start[0] == '.' && s.start[1] == '.')))
+ {
+ continue;
+ }
- if (ret == NJS_OK) {
- return njs_fs_result(vm, &retval, calltype, callback, 1);
- }
+ value = njs_array_push(vm, results);
+ if (njs_slow_path(value == NULL)) {
+ goto done;
+ }
- return NJS_ERROR;
-}
+ if (encoding == NULL) {
+ ret = njs_buffer_set(vm, &ename, s.start, s.length);
+ } else {
+ ret = encoding->encode(vm, &ename, &s);
+ }
-static njs_int_t
-njs_fs_unlink(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
- njs_index_t calltype)
-{
- njs_int_t ret;
- const char *path;
- njs_value_t retval, *callback;
- char path_buf[NJS_MAX_PATH + 1];
+ if (njs_slow_path(ret != NJS_OK)) {
+ goto done;
+ }
- path = njs_fs_path(vm, path_buf, njs_arg(args, nargs, 1), "path");
- if (njs_slow_path(path == NULL)) {
- return NJS_ERROR;
- }
+ if (njs_fast_path(!njs_is_true(&types))) {
+ *value = ename;
+ continue;
+ }
- callback = NULL;
+ njs_set_number(&etype, njs_dentry_type(entry));
- if (calltype == NJS_FS_CALLBACK) {
- callback = njs_arg(args, nargs, 2);
- if (!njs_is_function(callback)) {
- njs_type_error(vm, "\"callback\" must be a function");
- return NJS_ERROR;
+ ret = njs_fs_dirent_create(vm, &ename, &etype, value);
+ if (njs_slow_path(ret != NJS_OK)) {
+ goto done;
}
}
- njs_set_undefined(&retval);
+done:
- ret = unlink(path);
- if (njs_slow_path(ret != 0)) {
- ret = njs_fs_error(vm, "unlink", strerror(errno), path, errno, &retval);
+ if (dir != NULL) {
+ (void) closedir(dir);
}
if (ret == NJS_OK) {
- return njs_fs_result(vm, &retval, calltype, callback, 1);
+ return njs_fs_result(vm, &retval, calltype, callback, 2);
}
return NJS_ERROR;
}
-static njs_int_t
-njs_fs_mkdir(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
- njs_index_t calltype)
-{
- char *path;
- mode_t md;
- njs_int_t ret;
- njs_value_t mode, recursive, retval, *callback, *options;
- char path_buf[NJS_MAX_PATH + 1];
-
- path = (char *) njs_fs_path(vm, path_buf, njs_arg(args, nargs, 1), "path");
- if (njs_slow_path(path == NULL)) {
- return NJS_ERROR;
- }
-
- 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;
+static njs_int_t
+njs_fs_rename(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
+ njs_index_t calltype)
+{
+ njs_int_t ret;
+ const char *path, *newpath;
+ njs_value_t retval, *callback;
+ char path_buf[NJS_MAX_PATH + 1], newpath_buf[NJS_MAX_PATH + 1];
- case NJS_UNDEFINED:
- break;
+ callback = NULL;
- default:
- if (!njs_is_object(options)) {
- njs_type_error(vm, "Unknown options type: \"%s\" "
- "(a number or object required)",
- njs_type_string(options->type));
+ if (calltype == NJS_FS_CALLBACK) {
+ callback = njs_arg(args, nargs, 3);
+ if (!njs_is_function(callback)) {
+ njs_type_error(vm, "\"callback\" must be a function");
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;
- }
+ path = njs_fs_path(vm, path_buf, njs_arg(args, nargs, 1), "oldPath");
+ if (njs_slow_path(path == NULL)) {
+ return NJS_ERROR;
}
- md = njs_fs_mode(vm, &mode, 0777);
- if (njs_slow_path(md == (mode_t) -1)) {
+ newpath = njs_fs_path(vm, newpath_buf, njs_arg(args, nargs, 2), "newPath");
+ if (njs_slow_path(newpath == NULL)) {
return NJS_ERROR;
}
- ret = njs_fs_make_path(vm, path, md, njs_is_true(&recursive), &retval);
+ njs_set_undefined(&retval);
+
+ ret = rename(path, newpath);
+ if (njs_slow_path(ret != 0)) {
+ ret = njs_fs_error(vm, "rename", strerror(errno), NULL, errno, &retval);
+ }
if (ret == NJS_OK) {
return njs_fs_result(vm, &retval, calltype, callback, 1);
static njs_int_t
-njs_fs_readdir(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
- njs_index_t calltype)
+njs_fs_stat(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
+ njs_index_t magic)
{
- DIR *dir;
- njs_str_t s;
- njs_int_t ret;
- const char *path;
- njs_value_t encode, types, ename, etype, retval,
- *callback, *options, *value;
- njs_array_t *results;
- struct dirent *entry;
- const njs_buffer_encoding_t *encoding;
- char path_buf[NJS_MAX_PATH + 1];
+ njs_int_t ret;
+ njs_bool_t throw;
+ struct stat sb;
+ const char *path;
+ njs_value_t retval, *callback, *options;
+ njs_fs_calltype_t calltype;
+ char path_buf[NJS_MAX_PATH + 1];
- static const njs_value_t string_types = njs_string("withFileTypes");
+ static const njs_value_t string_bigint = njs_string("bigint");
+ static const njs_value_t string_throw = njs_string("throwIfNoEntry");
path = njs_fs_path(vm, path_buf, njs_arg(args, nargs, 1), "path");
if (njs_slow_path(path == NULL)) {
}
callback = NULL;
+ calltype = magic & 3;
options = njs_arg(args, nargs, 2);
if (njs_slow_path(calltype == NJS_FS_CALLBACK)) {
}
}
- njs_set_false(&types);
- njs_set_undefined(&encode);
+ throw = 1;
switch (options->type) {
- case NJS_STRING:
- encode = *options;
- break;
-
case NJS_UNDEFINED:
break;
default:
if (!njs_is_object(options)) {
njs_type_error(vm, "Unknown options type: \"%s\" "
- "(a string or object required)",
+ "(an object required)",
njs_type_string(options->type));
return NJS_ERROR;
}
- ret = njs_value_property(vm, options, njs_value_arg(&string_encoding),
- &encode);
+ ret = njs_value_property(vm, options, njs_value_arg(&string_bigint),
+ &retval);
if (njs_slow_path(ret == NJS_ERROR)) {
return ret;
}
- ret = njs_value_property(vm, options, njs_value_arg(&string_types),
- &types);
- if (njs_slow_path(ret == NJS_ERROR)) {
- return ret;
+ if (njs_bool(&retval)) {
+ njs_type_error(vm, "\"bigint\" is not supported");
+ return NJS_ERROR;
+ }
+
+ if (calltype == NJS_FS_DIRECT) {
+ ret = njs_value_property(vm, options, njs_value_arg(&string_throw),
+ &retval);
+ if (njs_slow_path(ret == NJS_ERROR)) {
+ return ret;
+ }
+
+ throw = njs_bool(&retval);
}
}
- encoding = NULL;
- if (!njs_is_string(&encode) || !njs_string_eq(&encode, &string_buffer)) {
- encoding = njs_buffer_encoding(vm, &encode);
- if (njs_slow_path(encoding == NULL)) {
- return NJS_ERROR;
+ ret = ((magic >> 2) == NJS_FS_STAT) ? stat(path, &sb) : lstat(path, &sb);
+ if (njs_slow_path(ret != 0)) {
+ if (errno != ENOENT || throw) {
+ ret = njs_fs_error(vm,
+ ((magic >> 2) == NJS_FS_STAT) ? "stat" : "lstat",
+ strerror(errno), path, errno, &retval);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return NJS_ERROR;
+ }
+ } else {
+ njs_set_undefined(&retval);
}
+
+ return njs_fs_result(vm, &retval, calltype, callback, 2);
}
- results = njs_array_alloc(vm, 1, 0, NJS_ARRAY_SPARE);
- if (njs_slow_path(results == NULL)) {
+ ret = njs_fs_stats_create(vm, &sb, &retval);
+ if (njs_slow_path(ret != NJS_OK)) {
return NJS_ERROR;
}
- njs_set_array(&retval, results);
+ return njs_fs_result(vm, &retval, calltype, callback, 2);
+}
- dir = opendir(path);
- if (njs_slow_path(dir == NULL)) {
- ret = njs_fs_error(vm, "opendir", strerror(errno), path, errno,
- &retval);
- goto done;
- }
- ret = NJS_OK;
+static njs_int_t
+njs_fs_symlink(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
+ njs_index_t calltype)
+{
+ njs_int_t ret;
+ const char *target, *path;
+ njs_value_t retval, *callback, *type;
+ char target_buf[NJS_MAX_PATH + 1], path_buf[NJS_MAX_PATH + 1];
- for ( ;; ) {
- errno = 0;
- entry = readdir(dir);
- if (njs_slow_path(entry == NULL)) {
- if (errno != 0) {
- ret = njs_fs_error(vm, "readdir", strerror(errno), path, errno,
- &retval);
- }
+ target = njs_fs_path(vm, target_buf, njs_arg(args, nargs, 1), "target");
+ if (njs_slow_path(target == NULL)) {
+ return NJS_ERROR;
+ }
- goto done;
- }
+ path = njs_fs_path(vm, path_buf, njs_arg(args, nargs, 2), "path");
+ if (njs_slow_path(path == NULL)) {
+ return NJS_ERROR;
+ }
- s.start = (u_char *) entry->d_name;
- s.length = njs_strlen(s.start);
+ callback = NULL;
+ type = njs_arg(args, nargs, 3);
- if ((s.length == 1 && s.start[0] == '.')
- || (s.length == 2 && (s.start[0] == '.' && s.start[1] == '.')))
- {
- continue;
+ if (calltype == NJS_FS_CALLBACK) {
+ callback = njs_arg(args, nargs, njs_min(nargs - 1, 4));
+ if (!njs_is_function(callback)) {
+ njs_type_error(vm, "\"callback\" must be a function");
+ return NJS_ERROR;
}
- value = njs_array_push(vm, results);
- if (njs_slow_path(value == NULL)) {
- goto done;
+ if (type == callback) {
+ type = njs_value_arg(&njs_value_undefined);
}
+ }
- if (encoding == NULL) {
- ret = njs_buffer_set(vm, &ename, s.start, s.length);
+ if (njs_slow_path(!njs_is_undefined(type) && !njs_is_string(type))) {
+ njs_type_error(vm, "\"type\" must be a string");
+ return NJS_ERROR;
+ }
- } else {
- ret = encoding->encode(vm, &ename, &s);
- }
+ njs_set_undefined(&retval);
- if (njs_slow_path(ret != NJS_OK)) {
- goto done;
- }
+ ret = symlink(target, path);
+ if (njs_slow_path(ret != 0)) {
+ ret = njs_fs_error(vm, "symlink", strerror(errno), path, errno,
+ &retval);
+ }
- if (njs_fast_path(!njs_is_true(&types))) {
- *value = ename;
- continue;
- }
+ if (ret == NJS_OK) {
+ return njs_fs_result(vm, &retval, calltype, callback, 1);
+ }
- njs_set_number(&etype, njs_dentry_type(entry));
+ return NJS_ERROR;
+}
- ret = njs_fs_dirent_create(vm, &ename, &etype, value);
- if (njs_slow_path(ret != NJS_OK)) {
- goto done;
+
+static njs_int_t
+njs_fs_unlink(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
+ njs_index_t calltype)
+{
+ njs_int_t ret;
+ const char *path;
+ njs_value_t retval, *callback;
+ char path_buf[NJS_MAX_PATH + 1];
+
+ path = njs_fs_path(vm, path_buf, njs_arg(args, nargs, 1), "path");
+ if (njs_slow_path(path == NULL)) {
+ return NJS_ERROR;
+ }
+
+ callback = NULL;
+
+ if (calltype == NJS_FS_CALLBACK) {
+ callback = njs_arg(args, nargs, 2);
+ if (!njs_is_function(callback)) {
+ njs_type_error(vm, "\"callback\" must be a function");
+ return NJS_ERROR;
}
}
-done:
+ njs_set_undefined(&retval);
- if (dir != NULL) {
- (void) closedir(dir);
+ ret = unlink(path);
+ if (njs_slow_path(ret != 0)) {
+ ret = njs_fs_error(vm, "unlink", strerror(errno), path, errno, &retval);
}
if (ret == NJS_OK) {
- return njs_fs_result(vm, &retval, calltype, callback, 2);
+ return njs_fs_result(vm, &retval, calltype, callback, 1);
}
return NJS_ERROR;
static njs_int_t
-njs_fs_stat(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
+njs_fs_write(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
njs_index_t magic)
{
- njs_int_t ret;
- njs_bool_t throw;
- struct stat sb;
- const char *path;
- njs_value_t retval, *callback, *options;
- njs_fs_calltype_t calltype;
- char path_buf[NJS_MAX_PATH + 1];
-
- static const njs_value_t string_bigint = njs_string("bigint");
- static const njs_value_t string_throw = njs_string("throwIfNoEntry");
+ int fd, flags;
+ u_char *p, *end;
+ mode_t md;
+ ssize_t n;
+ njs_str_t content;
+ njs_int_t ret;
+ const char *path;
+ njs_value_t flag, mode, encode, retval, *data, *callback,
+ *options;
+ njs_typed_array_t *array;
+ njs_fs_calltype_t calltype;
+ njs_array_buffer_t *buffer;
+ const njs_buffer_encoding_t *encoding;
+ char path_buf[NJS_MAX_PATH + 1];
path = njs_fs_path(vm, path_buf, njs_arg(args, nargs, 1), "path");
if (njs_slow_path(path == NULL)) {
callback = NULL;
calltype = magic & 3;
- options = njs_arg(args, nargs, 2);
+ options = njs_arg(args, nargs, 3);
- if (njs_slow_path(calltype == NJS_FS_CALLBACK)) {
- callback = njs_arg(args, nargs, njs_min(nargs - 1, 3));
+ if (calltype == NJS_FS_CALLBACK) {
+ callback = njs_arg(args, nargs, njs_min(nargs - 1, 4));
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);
}
}
- throw = 1;
+ njs_set_undefined(&flag);
+ njs_set_undefined(&mode);
+ njs_set_undefined(&encode);
switch (options->type) {
+ case NJS_STRING:
+ encode = *options;
+ break;
+
case NJS_UNDEFINED:
break;
default:
if (!njs_is_object(options)) {
njs_type_error(vm, "Unknown options type: \"%s\" "
- "(an object required)",
+ "(a string or object required)",
njs_type_string(options->type));
return NJS_ERROR;
}
- ret = njs_value_property(vm, options, njs_value_arg(&string_bigint),
- &retval);
+ ret = njs_value_property(vm, options, njs_value_arg(&string_flag),
+ &flag);
if (njs_slow_path(ret == NJS_ERROR)) {
return ret;
}
- if (njs_bool(&retval)) {
- njs_type_error(vm, "\"bigint\" is not supported");
+ 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_encoding),
+ &encode);
+ if (njs_slow_path(ret == NJS_ERROR)) {
+ return ret;
+ }
+ }
+
+ data = njs_arg(args, nargs, 2);
+
+ switch (data->type) {
+ case NJS_TYPED_ARRAY:
+ case NJS_DATA_VIEW:
+ array = njs_typed_array(data);
+ buffer = array->buffer;
+ if (njs_slow_path(njs_is_detached_buffer(buffer))) {
+ njs_type_error(vm, "detached buffer");
return NJS_ERROR;
}
- if (calltype == NJS_FS_DIRECT) {
- ret = njs_value_property(vm, options, njs_value_arg(&string_throw),
- &retval);
- if (njs_slow_path(ret == NJS_ERROR)) {
- return ret;
- }
+ content.start = &buffer->u.u8[array->offset];
+ content.length = array->byte_length;
+ break;
- throw = njs_bool(&retval);
+ case NJS_STRING:
+ default:
+ encoding = njs_buffer_encoding(vm, &encode);
+ if (njs_slow_path(encoding == NULL)) {
+ return NJS_ERROR;
+ }
+
+ ret = njs_value_to_string(vm, &retval, data);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return NJS_ERROR;
+ }
+
+ ret = njs_buffer_decode_string(vm, &retval, &retval, encoding);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return NJS_ERROR;
}
+
+ njs_string_get(&retval, &content);
+ break;
}
- ret = ((magic >> 2) == NJS_FS_STAT) ? stat(path, &sb) : lstat(path, &sb);
- if (njs_slow_path(ret != 0)) {
- if (errno != ENOENT || throw) {
- ret = njs_fs_error(vm,
- ((magic >> 2) == NJS_FS_STAT) ? "stat" : "lstat",
- strerror(errno), path, errno, &retval);
- if (njs_slow_path(ret != NJS_OK)) {
- return NJS_ERROR;
+ flags = njs_fs_flags(vm, &flag, O_CREAT | O_WRONLY);
+ if (njs_slow_path(flags == -1)) {
+ return NJS_ERROR;
+ }
+
+ flags |= ((magic >> 2) == NJS_FS_APPEND) ? O_APPEND : O_TRUNC;
+
+ md = njs_fs_mode(vm, &mode, 0666);
+ if (njs_slow_path(md == (mode_t) -1)) {
+ return NJS_ERROR;
+ }
+
+ fd = open(path, flags, md);
+ if (njs_slow_path(fd < 0)) {
+ ret = njs_fs_error(vm, "open", strerror(errno), path, errno, &retval);
+ goto done;
+ }
+
+ p = content.start;
+ end = p + content.length;
+
+ while (p < end) {
+ n = write(fd, p, end - p);
+ if (njs_slow_path(n == -1)) {
+ if (errno == EINTR) {
+ continue;
}
- } else {
- njs_set_undefined(&retval);
+
+ ret = njs_fs_error(vm, "write", strerror(errno), path, errno,
+ &retval);
+ goto done;
}
- return njs_fs_result(vm, &retval, calltype, callback, 2);
+ p += n;
}
- ret = njs_fs_stats_create(vm, &sb, &retval);
- if (njs_slow_path(ret != NJS_OK)) {
- return NJS_ERROR;
+ ret = NJS_OK;
+ njs_set_undefined(&retval);
+
+done:
+
+ if (fd != -1) {
+ (void) close(fd);
}
- return njs_fs_result(vm, &retval, calltype, callback, 2);
+ if (ret == NJS_OK) {
+ return njs_fs_result(vm, &retval, calltype, callback, 1);
+ }
+
+ return NJS_ERROR;
}
njs_fs_dirent_create(njs_vm_t *vm, njs_value_t *name, njs_value_t *type,
njs_value_t *retval)
{
- njs_int_t ret;
- njs_object_t *object;
+ njs_int_t ret;
static const njs_value_t string_name = njs_string("name");
static const njs_value_t string_type = njs_string("type");
- object = njs_object_alloc(vm);
- if (njs_slow_path(object == NULL)) {
- return NJS_ERROR;
+ ret = njs_vm_external_create(vm, retval, njs_fs_dirent_proto_id, NULL, 0);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
}
- object->__proto__ = &vm->prototypes[NJS_OBJ_TYPE_FS_DIRENT].object;
-
- njs_set_object(retval, object);
-
ret = njs_value_property_set(vm, retval, njs_value_arg(&string_name),
name);
if (njs_slow_path(ret != NJS_OK)) {
}
/* TODO: use a private symbol as a key. */
- ret = njs_value_property_set(vm, retval, njs_value_arg(&string_type),
- type);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
-
- return NJS_OK;
+ return njs_value_property_set(vm, retval, njs_value_arg(&string_type),
+ type);
}
static njs_int_t
-njs_dirent_constructor(njs_vm_t *vm, njs_value_t *args,
+njs_fs_dirent_constructor(njs_vm_t *vm, njs_value_t *args,
njs_uint_t nargs, njs_index_t unused)
{
if (njs_slow_path(!vm->top_frame->ctor)) {
}
return njs_fs_dirent_create(vm, njs_arg(args, nargs, 1),
- njs_arg(args, nargs, 2), &vm->retval);
-}
-
-
-static const njs_object_prop_t njs_dirent_constructor_properties[] =
-{
- {
- .type = NJS_PROPERTY,
- .name = njs_string("name"),
- .value = njs_string("Dirent"),
- .configurable = 1,
- },
-
- {
- .type = NJS_PROPERTY,
- .name = njs_string("length"),
- .value = njs_value(NJS_NUMBER, 1, 2.0),
- .configurable = 1,
- },
-
- {
- .type = NJS_PROPERTY_HANDLER,
- .name = njs_string("prototype"),
- .value = njs_prop_handler(njs_object_prototype_create),
- },
-};
-
-
-const njs_object_init_t njs_dirent_constructor_init = {
- njs_dirent_constructor_properties,
- njs_nitems(njs_dirent_constructor_properties),
-};
-
-
-static njs_int_t
-njs_fs_dirent_test(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
- njs_index_t testtype)
-{
- njs_int_t ret;
- njs_value_t type, *this;
-
- static const njs_value_t string_type = njs_string("type");
-
- this = njs_argument(args, 0);
-
- ret = njs_value_property(vm, this, njs_value_arg(&string_type), &type);
- if (njs_slow_path(ret == NJS_ERROR)) {
- return ret;
- }
-
- if (njs_slow_path(njs_is_number(&type)
- && (njs_number(&type) == NJS_DT_INVALID)))
- {
- njs_internal_error(vm, "dentry type is not supported on this platform");
- return NJS_ERROR;
- }
-
- njs_set_boolean(&vm->retval,
- njs_is_number(&type) && testtype == njs_number(&type));
-
- return NJS_OK;
-}
-
-
-static const njs_object_prop_t njs_dirent_prototype_properties[] =
-{
- {
- .type = NJS_PROPERTY,
- .name = njs_wellknown_symbol(NJS_SYMBOL_TO_STRING_TAG),
- .value = njs_string("Dirent"),
- .configurable = 1,
- },
-
- {
- .type = NJS_PROPERTY_HANDLER,
- .name = njs_string("constructor"),
- .value = njs_prop_handler(njs_object_prototype_create_constructor),
- .writable = 1,
- .configurable = 1,
- },
-
- {
- .type = NJS_PROPERTY,
- .name = njs_string("isDirectory"),
- .value = njs_native_function2(njs_fs_dirent_test, 0, DT_DIR),
- .writable = 1,
- .configurable = 1,
- },
-
- {
- .type = NJS_PROPERTY,
- .name = njs_string("isFile"),
- .value = njs_native_function2(njs_fs_dirent_test, 0, DT_REG),
- .writable = 1,
- .configurable = 1,
- },
-
- {
- .type = NJS_PROPERTY,
- .name = njs_string("isBlockDevice"),
- .value = njs_native_function2(njs_fs_dirent_test, 0, DT_BLK),
- .writable = 1,
- .configurable = 1,
- },
-
- {
- .type = NJS_PROPERTY,
- .name = njs_long_string("isCharacterDevice"),
- .value = njs_native_function2(njs_fs_dirent_test, 0, DT_CHR),
- .writable = 1,
- .configurable = 1,
- },
+ njs_arg(args, nargs, 2), &vm->retval);
+}
+
+static const njs_object_prop_t njs_dirent_constructor_properties[] =
+{
{
.type = NJS_PROPERTY,
- .name = njs_string("isSymbolicLink"),
- .value = njs_native_function2(njs_fs_dirent_test, 0, DT_LNK),
- .writable = 1,
+ .name = njs_string("name"),
+ .value = njs_string("Dirent"),
.configurable = 1,
},
{
.type = NJS_PROPERTY,
- .name = njs_string("isFIFO"),
- .value = njs_native_function2(njs_fs_dirent_test, 0, DT_FIFO),
- .writable = 1,
+ .name = njs_string("length"),
+ .value = njs_value(NJS_NUMBER, 1, 2.0),
.configurable = 1,
},
{
- .type = NJS_PROPERTY,
- .name = njs_string("isSocket"),
- .value = njs_native_function2(njs_fs_dirent_test, 0, DT_SOCK),
- .writable = 1,
- .configurable = 1,
+ .type = NJS_PROPERTY_HANDLER,
+ .name = njs_string("prototype"),
+ .value = njs_prop_handler(njs_object_prototype_create),
},
};
-const njs_object_init_t njs_dirent_prototype_init = {
- njs_dirent_prototype_properties,
- njs_nitems(njs_dirent_prototype_properties),
+const njs_object_init_t njs_dirent_constructor_init = {
+ njs_dirent_constructor_properties,
+ njs_nitems(njs_dirent_constructor_properties),
};
-const njs_object_type_init_t njs_dirent_type_init = {
- .constructor = njs_native_ctor(njs_dirent_constructor, 2, 0),
- .prototype_props = &njs_dirent_prototype_init,
- .constructor_props = &njs_dirent_constructor_init,
- .prototype_value = { .object = { .type = NJS_OBJECT } },
-};
+static njs_int_t
+njs_fs_dirent_test(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
+ njs_index_t testtype)
+{
+ njs_int_t ret;
+ njs_value_t type, *this;
+
+ static const njs_value_t string_type = njs_string("type");
+
+ this = njs_argument(args, 0);
+
+ ret = njs_value_property(vm, this, njs_value_arg(&string_type), &type);
+ if (njs_slow_path(ret == NJS_ERROR)) {
+ return ret;
+ }
+
+ if (njs_slow_path(njs_is_number(&type)
+ && (njs_number(&type) == NJS_DT_INVALID)))
+ {
+ njs_internal_error(vm, "dentry type is not supported on this platform");
+ return NJS_ERROR;
+ }
+
+ njs_set_boolean(&vm->retval,
+ njs_is_number(&type) && testtype == njs_number(&type));
+
+ return NJS_OK;
+}
static void
static njs_int_t
njs_fs_stats_create(njs_vm_t *vm, struct stat *st, njs_value_t *retval)
{
- njs_stat_t *copy;
- njs_object_value_t *stat;
+ njs_stat_t *stat;
- stat = njs_object_value_alloc(vm, NJS_OBJ_TYPE_FS_STATS, 0, NULL);
+ stat = njs_mp_alloc(vm->mem_pool, sizeof(njs_stat_t));
if (njs_slow_path(stat == NULL)) {
- return NJS_ERROR;
- }
-
- stat->object.shared_hash =
- vm->prototypes[NJS_OBJ_TYPE_FS_STATS].object.shared_hash;
-
- copy = njs_mp_alloc(vm->mem_pool, sizeof(njs_stat_t));
- if (copy == NULL) {
njs_memory_error(vm);
return NJS_ERROR;
}
- njs_fs_to_stat(copy, st);
-
- njs_set_data(&stat->value, copy, NJS_DATA_TAG_FS_STAT);
- njs_set_object_value(retval, stat);
-
- return NJS_OK;
-}
-
+ njs_fs_to_stat(stat, st);
-static njs_int_t
-njs_stats_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
- njs_index_t unused)
-{
- njs_type_error(vm, "Stats is not a constructor");
- return NJS_ERROR;
+ return njs_vm_external_create(vm, retval, njs_fs_stats_proto_id,
+ stat, 0);
}
njs_fs_stats_test(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
njs_index_t testtype)
{
- unsigned mask;
- njs_stat_t *st;
- njs_value_t *this;
-
- this = njs_argument(args, 0);
+ unsigned mask;
+ njs_stat_t *st;
- if (njs_slow_path(!njs_is_object_data(this, NJS_DATA_TAG_FS_STAT))) {
+ st = njs_vm_external(vm, njs_fs_stats_proto_id, njs_argument(args, 0));
+ if (njs_slow_path(st == NULL)) {
return NJS_DECLINED;
}
- st = njs_object_data(this);
-
switch (testtype) {
case DT_DIR:
mask = S_IFDIR;
#define njs_fs_time_ms(ts) ((ts)->tv_sec * 1000.0 + (ts)->tv_nsec / 1000000.0)
- if (njs_slow_path(!njs_is_object_data(value, NJS_DATA_TAG_FS_STAT))) {
+ st = njs_vm_external(vm, njs_fs_stats_proto_id, value);
+ if (njs_slow_path(st == NULL)) {
return NJS_DECLINED;
}
- st = njs_object_data(value);
-
- switch (prop->value.data.magic16) {
+ switch (prop->value.data.magic32 & 0xf) {
case NJS_FS_STAT_DEV:
v = st->st_dev;
break;
v = st->st_blksize;
break;
- case NJS_FS_STAT_BLOCKS:
- v = st->st_blocks;
- break;
-
- case NJS_FS_STAT_ATIME:
- v = njs_fs_time_ms(&st->st_atim);
- break;
-
- case NJS_FS_STAT_BIRTHTIME:
- v = njs_fs_time_ms(&st->st_birthtim);
- break;
-
- case NJS_FS_STAT_CTIME:
- v = njs_fs_time_ms(&st->st_ctim);
- break;
-
- case NJS_FS_STAT_MTIME:
- default:
- v = njs_fs_time_ms(&st->st_mtim);
- break;
- }
-
- switch (prop->value.data.magic32) {
- case NJS_NUMBER:
- njs_set_number(retval, v);
- break;
-
- case NJS_DATE:
- default:
- date = njs_date_alloc(vm, v);
- if (njs_slow_path(date == NULL)) {
- return NJS_ERROR;
- }
-
- njs_set_date(retval, date);
- break;
- }
-
- return NJS_OK;
-}
-
-
-static const njs_object_prop_t njs_stats_constructor_properties[] =
-{
- {
- .type = NJS_PROPERTY,
- .name = njs_string("name"),
- .value = njs_string("Stats"),
- .configurable = 1,
- },
-
- {
- .type = NJS_PROPERTY,
- .name = njs_string("length"),
- .value = njs_value(NJS_NUMBER, 1, 0),
- .configurable = 1,
- },
-
- {
- .type = NJS_PROPERTY_HANDLER,
- .name = njs_string("prototype"),
- .value = njs_prop_handler(njs_object_prototype_create),
- },
-};
-
-
-const njs_object_init_t njs_stats_constructor_init = {
- njs_stats_constructor_properties,
- njs_nitems(njs_stats_constructor_properties),
-};
-
-
-static const njs_object_prop_t njs_stats_prototype_properties[] =
-{
- {
- .type = NJS_PROPERTY,
- .name = njs_wellknown_symbol(NJS_SYMBOL_TO_STRING_TAG),
- .value = njs_string("Stats"),
- .configurable = 1,
- },
-
- {
- .type = NJS_PROPERTY_HANDLER,
- .name = njs_string("constructor"),
- .value = njs_prop_handler(njs_object_prototype_create_constructor),
- .writable = 1,
- .configurable = 1,
- },
-
- {
- .type = NJS_PROPERTY,
- .name = njs_string("isBlockDevice"),
- .value = njs_native_function2(njs_fs_stats_test, 0, DT_BLK),
- .writable = 1,
- .configurable = 1,
- },
-
- {
- .type = NJS_PROPERTY,
- .name = njs_long_string("isCharacterDevice"),
- .value = njs_native_function2(njs_fs_stats_test, 0, DT_CHR),
- .writable = 1,
- .configurable = 1,
- },
-
- {
- .type = NJS_PROPERTY,
- .name = njs_string("isDirectory"),
- .value = njs_native_function2(njs_fs_stats_test, 0, DT_DIR),
- .writable = 1,
- .configurable = 1,
- },
-
- {
- .type = NJS_PROPERTY,
- .name = njs_string("isFIFO"),
- .value = njs_native_function2(njs_fs_stats_test, 0, DT_FIFO),
- .writable = 1,
- .configurable = 1,
- },
-
- {
- .type = NJS_PROPERTY,
- .name = njs_string("isFile"),
- .value = njs_native_function2(njs_fs_stats_test, 0, DT_REG),
- .writable = 1,
- .configurable = 1,
- },
-
- {
- .type = NJS_PROPERTY,
- .name = njs_string("isSocket"),
- .value = njs_native_function2(njs_fs_stats_test, 0, DT_SOCK),
- .writable = 1,
- .configurable = 1,
- },
-
- {
- .type = NJS_PROPERTY,
- .name = njs_string("isSymbolicLink"),
- .value = njs_native_function2(njs_fs_stats_test, 0, DT_LNK),
- .writable = 1,
- .configurable = 1,
- },
-
- {
- .type = NJS_PROPERTY_HANDLER,
- .name = njs_string("dev"),
- .value = njs_prop_handler2(njs_fs_stats_prop, NJS_FS_STAT_DEV,
- NJS_NUMBER),
- .enumerable = 1,
- },
-
- {
- .type = NJS_PROPERTY_HANDLER,
- .name = njs_string("ino"),
- .value = njs_prop_handler2(njs_fs_stats_prop, NJS_FS_STAT_INO,
- NJS_NUMBER),
- .enumerable = 1,
- },
-
- {
- .type = NJS_PROPERTY_HANDLER,
- .name = njs_string("mode"),
- .value = njs_prop_handler2(njs_fs_stats_prop, NJS_FS_STAT_MODE,
- NJS_NUMBER),
- .enumerable = 1,
- },
-
- {
- .type = NJS_PROPERTY_HANDLER,
- .name = njs_string("nlink"),
- .value = njs_prop_handler2(njs_fs_stats_prop, NJS_FS_STAT_NLINK,
- NJS_NUMBER),
- .enumerable = 1,
- },
-
- {
- .type = NJS_PROPERTY_HANDLER,
- .name = njs_string("uid"),
- .value = njs_prop_handler2(njs_fs_stats_prop, NJS_FS_STAT_UID,
- NJS_NUMBER),
- .enumerable = 1,
- },
-
- {
- .type = NJS_PROPERTY_HANDLER,
- .name = njs_string("gid"),
- .value = njs_prop_handler2(njs_fs_stats_prop, NJS_FS_STAT_GID,
- NJS_NUMBER),
- .enumerable = 1,
- },
-
- {
- .type = NJS_PROPERTY_HANDLER,
- .name = njs_string("rdev"),
- .value = njs_prop_handler2(njs_fs_stats_prop, NJS_FS_STAT_RDEV,
- NJS_NUMBER),
- .enumerable = 1,
- },
-
- {
- .type = NJS_PROPERTY_HANDLER,
- .name = njs_string("size"),
- .value = njs_prop_handler2(njs_fs_stats_prop, NJS_FS_STAT_SIZE,
- NJS_NUMBER),
- .enumerable = 1,
- },
-
- {
- .type = NJS_PROPERTY_HANDLER,
- .name = njs_string("blksize"),
- .value = njs_prop_handler2(njs_fs_stats_prop, NJS_FS_STAT_BLKSIZE,
- NJS_NUMBER),
- .enumerable = 1,
- },
-
- {
- .type = NJS_PROPERTY_HANDLER,
- .name = njs_string("blocks"),
- .value = njs_prop_handler2(njs_fs_stats_prop, NJS_FS_STAT_BLOCKS,
- NJS_NUMBER),
- .enumerable = 1,
- },
-
- {
- .type = NJS_PROPERTY_HANDLER,
- .name = njs_string("atimeMs"),
- .value = njs_prop_handler2(njs_fs_stats_prop, NJS_FS_STAT_ATIME,
- NJS_NUMBER),
- .enumerable = 1,
- },
-
- {
- .type = NJS_PROPERTY_HANDLER,
- .name = njs_string("birthtimeMs"),
- .value = njs_prop_handler2(njs_fs_stats_prop, NJS_FS_STAT_BIRTHTIME,
- NJS_NUMBER),
- .enumerable = 1,
- },
-
- {
- .type = NJS_PROPERTY_HANDLER,
- .name = njs_string("ctimeMs"),
- .value = njs_prop_handler2(njs_fs_stats_prop, NJS_FS_STAT_CTIME,
- NJS_NUMBER),
- .enumerable = 1,
- },
-
- {
- .type = NJS_PROPERTY_HANDLER,
- .name = njs_string("mtimeMs"),
- .value = njs_prop_handler2(njs_fs_stats_prop, NJS_FS_STAT_MTIME,
- NJS_NUMBER),
- .enumerable = 1,
- },
-
- {
- .type = NJS_PROPERTY_HANDLER,
- .name = njs_string("atime"),
- .value = njs_prop_handler2(njs_fs_stats_prop, NJS_FS_STAT_ATIME,
- NJS_DATE),
- .enumerable = 1,
- },
+ case NJS_FS_STAT_BLOCKS:
+ v = st->st_blocks;
+ break;
- {
- .type = NJS_PROPERTY_HANDLER,
- .name = njs_string("birthtime"),
- .value = njs_prop_handler2(njs_fs_stats_prop, NJS_FS_STAT_BIRTHTIME,
- NJS_DATE),
- .enumerable = 1,
- },
+ case NJS_FS_STAT_ATIME:
+ v = njs_fs_time_ms(&st->st_atim);
+ break;
- {
- .type = NJS_PROPERTY_HANDLER,
- .name = njs_string("ctime"),
- .value = njs_prop_handler2(njs_fs_stats_prop, NJS_FS_STAT_CTIME,
- NJS_DATE),
- .enumerable = 1,
- },
+ case NJS_FS_STAT_BIRTHTIME:
+ v = njs_fs_time_ms(&st->st_birthtim);
+ break;
- {
- .type = NJS_PROPERTY_HANDLER,
- .name = njs_string("mtime"),
- .value = njs_prop_handler2(njs_fs_stats_prop, NJS_FS_STAT_MTIME,
- NJS_DATE),
- .enumerable = 1,
- },
-};
+ case NJS_FS_STAT_CTIME:
+ v = njs_fs_time_ms(&st->st_ctim);
+ break;
+
+ case NJS_FS_STAT_MTIME:
+ default:
+ v = njs_fs_time_ms(&st->st_mtim);
+ break;
+ }
+ switch (prop->value.data.magic32 >> 4) {
+ case NJS_NUMBER:
+ njs_set_number(retval, v);
+ break;
-const njs_object_init_t njs_stats_prototype_init = {
- njs_stats_prototype_properties,
- njs_nitems(njs_stats_prototype_properties),
-};
+ case NJS_DATE:
+ default:
+ date = njs_date_alloc(vm, v);
+ if (njs_slow_path(date == NULL)) {
+ return NJS_ERROR;
+ }
+ njs_set_date(retval, date);
+ break;
+ }
-const njs_object_type_init_t njs_stats_type_init = {
- .constructor = njs_native_ctor(njs_stats_constructor, 0, 0),
- .prototype_props = &njs_stats_prototype_init,
- .constructor_props = &njs_stats_constructor_init,
- .prototype_value = { .object = { .type = NJS_OBJECT } },
-};
+ return NJS_OK;
+}
static const njs_object_prop_t njs_fs_promises_properties[] =
{
.type = NJS_PROPERTY,
.name = njs_string("readFile"),
- .value = njs_native_function2(njs_fs_read_file, 0, NJS_FS_PROMISE),
+ .value = njs_native_function2(njs_fs_read, 0, NJS_FS_PROMISE),
.writable = 1,
.configurable = 1,
},
{
.type = NJS_PROPERTY,
.name = njs_string("appendFile"),
- .value = njs_native_function2(njs_fs_write_file, 0,
+ .value = njs_native_function2(njs_fs_write, 0,
njs_fs_magic(NJS_FS_PROMISE, NJS_FS_APPEND)),
.writable = 1,
.configurable = 1,
{
.type = NJS_PROPERTY,
.name = njs_string("writeFile"),
- .value = njs_native_function2(njs_fs_write_file, 0,
- njs_fs_magic(NJS_FS_PROMISE, NJS_FS_TRUNC)),
+ .value = njs_native_function2(njs_fs_write, 0,
+ njs_fs_magic(NJS_FS_PROMISE, NJS_FS_TRUNC)),
.writable = 1,
.configurable = 1,
},
}
-static const njs_object_prop_t njs_fs_object_properties[] =
+static njs_int_t
+njs_fs_init(njs_vm_t *vm)
{
- {
- .type = NJS_PROPERTY,
- .name = njs_string("name"),
- .value = njs_string("fs"),
- .configurable = 1,
- },
-
- {
- .type = NJS_PROPERTY_HANDLER,
- .name = njs_string("constants"),
- .value = njs_prop_handler(njs_fs_constants),
- .enumerable = 1,
- },
-
- {
- .type = NJS_PROPERTY_HANDLER,
- .name = njs_string("promises"),
- .value = njs_prop_handler(njs_fs_promises),
- },
-
- {
- .type = NJS_PROPERTY,
- .name = njs_string("Dirent"),
- .value = _njs_native_function(njs_dirent_constructor, 2, 1, 0),
- .writable = 1,
- .configurable = 1,
- },
-
- {
- .type = NJS_PROPERTY,
- .name = njs_string("access"),
- .value = njs_native_function2(njs_fs_access, 0, NJS_FS_CALLBACK),
- .writable = 1,
- .configurable = 1,
- },
-
- {
- .type = NJS_PROPERTY,
- .name = njs_string("accessSync"),
- .value = njs_native_function2(njs_fs_access, 0, NJS_FS_DIRECT),
- .writable = 1,
- .configurable = 1,
- },
-
- {
- .type = NJS_PROPERTY,
- .name = njs_string("readFile"),
- .value = njs_native_function2(njs_fs_read_file, 0, NJS_FS_CALLBACK),
- .writable = 1,
- .configurable = 1,
- },
-
- {
- .type = NJS_PROPERTY,
- .name = njs_string("readFileSync"),
- .value = njs_native_function2(njs_fs_read_file, 0, NJS_FS_DIRECT),
- .writable = 1,
- .configurable = 1,
- },
-
- {
- .type = NJS_PROPERTY,
- .name = njs_string("appendFile"),
- .value = njs_native_function2(njs_fs_write_file, 0,
- njs_fs_magic(NJS_FS_CALLBACK, NJS_FS_APPEND)),
- .writable = 1,
- .configurable = 1,
- },
-
- {
- .type = NJS_PROPERTY,
- .name = njs_string("appendFileSync"),
- .value = njs_native_function2(njs_fs_write_file, 0,
- njs_fs_magic(NJS_FS_DIRECT, NJS_FS_APPEND)),
- .writable = 1,
- .configurable = 1,
- },
-
- {
- .type = NJS_PROPERTY,
- .name = njs_string("writeFile"),
- .value = njs_native_function2(njs_fs_write_file, 0,
- njs_fs_magic(NJS_FS_CALLBACK, NJS_FS_TRUNC)),
- .writable = 1,
- .configurable = 1,
- },
-
- {
- .type = NJS_PROPERTY,
- .name = njs_string("writeFileSync"),
- .value = njs_native_function2(njs_fs_write_file, 0,
- njs_fs_magic(NJS_FS_DIRECT, NJS_FS_TRUNC)),
- .writable = 1,
- .configurable = 1,
- },
-
- {
- .type = NJS_PROPERTY,
- .name = njs_string("rename"),
- .value = njs_native_function2(njs_fs_rename, 0, NJS_FS_CALLBACK),
- .writable = 1,
- .configurable = 1,
- },
-
- {
- .type = NJS_PROPERTY,
- .name = njs_string("renameSync"),
- .value = njs_native_function2(njs_fs_rename, 0, NJS_FS_DIRECT),
- .writable = 1,
- .configurable = 1,
- },
-
- {
- .type = NJS_PROPERTY,
- .name = njs_string("symlink"),
- .value = njs_native_function2(njs_fs_symlink, 0, NJS_FS_CALLBACK),
- .writable = 1,
- .configurable = 1,
- },
-
- {
- .type = NJS_PROPERTY,
- .name = njs_string("symlinkSync"),
- .value = njs_native_function2(njs_fs_symlink, 0, NJS_FS_DIRECT),
- .writable = 1,
- .configurable = 1,
- },
-
- {
- .type = NJS_PROPERTY,
- .name = njs_string("unlink"),
- .value = njs_native_function2(njs_fs_unlink, 0, NJS_FS_CALLBACK),
- .writable = 1,
- .configurable = 1,
- },
-
- {
- .type = NJS_PROPERTY,
- .name = njs_string("unlinkSync"),
- .value = njs_native_function2(njs_fs_unlink, 0, NJS_FS_DIRECT),
- .writable = 1,
- .configurable = 1,
- },
-
- {
- .type = NJS_PROPERTY,
- .name = njs_string("realpath"),
- .value = njs_native_function2(njs_fs_realpath, 0, NJS_FS_CALLBACK),
- .writable = 1,
- .configurable = 1,
- },
-
- {
- .type = NJS_PROPERTY,
- .name = njs_string("realpathSync"),
- .value = njs_native_function2(njs_fs_realpath, 0, NJS_FS_DIRECT),
- .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,
- },
+ njs_int_t ret, proto_id;
+ njs_mod_t *module;
+ njs_opaque_value_t value;
- {
- .type = NJS_PROPERTY,
- .name = njs_string("readdir"),
- .value = njs_native_function2(njs_fs_readdir, 0, NJS_FS_CALLBACK),
- .writable = 1,
- .configurable = 1,
- },
+ if (vm->options.sandbox) {
+ return NJS_OK;
+ }
- {
- .type = NJS_PROPERTY,
- .name = njs_string("readdirSync"),
- .value = njs_native_function2(njs_fs_readdir, 0, NJS_FS_DIRECT),
- .writable = 1,
- .configurable = 1,
- },
+ njs_fs_stats_proto_id = njs_vm_external_prototype(vm, njs_ext_stats,
+ njs_nitems(njs_ext_stats));
+ if (njs_slow_path(njs_fs_stats_proto_id < 0)) {
+ return NJS_ERROR;
+ }
- {
- .type = NJS_PROPERTY,
- .name = njs_string("lstat"),
- .value = njs_native_function2(njs_fs_stat, 0,
- njs_fs_magic(NJS_FS_CALLBACK, NJS_FS_LSTAT)),
- .writable = 1,
- .configurable = 1,
- },
+ njs_fs_dirent_proto_id = njs_vm_external_prototype(vm, njs_ext_dirent,
+ njs_nitems(njs_ext_dirent));
+ if (njs_slow_path(njs_fs_dirent_proto_id < 0)) {
+ return NJS_ERROR;
+ }
- {
- .type = NJS_PROPERTY,
- .name = njs_string("lstatSync"),
- .value = njs_native_function2(njs_fs_stat, 0,
- njs_fs_magic(NJS_FS_DIRECT, NJS_FS_LSTAT)),
- .writable = 1,
- .configurable = 1,
- },
+ proto_id = njs_vm_external_prototype(vm, njs_ext_fs,
+ njs_nitems(njs_ext_fs));
+ if (njs_slow_path(proto_id < 0)) {
+ return NJS_ERROR;
+ }
- {
- .type = NJS_PROPERTY,
- .name = njs_string("stat"),
- .value = njs_native_function2(njs_fs_stat, 0,
- njs_fs_magic(NJS_FS_CALLBACK, NJS_FS_STAT)),
- .writable = 1,
- .configurable = 1,
- },
+ ret = njs_vm_external_create(vm, njs_value_arg(&value), proto_id, NULL, 1);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return NJS_ERROR;
+ }
- {
- .type = NJS_PROPERTY,
- .name = njs_string("statSync"),
- .value = njs_native_function2(njs_fs_stat, 0,
- njs_fs_magic(NJS_FS_DIRECT, NJS_FS_STAT)),
- .writable = 1,
- .configurable = 1,
- },
-};
+ module = njs_module_add(vm, &njs_str_value("fs"), 1);
+ if (njs_slow_path(module == NULL)) {
+ return NJS_ERROR;
+ }
+ njs_value_assign(&module->value, &value);
+ module->function.native = 1;
-const njs_object_init_t njs_fs_object_init = {
- njs_fs_object_properties,
- njs_nitems(njs_fs_object_properties),
-};
+ return NJS_OK;
+}