diff --git a/doc/api/fs.markdown b/doc/api/fs.markdown index dca35674cd3f..587ce4a06104 100644 --- a/doc/api/fs.markdown +++ b/doc/api/fs.markdown @@ -168,12 +168,15 @@ Only available on Mac OS X. Synchronous lchmod(2). -## fs.stat(path, callback) +## fs.stat(path, callback, [throwSafe]) Asynchronous stat(2). The callback gets two arguments `(err, stats)` where `stats` is a [fs.Stats](#fs_class_fs_stats) object. See the [fs.Stats](#fs_class_fs_stats) section below for more information. +Setting the throwSafe parameter to true prevents the error creation. If the call +fails, the first parameter of the callback will be true. + ## fs.lstat(path, callback) Asynchronous lstat(2). The callback gets two arguments `(err, stats)` where @@ -187,10 +190,13 @@ Asynchronous fstat(2). The callback gets two arguments `(err, stats)` where `stats` is a `fs.Stats` object. `fstat()` is identical to `stat()`, except that the file to be stat-ed is specified by the file descriptor `fd`. -## fs.statSync(path) +## fs.statSync(path, [throwSafe]) Synchronous stat(2). Returns an instance of `fs.Stats`. +Setting the throwSafe parameter to true prevents the error creation. If the call +fails `fs.statSync` returns `false`. + ## fs.lstatSync(path) Synchronous lstat(2). Returns an instance of `fs.Stats`. diff --git a/lib/fs.js b/lib/fs.js index 3301a6af8474..0e2282ff5cd2 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -100,14 +100,16 @@ function assertEncoding(encoding) { } } -function nullCheck(path, callback) { +function nullCheck(path, callback, throwSafe) { if (('' + path).indexOf('\u0000') !== -1) { - var er = new Error('Path must be a string without null bytes.'); - if (!callback) - throw er; - process.nextTick(function() { - callback(er); - }); + if (!throwSafe) { + var er = new Error('Path must be a string without null bytes.'); + if (!callback) + throw er; + process.nextTick(function() { + callback(er); + }); + } return false; } return true; @@ -181,21 +183,30 @@ fs.Stats.prototype.isSocket = function() { }; fs.exists = function(path, callback) { - if (!nullCheck(path, cb)) return; - binding.stat(pathModule._makeLong(path), cb); - function cb(err, stats) { - if (callback) callback(err ? false : true); + if (!nullCheck(path, undefined, true)) { + process.nextTick(function() { + cb(true, false); + }); + return; + } + binding.stat(pathModule._makeLong(path), cb, true); + function cb(err, result) { + if (callback) { + if (err) { + callback(false); + } else { + callback(!!result); + } + } } }; fs.existsSync = function(path) { - try { - nullCheck(path); - binding.stat(pathModule._makeLong(path)); - return true; - } catch (e) { + if (!nullCheck(path, undefined, true)) return false; - } + if (!binding.stat(pathModule._makeLong(path), undefined, true)) + return false; + return true; }; fs.readFile = function(path, options, callback_) { @@ -701,10 +712,17 @@ fs.lstat = function(path, callback) { binding.lstat(pathModule._makeLong(path), callback); }; -fs.stat = function(path, callback) { +fs.stat = function(path, callback, throwSafe) { callback = makeCallback(callback); - if (!nullCheck(path, callback)) return; - binding.stat(pathModule._makeLong(path), callback); + if (!nullCheck(path, callback, throwSafe)) { + if (throwSafe) { + process.nextTick(function() { + callback(true, false); + }); + } + return; + } + binding.stat(pathModule._makeLong(path), callback, throwSafe); }; fs.fstatSync = function(fd) { @@ -716,9 +734,11 @@ fs.lstatSync = function(path) { return binding.lstat(pathModule._makeLong(path)); }; -fs.statSync = function(path) { - nullCheck(path); - return binding.stat(pathModule._makeLong(path)); +fs.statSync = function(path, throwSafe) { + if (!nullCheck(path, undefined, throwSafe)) + return false; + + return binding.stat(pathModule._makeLong(path), undefined, throwSafe); }; fs.readlink = function(path, callback) { diff --git a/lib/module.js b/lib/module.js index 564f6c49d6cb..ff41a68231f3 100644 --- a/lib/module.js +++ b/lib/module.js @@ -82,10 +82,9 @@ var debug = Module._debug; // -> a/index. function statPath(path) { - try { - return fs.statSync(path); - } catch (ex) {} - return false; + var fs = NativeModule.require('fs'); + + return fs.statSync(path, true); } // check if the directory is a package.json dir diff --git a/src/node_file.cc b/src/node_file.cc index d62fbe2ab9d9..5bd88b87e0d3 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -66,13 +66,13 @@ using v8::Value; #define THROW_BAD_ARGS TYPE_ERROR("Bad argument") -class FSReqWrap: public ReqWrap { +class FSReqWrap: public ReqWrap { public: void* operator new(size_t size) { return new char[size]; } void* operator new(size_t size, char* storage) { return storage; } FSReqWrap(Environment* env, const char* syscall, char* data = NULL) - : ReqWrap(env, Object::New(env->isolate())), + : ReqWrap(env, Object::New(env->isolate())), syscall_(syscall), data_(data), dest_len_(0) { @@ -115,8 +115,10 @@ static inline bool IsInt64(double x) { static void After(uv_fs_t *req) { - FSReqWrap* req_wrap = static_cast(req->data); - assert(&req_wrap->req_ == req); + node_fs_t* req_node = reinterpret_cast(req); + + FSReqWrap* req_wrap = static_cast(req_node->data); + assert(&req_wrap->req_.req == req); req_wrap->ReleaseEarly(); // Free memory that's no longer used now. Environment* env = req_wrap->env(); @@ -131,8 +133,12 @@ static void After(uv_fs_t *req) { Local argv[2]; if (req->result < 0) { - // If the request doesn't have a path parameter set. - if (req->path == NULL) { + if (req_node->throwSafe == 1) { + argc = 2; + argv[0] = True(env->isolate()); + argv[1] = False(env->isolate()); + } else if (req->path == NULL) { + // If the request doesn't have a path parameter set. argv[0] = UVException(req->result, NULL, req_wrap->syscall()); } else if ((req->result == UV_EEXIST || req->result == UV_ENOTEMPTY || @@ -235,7 +241,7 @@ static void After(uv_fs_t *req) { req_wrap->MakeCallback(env->oncomplete_string(), argc, argv); - uv_fs_req_cleanup(&req_wrap->req_); + uv_fs_req_cleanup(&req_wrap->req_.req); delete req_wrap; } @@ -243,15 +249,15 @@ static void After(uv_fs_t *req) { // For async calls FSReqWrap is used. struct fs_req_wrap { fs_req_wrap() {} - ~fs_req_wrap() { uv_fs_req_cleanup(&req); } + ~fs_req_wrap() { uv_fs_req_cleanup(&req.req); } // Ensure that copy ctor and assignment operator are not used. fs_req_wrap(const fs_req_wrap& req); fs_req_wrap& operator=(const fs_req_wrap& req); - uv_fs_t req; + node_fs_t req; }; -#define ASYNC_DEST_CALL(func, callback, dest_path, ...) \ +#define ASYNC_DEST_CALL(func, callback, dest_path, throwSafeVal, ...) \ Environment* env = Environment::GetCurrent(args.GetIsolate()); \ FSReqWrap* req_wrap; \ char* dest_str = (dest_path); \ @@ -264,31 +270,36 @@ struct fs_req_wrap { dest_str, \ dest_len + 1); \ } \ + req_wrap->req_.throwSafe = throwSafeVal; \ int err = uv_fs_ ## func(env->event_loop() , \ - &req_wrap->req_, \ + &req_wrap->req_.req, \ __VA_ARGS__, \ After); \ req_wrap->object()->Set(env->oncomplete_string(), callback); \ req_wrap->Dispatched(); \ if (err < 0) { \ - uv_fs_t* req = &req_wrap->req_; \ + uv_fs_t* req = &req_wrap->req_.req; \ req->result = err; \ req->path = NULL; \ After(req); \ } \ args.GetReturnValue().Set(req_wrap->persistent()); -#define ASYNC_CALL(func, callback, ...) \ - ASYNC_DEST_CALL(func, callback, NULL, __VA_ARGS__) \ +#define ASYNC_CALL(func, callback, throwSafeVal, ...) \ + ASYNC_DEST_CALL(func, callback, NULL, throwSafeVal, __VA_ARGS__) \ -#define SYNC_DEST_CALL(func, path, dest, ...) \ +#define SYNC_DEST_CALL(func, path, dest, throwSafeVal, ...) \ fs_req_wrap req_wrap; \ + req_wrap.req.throwSafe = throwSafeVal; \ int err = uv_fs_ ## func(env->event_loop(), \ - &req_wrap.req, \ + &req_wrap.req.req, \ __VA_ARGS__, \ NULL); \ if (err < 0) { \ - if (dest != NULL && \ + if (req_wrap.req.throwSafe == 1) { \ + args.GetReturnValue().Set(False(env->isolate())); \ + return; \ + } else if (dest != NULL && \ (err == UV_EEXIST || \ err == UV_ENOTEMPTY || \ err == UV_EPERM)) { \ @@ -298,10 +309,10 @@ struct fs_req_wrap { } \ } \ -#define SYNC_CALL(func, path, ...) \ - SYNC_DEST_CALL(func, path, NULL, __VA_ARGS__) \ +#define SYNC_CALL(func, path, throwSafeVal, ...) \ + SYNC_DEST_CALL(func, path, NULL, throwSafeVal, __VA_ARGS__) \ -#define SYNC_REQ req_wrap.req +#define SYNC_REQ req_wrap.req.req #define SYNC_RESULT err @@ -317,9 +328,9 @@ static void Close(const FunctionCallbackInfo& args) { int fd = args[0]->Int32Value(); if (args[1]->IsFunction()) { - ASYNC_CALL(close, args[1], fd) + ASYNC_CALL(close, args[1], 0, fd) } else { - SYNC_CALL(close, 0, fd) + SYNC_CALL(close, 0, 0, fd) } } @@ -432,10 +443,15 @@ static void Stat(const FunctionCallbackInfo& args) { node::Utf8Value path(args[0]); + int throwSafe = 0; + if (args[2]->IsTrue()) { + throwSafe = 1; + } + if (args[1]->IsFunction()) { - ASYNC_CALL(stat, args[1], *path) + ASYNC_CALL(stat, args[1], throwSafe, *path) } else { - SYNC_CALL(stat, *path, *path) + SYNC_CALL(stat, *path, throwSafe, *path) args.GetReturnValue().Set( BuildStatsObject(env, static_cast(SYNC_REQ.ptr))); } @@ -453,9 +469,9 @@ static void LStat(const FunctionCallbackInfo& args) { node::Utf8Value path(args[0]); if (args[1]->IsFunction()) { - ASYNC_CALL(lstat, args[1], *path) + ASYNC_CALL(lstat, args[1], 0, *path) } else { - SYNC_CALL(lstat, *path, *path) + SYNC_CALL(lstat, *path, 0, *path) args.GetReturnValue().Set( BuildStatsObject(env, static_cast(SYNC_REQ.ptr))); } @@ -472,9 +488,9 @@ static void FStat(const FunctionCallbackInfo& args) { int fd = args[0]->Int32Value(); if (args[1]->IsFunction()) { - ASYNC_CALL(fstat, args[1], fd) + ASYNC_CALL(fstat, args[1], 0, fd) } else { - SYNC_CALL(fstat, 0, fd) + SYNC_CALL(fstat, 0, 0, fd) args.GetReturnValue().Set( BuildStatsObject(env, static_cast(SYNC_REQ.ptr))); } @@ -510,9 +526,9 @@ static void Symlink(const FunctionCallbackInfo& args) { } if (args[3]->IsFunction()) { - ASYNC_DEST_CALL(symlink, args[3], *dest, *dest, *path, flags) + ASYNC_DEST_CALL(symlink, args[3], *dest, 0, *dest, *path, flags) } else { - SYNC_DEST_CALL(symlink, *path, *dest, *dest, *path, flags) + SYNC_DEST_CALL(symlink, *path, *dest, 0, *dest, *path, flags) } } @@ -534,9 +550,9 @@ static void Link(const FunctionCallbackInfo& args) { node::Utf8Value new_path(args[1]); if (args[2]->IsFunction()) { - ASYNC_DEST_CALL(link, args[2], *new_path, *orig_path, *new_path) + ASYNC_DEST_CALL(link, args[2], *new_path, 0, *orig_path, *new_path) } else { - SYNC_DEST_CALL(link, *orig_path, *new_path, *orig_path, *new_path) + SYNC_DEST_CALL(link, *orig_path, *new_path, 0, *orig_path, *new_path) } } @@ -552,9 +568,9 @@ static void ReadLink(const FunctionCallbackInfo& args) { node::Utf8Value path(args[0]); if (args[1]->IsFunction()) { - ASYNC_CALL(readlink, args[1], *path) + ASYNC_CALL(readlink, args[1], 0, *path) } else { - SYNC_CALL(readlink, *path, *path) + SYNC_CALL(readlink, *path, 0, *path) const char* link_path = static_cast(SYNC_REQ.ptr); Local rc = String::NewFromUtf8(env->isolate(), link_path); args.GetReturnValue().Set(rc); @@ -579,9 +595,9 @@ static void Rename(const FunctionCallbackInfo& args) { node::Utf8Value new_path(args[1]); if (args[2]->IsFunction()) { - ASYNC_DEST_CALL(rename, args[2], *new_path, *old_path, *new_path) + ASYNC_DEST_CALL(rename, args[2], *new_path, 0, *old_path, *new_path) } else { - SYNC_DEST_CALL(rename, *old_path, *new_path, *old_path, *new_path) + SYNC_DEST_CALL(rename, *old_path, *new_path, 0, *old_path, *new_path) } } @@ -599,9 +615,9 @@ static void FTruncate(const FunctionCallbackInfo& args) { int64_t len = GET_TRUNCATE_LENGTH(args[1]); if (args[2]->IsFunction()) { - ASYNC_CALL(ftruncate, args[2], fd, len) + ASYNC_CALL(ftruncate, args[2], 0, fd, len) } else { - SYNC_CALL(ftruncate, 0, fd, len) + SYNC_CALL(ftruncate, 0, 0, fd, len) } } @@ -616,9 +632,9 @@ static void Fdatasync(const FunctionCallbackInfo& args) { int fd = args[0]->Int32Value(); if (args[1]->IsFunction()) { - ASYNC_CALL(fdatasync, args[1], fd) + ASYNC_CALL(fdatasync, args[1], 0, fd) } else { - SYNC_CALL(fdatasync, 0, fd) + SYNC_CALL(fdatasync, 0, 0, fd) } } @@ -633,9 +649,9 @@ static void Fsync(const FunctionCallbackInfo& args) { int fd = args[0]->Int32Value(); if (args[1]->IsFunction()) { - ASYNC_CALL(fsync, args[1], fd) + ASYNC_CALL(fsync, args[1], 0, fd) } else { - SYNC_CALL(fsync, 0, fd) + SYNC_CALL(fsync, 0, 0, fd) } } @@ -651,9 +667,9 @@ static void Unlink(const FunctionCallbackInfo& args) { node::Utf8Value path(args[0]); if (args[1]->IsFunction()) { - ASYNC_CALL(unlink, args[1], *path) + ASYNC_CALL(unlink, args[1], 0, *path) } else { - SYNC_CALL(unlink, *path, *path) + SYNC_CALL(unlink, *path, 0, *path) } } @@ -669,9 +685,9 @@ static void RMDir(const FunctionCallbackInfo& args) { node::Utf8Value path(args[0]); if (args[1]->IsFunction()) { - ASYNC_CALL(rmdir, args[1], *path) + ASYNC_CALL(rmdir, args[1], 0, *path) } else { - SYNC_CALL(rmdir, *path, *path) + SYNC_CALL(rmdir, *path, 0, *path) } } @@ -687,9 +703,9 @@ static void MKDir(const FunctionCallbackInfo& args) { int mode = static_cast(args[1]->Int32Value()); if (args[2]->IsFunction()) { - ASYNC_CALL(mkdir, args[2], *path, mode) + ASYNC_CALL(mkdir, args[2], 0, *path, mode) } else { - SYNC_CALL(mkdir, *path, *path, mode) + SYNC_CALL(mkdir, *path, 0, *path, mode) } } @@ -705,9 +721,9 @@ static void ReadDir(const FunctionCallbackInfo& args) { node::Utf8Value path(args[0]); if (args[1]->IsFunction()) { - ASYNC_CALL(readdir, args[1], *path, 0 /*flags*/) + ASYNC_CALL(readdir, args[1], 0, *path, 0 /*flags*/) } else { - SYNC_CALL(readdir, *path, *path, 0 /*flags*/) + SYNC_CALL(readdir, *path, 0, *path, 0 /*flags*/) assert(SYNC_REQ.result >= 0); char* namebuf = static_cast(SYNC_REQ.ptr); @@ -752,9 +768,9 @@ static void Open(const FunctionCallbackInfo& args) { int mode = static_cast(args[2]->Int32Value()); if (args[3]->IsFunction()) { - ASYNC_CALL(open, args[3], *path, flags, mode) + ASYNC_CALL(open, args[3], 0, *path, flags, mode) } else { - SYNC_CALL(open, *path, *path, flags, mode) + SYNC_CALL(open, *path, 0, *path, flags, mode) args.GetReturnValue().Set(SYNC_RESULT); } } @@ -799,11 +815,11 @@ static void WriteBuffer(const FunctionCallbackInfo& args) { uv_buf_t uvbuf = uv_buf_init(const_cast(buf), len); if (cb->IsFunction()) { - ASYNC_CALL(write, cb, fd, &uvbuf, 1, pos) + ASYNC_CALL(write, cb, 0, fd, &uvbuf, 1, pos) return; } - SYNC_CALL(write, NULL, fd, &uvbuf, 1, pos) + SYNC_CALL(write, NULL, 0, fd, &uvbuf, 1, pos) args.GetReturnValue().Set(SYNC_RESULT); } @@ -850,15 +866,16 @@ static void WriteString(const FunctionCallbackInfo& args) { uv_buf_t uvbuf = uv_buf_init(const_cast(buf), len); if (!cb->IsFunction()) { - SYNC_CALL(write, NULL, fd, &uvbuf, 1, pos) + SYNC_CALL(write, NULL, 0, fd, &uvbuf, 1, pos) if (must_free) delete[] buf; return args.GetReturnValue().Set(SYNC_RESULT); } FSReqWrap* req_wrap = new FSReqWrap(env, "write", must_free ? buf : NULL); + req_wrap->req_.throwSafe = 0; int err = uv_fs_write(env->event_loop(), - &req_wrap->req_, + &req_wrap->req_.req, fd, &uvbuf, 1, @@ -867,7 +884,7 @@ static void WriteString(const FunctionCallbackInfo& args) { req_wrap->object()->Set(env->oncomplete_string(), cb); req_wrap->Dispatched(); if (err < 0) { - uv_fs_t* req = &req_wrap->req_; + uv_fs_t* req = &req_wrap->req_.req; req->result = err; req->path = NULL; After(req); @@ -932,9 +949,9 @@ static void Read(const FunctionCallbackInfo& args) { cb = args[5]; if (cb->IsFunction()) { - ASYNC_CALL(read, cb, fd, &uvbuf, 1, pos); + ASYNC_CALL(read, cb, 0, fd, &uvbuf, 1, pos); } else { - SYNC_CALL(read, 0, fd, &uvbuf, 1, pos) + SYNC_CALL(read, 0, 0, fd, &uvbuf, 1, pos) args.GetReturnValue().Set(SYNC_RESULT); } } @@ -954,9 +971,9 @@ static void Chmod(const FunctionCallbackInfo& args) { int mode = static_cast(args[1]->Int32Value()); if (args[2]->IsFunction()) { - ASYNC_CALL(chmod, args[2], *path, mode); + ASYNC_CALL(chmod, args[2], 0, *path, mode); } else { - SYNC_CALL(chmod, *path, *path, mode); + SYNC_CALL(chmod, *path, 0, *path, mode); } } @@ -975,9 +992,9 @@ static void FChmod(const FunctionCallbackInfo& args) { int mode = static_cast(args[1]->Int32Value()); if (args[2]->IsFunction()) { - ASYNC_CALL(fchmod, args[2], fd, mode); + ASYNC_CALL(fchmod, args[2], 0, fd, mode); } else { - SYNC_CALL(fchmod, 0, fd, mode); + SYNC_CALL(fchmod, 0, 0, fd, mode); } } @@ -1008,9 +1025,9 @@ static void Chown(const FunctionCallbackInfo& args) { uv_gid_t gid = static_cast(args[2]->Uint32Value()); if (args[3]->IsFunction()) { - ASYNC_CALL(chown, args[3], *path, uid, gid); + ASYNC_CALL(chown, args[3], 0, *path, uid, gid); } else { - SYNC_CALL(chown, *path, *path, uid, gid); + SYNC_CALL(chown, *path, 0, *path, uid, gid); } } @@ -1041,9 +1058,9 @@ static void FChown(const FunctionCallbackInfo& args) { uv_gid_t gid = static_cast(args[2]->Uint32Value()); if (args[3]->IsFunction()) { - ASYNC_CALL(fchown, args[3], fd, uid, gid); + ASYNC_CALL(fchown, args[3], 0, fd, uid, gid); } else { - SYNC_CALL(fchown, 0, fd, uid, gid); + SYNC_CALL(fchown, 0, 0, fd, uid, gid); } } @@ -1071,9 +1088,9 @@ static void UTimes(const FunctionCallbackInfo& args) { const double mtime = static_cast(args[2]->NumberValue()); if (args[3]->IsFunction()) { - ASYNC_CALL(utime, args[3], *path, atime, mtime); + ASYNC_CALL(utime, args[3], 0, *path, atime, mtime); } else { - SYNC_CALL(utime, *path, *path, atime, mtime); + SYNC_CALL(utime, *path, 0, *path, atime, mtime); } } @@ -1100,9 +1117,9 @@ static void FUTimes(const FunctionCallbackInfo& args) { const double mtime = static_cast(args[2]->NumberValue()); if (args[3]->IsFunction()) { - ASYNC_CALL(futime, args[3], fd, atime, mtime); + ASYNC_CALL(futime, args[3], 0, fd, atime, mtime); } else { - SYNC_CALL(futime, 0, fd, atime, mtime); + SYNC_CALL(futime, 0, 0, fd, atime, mtime); } } diff --git a/src/node_file.h b/src/node_file.h index dc5deedb0a1c..4e655b664a40 100644 --- a/src/node_file.h +++ b/src/node_file.h @@ -27,6 +27,12 @@ namespace node { +struct node_fs_t { + uv_fs_t req; + int throwSafe; + void* data; +}; + void InitFs(v8::Handle target); } // namespace node diff --git a/test/simple/test-fs-stat-sync.js b/test/simple/test-fs-stat-sync.js new file mode 100644 index 000000000000..1c68e5e08632 --- /dev/null +++ b/test/simple/test-fs-stat-sync.js @@ -0,0 +1,168 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var common = require('../common'); +var assert = require('assert'); +var fs = require('fs'); +var got_error = false; +var success_count = 0; + +var stats; + +// statSync +try { + stats = fs.statSync('.'); +} catch (e) { + got_error = true; +} +if (!stats) { + got_error = true; +} else { + console.dir(stats); + assert.ok(stats.mtime instanceof Date); + success_count++; +} + +try { + stats = fs.statSync('.', true); +} catch (e) { + got_error = true; +} +if (!stats) { + got_error = true; +} else { + console.dir(stats); + assert.ok(stats.mtime instanceof Date); + success_count++; +} + +var errorCaught = false; +try { + stats = fs.statSync('nonexisting_file'); +} catch (e) { + assert.ok(e instanceof Error); + success_count++; + errorCaught = true; +} +if (!errorCaught) { + got_error = true; +} + +try { + stats = fs.statSync('nonexisting_file', true); +} catch (e) { + got_error = true; +} +assert.equal(false, stats); +success_count++; + +// lstatSync +try { + stats = fs.lstatSync('.'); +} catch (e) { + got_error = true; +} +if (!stats) { + got_error = true; +} else { + console.dir(stats); + assert.ok(stats.mtime instanceof Date); + success_count++; +} + +// fstatSync +fs.open('.', 'r', undefined, function(err, fd) { + assert.ok(!err); + assert.ok(fd); + + var stats; + try { + stats = fs.fstatSync(fd); + } catch (e) { + got_error = true; + } + if (!stats) { + got_error = true; + } else { + console.dir(stats); + assert.ok(stats.mtime instanceof Date); + success_count++; + } + + assert(this === global); +}); + +// fstatSync +fs.open('.', 'r', undefined, function(err, fd) { + var stats; + try { + stats = fs.fstatSync(fd); + } catch (err) { + got_error = true; + } + if (stats) { + console.dir(stats); + assert.ok(stats.mtime instanceof Date); + success_count++; + } + fs.close(fd); +}); + +console.log('stating: ' + __filename); +try { + stats = fs.statSync(__filename); +} catch (e) { + got_error = true; +} +if (!stats) { + got_error = true; +} else { + console.dir(stats); + success_count++; + + console.log('isDirectory: ' + JSON.stringify(stats.isDirectory())); + assert.equal(false, stats.isDirectory()); + + console.log('isFile: ' + JSON.stringify(stats.isFile())); + assert.equal(true, stats.isFile()); + + console.log('isSocket: ' + JSON.stringify(stats.isSocket())); + assert.equal(false, stats.isSocket()); + + console.log('isBlockDevice: ' + JSON.stringify(stats.isBlockDevice())); + assert.equal(false, stats.isBlockDevice()); + + console.log('isCharacterDevice: ' + JSON.stringify(stats.isCharacterDevice())); + assert.equal(false, stats.isCharacterDevice()); + + console.log('isFIFO: ' + JSON.stringify(stats.isFIFO())); + assert.equal(false, stats.isFIFO()); + + console.log('isSymbolicLink: ' + JSON.stringify(stats.isSymbolicLink())); + assert.equal(false, stats.isSymbolicLink()); + + assert.ok(stats.mtime instanceof Date); +} + +process.on('exit', function() { + assert.equal(8, success_count); + assert.equal(false, got_error); +}); diff --git a/test/simple/test-fs-stat.js b/test/simple/test-fs-stat.js index 8c5a9c64c153..5471f366f92c 100644 --- a/test/simple/test-fs-stat.js +++ b/test/simple/test-fs-stat.js @@ -41,6 +41,23 @@ fs.stat('.', function(err, stats) { assert.ok(stats.hasOwnProperty('blocks')); }); +fs.stat('nonexisting_file', function(err, stats) { + if (err) { + assert.ok(err instanceof Error); + success_count++; + } else { + got_error = true; + } + assert(this === global); +}); + +fs.stat('nonexisting_file', function(err, stats) { + assert.equal(true, err); + assert.equal(false, stats); + assert(this === global); + success_count++; +}, true); + fs.lstat('.', function(err, stats) { if (err) { got_error = true; @@ -89,40 +106,39 @@ fs.open('.', 'r', undefined, function(err, fd) { }); console.log('stating: ' + __filename); -fs.stat(__filename, function(err, s) { +fs.stat(__filename, function(err, stats) { if (err) { got_error = true; } else { - console.dir(s); + console.dir(stats); success_count++; - console.log('isDirectory: ' + JSON.stringify(s.isDirectory())); - assert.equal(false, s.isDirectory()); + console.log('isDirectory: ' + JSON.stringify(stats.isDirectory())); + assert.equal(false, stats.isDirectory()); - console.log('isFile: ' + JSON.stringify(s.isFile())); - assert.equal(true, s.isFile()); + console.log('isFile: ' + JSON.stringify(stats.isFile())); + assert.equal(true, stats.isFile()); - console.log('isSocket: ' + JSON.stringify(s.isSocket())); - assert.equal(false, s.isSocket()); + console.log('isSocket: ' + JSON.stringify(stats.isSocket())); + assert.equal(false, stats.isSocket()); - console.log('isBlockDevice: ' + JSON.stringify(s.isBlockDevice())); - assert.equal(false, s.isBlockDevice()); + console.log('isBlockDevice: ' + JSON.stringify(stats.isBlockDevice())); + assert.equal(false, stats.isBlockDevice()); - console.log('isCharacterDevice: ' + JSON.stringify(s.isCharacterDevice())); - assert.equal(false, s.isCharacterDevice()); + console.log('isCharacterDevice: ' + JSON.stringify(stats.isCharacterDevice())); + assert.equal(false, stats.isCharacterDevice()); - console.log('isFIFO: ' + JSON.stringify(s.isFIFO())); - assert.equal(false, s.isFIFO()); + console.log('isFIFO: ' + JSON.stringify(stats.isFIFO())); + assert.equal(false, stats.isFIFO()); - console.log('isSymbolicLink: ' + JSON.stringify(s.isSymbolicLink())); - assert.equal(false, s.isSymbolicLink()); + console.log('isSymbolicLink: ' + JSON.stringify(stats.isSymbolicLink())); + assert.equal(false, stats.isSymbolicLink()); - assert.ok(s.mtime instanceof Date); + assert.ok(stats.mtime instanceof Date); } }); process.on('exit', function() { - assert.equal(5, success_count); + assert.equal(7, success_count); assert.equal(false, got_error); }); -