[njs] Fixed fs.readFile() and fs.readFileSync() for files with 0 size.
Dmitry Volyntsev
xeioex at nginx.com
Mon Aug 12 18:05:16 UTC 2019
details: https://hg.nginx.org/njs/rev/355028822e48
branches:
changeset: 1121:355028822e48
user: Dmitry Volyntsev <xeioex at nginx.com>
date: Mon Aug 12 21:03:24 2019 +0300
description:
Fixed fs.readFile() and fs.readFileSync() for files with 0 size.
diffstat:
src/njs_fs.c | 183 +++++++++++++++++++++++++++++++++++-----------
test/njs_expect_test.exp | 21 +++++
2 files changed, 160 insertions(+), 44 deletions(-)
diffs (282 lines):
diff -r 33c4966abdda -r 355028822e48 src/njs_fs.c
--- a/src/njs_fs.c Thu Aug 08 03:52:18 2019 -0400
+++ b/src/njs_fs.c Mon Aug 12 21:03:24 2019 +0300
@@ -31,6 +31,8 @@ static njs_int_t njs_fs_write_file_inter
static njs_int_t njs_fs_write_file_sync_internal(njs_vm_t *vm,
njs_value_t *args, njs_uint_t nargs, int default_flags);
+static njs_int_t njs_fs_fd_read(njs_vm_t *vm, njs_value_t *path, int fd,
+ njs_str_t *data);
static njs_int_t njs_fs_error(njs_vm_t *vm, const char *syscall,
const char *description, njs_value_t *path, int errn, njs_value_t *retval);
static int njs_fs_flags(njs_str_t *value);
@@ -70,9 +72,10 @@ njs_fs_read_file(njs_vm_t *vm, njs_value
njs_index_t unused)
{
int fd, errn, flags;
- u_char *p, *start, *end;
- ssize_t n, length;
- njs_str_t flag, encoding;
+ u_char *start;
+ size_t size;
+ ssize_t length;
+ njs_str_t flag, encoding, data;
njs_int_t ret;
const char *path, *syscall, *description;
struct stat sb;
@@ -209,32 +212,46 @@ njs_fs_read_file(njs_vm_t *vm, njs_value
length = 0;
}
- start = njs_string_alloc(vm, &arguments[2], sb.st_size, length);
- if (njs_slow_path(start == NULL)) {
- goto fail;
- }
+ size = sb.st_size;
- p = start;
- end = p + sb.st_size;
+ if (njs_fast_path(size != 0)) {
- while (p < end) {
- n = read(fd, p, end - p);
- if (njs_slow_path(n == -1)) {
- if (errno == EINTR) {
- continue;
- }
+ start = njs_string_alloc(vm, &arguments[2], size, length);
+ if (njs_slow_path(start == NULL)) {
+ goto fail;
+ }
- errn = errno;
- description = strerror(errno);
- syscall = "read";
- goto done;
+ data.start = start;
+ data.length = size;
+
+ ret = njs_fs_fd_read(vm, &args[1], fd, &data);
+ if (ret != NJS_OK) {
+ goto fail;
}
- p += n;
+ start = data.start;
+
+ } else {
+ /* size of the file is not known in advance. */
+
+ data.length = 0;
+
+ ret = njs_fs_fd_read(vm, &args[1], fd, &data);
+ if (ret != NJS_OK) {
+ goto fail;
+ }
+
+ size = data.length;
+ start = data.start;
+
+ ret = njs_string_new(vm, &arguments[2], start, size, length);
+ if (njs_slow_path(ret != NJS_OK)) {
+ goto fail;
+ }
}
if (encoding.length != 0) {
- length = njs_utf8_length(start, sb.st_size);
+ length = njs_utf8_length(start, size);
if (length >= 0) {
njs_string_length_set(&arguments[2], length);
@@ -295,9 +312,10 @@ njs_fs_read_file_sync(njs_vm_t *vm, njs_
njs_index_t unused)
{
int fd, errn, flags;
- u_char *p, *start, *end;
- ssize_t n, length;
- njs_str_t flag, encoding;
+ u_char *start;
+ size_t size;
+ ssize_t length;
+ njs_str_t flag, encoding, data;
njs_int_t ret;
const char *path, *syscall, *description;
struct stat sb;
@@ -418,32 +436,46 @@ njs_fs_read_file_sync(njs_vm_t *vm, njs_
length = 0;
}
- start = njs_string_alloc(vm, &vm->retval, sb.st_size, length);
- if (njs_slow_path(start == NULL)) {
- goto fail;
- }
+ size = sb.st_size;
- p = start;
- end = p + sb.st_size;
+ if (njs_fast_path(size != 0)) {
- while (p < end) {
- n = read(fd, p, end - p);
- if (njs_slow_path(n == -1)) {
- if (errno == EINTR) {
- continue;
- }
+ start = njs_string_alloc(vm, &vm->retval, size, length);
+ if (njs_slow_path(start == NULL)) {
+ goto fail;
+ }
- errn = errno;
- description = strerror(errno);
- syscall = "read";
- goto done;
+ data.start = start;
+ data.length = size;
+
+ ret = njs_fs_fd_read(vm, &args[1], fd, &data);
+ if (ret != NJS_OK) {
+ goto fail;
}
- p += n;
+ start = data.start;
+
+ } else {
+ /* size of the file is not known in advance. */
+
+ data.length = 0;
+
+ ret = njs_fs_fd_read(vm, &args[1], fd, &data);
+ if (ret != NJS_OK) {
+ goto fail;
+ }
+
+ size = data.length;
+ start = data.start;
+
+ ret = njs_string_new(vm, &vm->retval, start, size, length);
+ if (njs_slow_path(ret != NJS_OK)) {
+ goto fail;
+ }
}
if (encoding.length != 0) {
- length = njs_utf8_length(start, sb.st_size);
+ length = njs_utf8_length(start, size);
if (length >= 0) {
njs_string_length_set(&vm->retval, length);
@@ -872,8 +904,71 @@ done:
}
-static njs_int_t njs_fs_error(njs_vm_t *vm, const char *syscall,
- const char *description, njs_value_t *path, int errn, njs_value_t *retval)
+static njs_int_t
+njs_fs_fd_read(njs_vm_t *vm, njs_value_t *path, int fd, njs_str_t *data)
+{
+ u_char *p, *end, *start;
+ size_t size;
+ ssize_t n;
+
+ size = data->length;
+
+ if (size == 0) {
+ size = 4096;
+
+ data->start = njs_mp_alloc(vm->mem_pool, size);
+ if (data->start == NULL) {
+ njs_memory_error(vm);
+ return NJS_ERROR;
+ }
+ }
+
+ p = data->start;
+ end = p + size;
+
+ for ( ;; ) {
+ n = read(fd, p, end - p);
+
+ if (njs_slow_path(n < 0)) {
+ (void) njs_fs_error(vm, "read", strerror(errno), path, errno,
+ &vm->retval);
+ return NJS_ERROR;
+ }
+
+ p += n;
+
+ if (n == 0) {
+ break;
+ }
+
+ if (end - p < 2048) {
+ size *= 2;
+
+ start = njs_mp_alloc(vm->mem_pool, size);
+ if (start == NULL) {
+ njs_memory_error(vm);
+ return NJS_ERROR;
+ }
+
+ memcpy(start, data->start, p - data->start);
+
+ njs_mp_free(vm->mem_pool, data->start);
+
+ p = start + (p - data->start);
+ end = start + size;
+ data->start = start;
+ }
+ }
+
+ data->length = p - data->start;
+
+ return NJS_OK;
+}
+
+
+static njs_int_t
+njs_fs_error(njs_vm_t *vm, const char *syscall, const char *description,
+ njs_value_t *path, int errn, njs_value_t *retval)
{
size_t size;
njs_int_t ret;
diff -r 33c4966abdda -r 355028822e48 test/njs_expect_test.exp
--- a/test/njs_expect_test.exp Thu Aug 08 03:52:18 2019 -0400
+++ b/test/njs_expect_test.exp Mon Aug 12 21:03:24 2019 +0300
@@ -442,6 +442,15 @@ njs_test {
"Error: No such file or directory\r\nundefined\r\n>> "}
}
+njs_test {
+ {"var fs = require('fs')\r\n"
+ "undefined\r\n>> "}
+ {"fs.readFile('/proc/version', (e, data) => {console.log(e || data.slice(0,5) == 'Linux')})\r\n"
+ "true\r\nundefined\r\n>> "}
+ {"fs.readFile('/proc/cpuinfo', (e, data) => {console.log(e || data.slice(0,9) == 'processor')})\r\n"
+ "true\r\nundefined\r\n>> "}
+}
+
# require('fs').readFileSync()
njs_test {
@@ -500,6 +509,18 @@ njs_test {
"Error: Non-UTF8 file, convertion is not implemented"}
}
+njs_test {
+ {"var fs = require('fs'), file\r\n"
+ "undefined\r\n>> "}
+ {"try { file = fs.readFileSync('/proc/version')} catch (e) {}\r\n"
+ "undefined"}
+ {"(!file || file.slice(0,5) == 'Linux')\r\n"
+ "true"}
+ {"try { file = fs.readFileSync('/proc/cpuinfo')} catch (e) {}\r\n"
+ "undefined"}
+ {"(!file || file.slice(0,9) == 'processor')\r\n"
+ "true"}
+}
# require('fs').writeFile()
More information about the nginx-devel
mailing list