diff --git a/doc/api/fs.markdown b/doc/api/fs.markdown index f886b73dc7e..380820cb39e 100644 --- a/doc/api/fs.markdown +++ b/doc/api/fs.markdown @@ -153,12 +153,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. +The throwSafe parameter if set 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 @@ -172,10 +175,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`. +The throwSafe parameter if set to true prevents the error creation. If the call +fails, the first parameter of the callback will be true. + ## fs.lstatSync(path) Synchronous lstat(2). Returns an instance of `fs.Stats`. diff --git a/lib/fs.js b/lib/fs.js index 1e3dc6415a6..2b04ce2006b 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -114,14 +114,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; @@ -162,21 +164,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_) { @@ -675,10 +686,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) { @@ -690,9 +708,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 edca95bd4e0..5d3f2fbc1f3 100644 --- a/lib/module.js +++ b/lib/module.js @@ -87,10 +87,8 @@ var debug = Module._debug; function statPath(path) { var fs = NativeModule.require('fs'); - try { - return fs.statSync(path); - } catch (ex) {} - return false; + + 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 3c35e0b4ffa..d6589ab0322 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -49,7 +49,7 @@ using namespace v8; #define THROW_BAD_ARGS TYPE_ERROR("Bad argument") -class FSReqWrap: public ReqWrap { +class FSReqWrap: public ReqWrap { public: void* operator new(size_t size, char* storage) { return storage; } @@ -92,8 +92,10 @@ static inline bool IsInt64(double x) { static void After(uv_fs_t *req) { HandleScope scope; - FSReqWrap* req_wrap = (FSReqWrap*) req->data; - assert(&req_wrap->req_ == req); + node_fs_t* req_node = (node_fs_t*) req; + + FSReqWrap* req_wrap = (FSReqWrap*) req_node->data; + assert(&req_wrap->req_.req == req); // there is always at least one argument. "error" int argc = 1; @@ -107,7 +109,11 @@ static void After(uv_fs_t *req) { if (req->result == -1) { // If the request doesn't have a path parameter set. - if (!req->path) { + if (req_node->throwSafe == 1) { + argc = 2; + argv[0] = Local::New(True()); + argv[1] = Local::New(False()); + } else if (!req->path) { argv[0] = UVException(req->errorno, NULL, req_wrap->syscall()); @@ -125,6 +131,7 @@ static void After(uv_fs_t *req) { req_wrap->syscall(), static_cast(req->path)); } + } else { // error value is empty or null for non-error. argv[0] = Local::New(Null()); @@ -213,7 +220,7 @@ static void After(uv_fs_t *req) { } MakeCallback(req_wrap->object_, oncomplete_sym, argc, argv); - uv_fs_req_cleanup(&req_wrap->req_); + uv_fs_req_cleanup(&req_wrap->req_.req); delete req_wrap; } @@ -221,15 +228,16 @@ 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, \ + throwSafeValue, ...) \ FSReqWrap* req_wrap; \ char* dest_str = (dest_path); \ int dest_len = dest_str == NULL ? 0 : strlen(dest_str); \ @@ -241,14 +249,15 @@ struct fs_req_wrap { dest_str, \ dest_len + 1); \ } \ + req_wrap->req_.throwSafe = throwSafeValue; \ int r = uv_fs_##func(uv_default_loop(), \ - &req_wrap->req_, \ + &req_wrap->req_.req, \ __VA_ARGS__, \ After); \ req_wrap->object_->Set(oncomplete_sym, callback); \ req_wrap->Dispatched(); \ if (r < 0) { \ - uv_fs_t* req = &req_wrap->req_; \ + uv_fs_t* req = &req_wrap->req_.req; \ req->result = r; \ req->path = NULL; \ req->errorno = uv_last_error(uv_default_loop()).code; \ @@ -256,16 +265,21 @@ struct fs_req_wrap { } \ return scope.Close(req_wrap->object_); -#define ASYNC_CALL(func, callback, ...) \ - ASYNC_DEST_CALL(func, callback, NULL, __VA_ARGS__) \ +#define ASYNC_CALL(func, callback, throwSafeValue, ...) \ + ASYNC_DEST_CALL(func, callback, NULL, throwSafeValue, \ + __VA_ARGS__) \ -#define SYNC_DEST_CALL(func, path, dest, ...) \ +#define SYNC_DEST_CALL(func, path, dest, throwSafeValue, ...) \ fs_req_wrap req_wrap; \ + req_wrap.req.throwSafe = throwSafeValue; \ int result = uv_fs_##func(uv_default_loop(), \ - &req_wrap.req, \ + &req_wrap.req.req, \ __VA_ARGS__, \ NULL); \ if (result < 0) { \ + if (req_wrap.req.throwSafe == 1) { \ + return False(); \ + } \ int code = uv_last_error(uv_default_loop()).code; \ if (dest != NULL && \ (code == UV_EEXIST || \ @@ -277,10 +291,10 @@ struct fs_req_wrap { } \ } \ -#define SYNC_CALL(func, path, ...) \ - SYNC_DEST_CALL(func, path, NULL, __VA_ARGS__) \ +#define SYNC_CALL(func, path, throwSafeValue, ...) \ + SYNC_DEST_CALL(func, path, NULL, throwSafeValue, __VA_ARGS__) \ -#define SYNC_REQ req_wrap.req +#define SYNC_REQ req_wrap.req.req #define SYNC_RESULT result @@ -295,9 +309,9 @@ static Handle Close(const Arguments& 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) return Undefined(); } } @@ -406,10 +420,15 @@ static Handle Stat(const Arguments& 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) return scope.Close( BuildStatsObject(static_cast(SYNC_REQ.ptr))); } @@ -424,9 +443,9 @@ static Handle LStat(const Arguments& 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) return scope.Close( BuildStatsObject(static_cast(SYNC_REQ.ptr))); } @@ -442,9 +461,9 @@ static Handle FStat(const Arguments& 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) return scope.Close( BuildStatsObject(static_cast(SYNC_REQ.ptr))); } @@ -476,9 +495,9 @@ static Handle Symlink(const Arguments& 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) return Undefined(); } } @@ -496,9 +515,9 @@ static Handle Link(const Arguments& 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) return Undefined(); } } @@ -512,9 +531,9 @@ static Handle ReadLink(const Arguments& 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) return scope.Close(String::New((char*)SYNC_REQ.ptr)); } } @@ -532,9 +551,9 @@ static Handle Rename(const Arguments& 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) return Undefined(); } } @@ -552,9 +571,9 @@ static Handle FTruncate(const Arguments& 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) return Undefined(); } } @@ -569,9 +588,9 @@ static Handle Fdatasync(const Arguments& 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) return Undefined(); } } @@ -586,9 +605,9 @@ static Handle Fsync(const Arguments& 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) return Undefined(); } } @@ -602,9 +621,9 @@ static Handle Unlink(const Arguments& 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) return Undefined(); } } @@ -618,9 +637,9 @@ static Handle RMDir(const Arguments& 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) return Undefined(); } } @@ -636,9 +655,9 @@ static Handle MKDir(const Arguments& 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) return Undefined(); } } @@ -652,12 +671,12 @@ static Handle ReadDir(const Arguments& 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*/) char *namebuf = static_cast(SYNC_REQ.ptr); - int nnames = req_wrap.req.result; + int nnames = req_wrap.req.req.result; Local names = Array::New(nnames); for (int i = 0; i < nnames; i++) { @@ -692,9 +711,9 @@ static Handle Open(const Arguments& 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) int fd = SYNC_RESULT; return scope.Close(Integer::New(fd)); } @@ -746,9 +765,9 @@ static Handle Write(const Arguments& args) { Local cb = args[5]; if (cb->IsFunction()) { - ASYNC_CALL(write, cb, fd, buf, len, pos) + ASYNC_CALL(write, cb, 0, fd, buf, len, pos) } else { - SYNC_CALL(write, 0, fd, buf, len, pos) + SYNC_CALL(write, 0, 0, fd, buf, len, pos) return scope.Close(Integer::New(SYNC_RESULT)); } } @@ -809,9 +828,9 @@ static Handle Read(const Arguments& args) { cb = args[5]; if (cb->IsFunction()) { - ASYNC_CALL(read, cb, fd, buf, len, pos); + ASYNC_CALL(read, cb, 0, fd, buf, len, pos); } else { - SYNC_CALL(read, 0, fd, buf, len, pos) + SYNC_CALL(read, 0, 0, fd, buf, len, pos) Local bytesRead = Integer::New(SYNC_RESULT); return scope.Close(bytesRead); } @@ -831,9 +850,9 @@ static Handle Chmod(const Arguments& 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); return Undefined(); } } @@ -852,9 +871,9 @@ static Handle FChmod(const Arguments& 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); return Undefined(); } } @@ -879,9 +898,9 @@ static Handle Chown(const Arguments& 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); return Undefined(); } } @@ -906,9 +925,9 @@ static Handle FChown(const Arguments& 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); return Undefined(); } } @@ -930,9 +949,9 @@ static Handle UTimes(const Arguments& 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); return Undefined(); } } @@ -953,9 +972,9 @@ static Handle FUTimes(const Arguments& 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); return Undefined(); } } diff --git a/src/node_file.h b/src/node_file.h index 5757e732b58..a57a1238ee6 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; +}; + class File { public: static void Initialize(v8::Handle target); diff --git a/test/simple/test-fs-stat-sync.js b/test/simple/test-fs-stat-sync.js new file mode 100644 index 00000000000..1c68e5e0863 --- /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 90b0ba52d4a..3293d8ff798 100644 --- a/test/simple/test-fs-stat.js +++ b/test/simple/test-fs-stat.js @@ -36,6 +36,34 @@ fs.stat('.', function(err, stats) { assert(this === global); }); +fs.stat('.', function(err, stats) { + if (err) { + got_error = true; + } else { + console.dir(stats); + assert.ok(stats.mtime instanceof Date); + success_count++; + } + assert(this === global); +}, true); + +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; @@ -84,40 +112,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(8, success_count); assert.equal(false, got_error); }); -