diff --git a/doc/api.markdown b/doc/api.markdown index 72d29941d0..17e9e4d3a3 100644 --- a/doc/api.markdown +++ b/doc/api.markdown @@ -1269,9 +1269,9 @@ Asynchronous chmod(2). No arguments other than a possible exception are given to Synchronous chmod(2). -### fs.stat(path, callback), fs.lstat(path, callback) +### fs.stat(path, callback), fs.lstat(path, callback), fs.fstat(fd, callback) -Asynchronous stat(2) or lstat(2). The callback gets two arguments `(err, stats)` where `stats` is a `fs.Stats` object. It looks like this: +Asynchronous stat(2), lstat(2) or fstat(2). The callback gets two arguments `(err, stats)` where `stats` is a `fs.Stats` object. It looks like this: { dev: 2049 , ino: 305352 @@ -1290,9 +1290,9 @@ Asynchronous stat(2) or lstat(2). The callback gets two arguments `(err, stats)` See the `fs.Stats` section below for more information. -### fs.statSync(path), fs.lstatSync(path) +### fs.statSync(path), fs.lstatSync(path), fs.fstatSync(fd) -Synchronous stat(2) or lstat(2). Returns an instance of `fs.Stats`. +Synchronous stat(2), lstat(2) or fstat(2). Returns an instance of `fs.Stats`. ### fs.link(srcpath, dstpath, callback) diff --git a/lib/fs.js b/lib/fs.js index dbfec123c0..033b8b7a14 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -207,6 +207,10 @@ fs.readdirSync = function (path) { return binding.readdir(path); }; +fs.fstat = function (fd, callback) { + binding.fstat(fd, callback || noop); +}; + fs.lstat = function (path, callback) { binding.lstat(path, callback || noop); }; @@ -215,6 +219,10 @@ fs.stat = function (path, callback) { binding.stat(path, callback || noop); }; +fs.fstatSync = function (fd) { + return binding.fstat(fd); +}; + fs.lstatSync = function (path) { return binding.lstat(path); }; diff --git a/src/node_file.cc b/src/node_file.cc index f9fd27c122..a576b5cbbf 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -73,6 +73,7 @@ static int After(eio_req *req) { case EIO_STAT: case EIO_LSTAT: + case EIO_FSTAT: { struct stat *s = reinterpret_cast(req->ptr2); argc = 2; @@ -215,6 +216,25 @@ static Handle LStat(const Arguments& args) { } } +static Handle FStat(const Arguments& args) { + HandleScope scope; + + if (args.Length() < 1 || !args[0]->IsInt32()) { + return THROW_BAD_ARGS; + } + + int fd = args[0]->Int32Value(); + + if (args[1]->IsFunction()) { + ASYNC_CALL(fstat, args[1], fd) + } else { + struct stat s; + int ret = fstat(fd, &s); + if (ret != 0) return ThrowException(ErrnoException(errno)); + return scope.Close(BuildStatsObject(&s)); + } +} + static Handle Symlink(const Arguments& args) { HandleScope scope; @@ -744,6 +764,7 @@ void File::Initialize(Handle target) { NODE_SET_METHOD(target, "readdir", ReadDir); NODE_SET_METHOD(target, "stat", Stat); NODE_SET_METHOD(target, "lstat", LStat); + NODE_SET_METHOD(target, "fstat", FStat); NODE_SET_METHOD(target, "link", Link); NODE_SET_METHOD(target, "symlink", Symlink); NODE_SET_METHOD(target, "readlink", ReadLink); diff --git a/test/simple/test-fs-stat.js b/test/simple/test-fs-stat.js index 5f5333d1b8..eb19251184 100644 --- a/test/simple/test-fs-stat.js +++ b/test/simple/test-fs-stat.js @@ -23,6 +23,39 @@ fs.lstat(".", function (err, stats) { } }); +// fstat +fs.open(".", "r", undefined, function(err, fd) { + assert.ok(!err); + assert.ok(fd); + + fs.fstat(fd, function (err, stats) { + if (err) { + got_error = true; + } else { + p(stats); + assert.ok(stats.mtime instanceof Date); + success_count++; + fs.close(fd); + } + }); +}); + +// fstatSync +fs.open(".", "r", undefined, function(err, fd) { + var stats; + try { + stats = fs.fstatSync(fd); + } catch (err) { + got_error = true; + } + if (stats) { + p(stats); + assert.ok(stats.mtime instanceof Date); + success_count++; + } + fs.close(fd); +}); + puts("stating: " + __filename); fs.stat(__filename, function (err, s) { if (err) { @@ -57,7 +90,7 @@ fs.stat(__filename, function (err, s) { }); process.addListener("exit", function () { - assert.equal(3, success_count); + assert.equal(5, success_count); assert.equal(false, got_error); });