Add isDirectory(), isFile(), isSocket(), ... methods to stats object.
authorRyan <ry@tinyclouds.org>
Fri, 11 Sep 2009 11:41:47 +0000 (13:41 +0200)
committerRyan <ry@tinyclouds.org>
Fri, 11 Sep 2009 11:41:47 +0000 (13:41 +0200)
Thanks to Felix Geisendörfer for the initial patch.

doc/api.txt
src/constants.cc
src/file.cc
src/file.js
test/mjsunit/test-fs-stat.js

index df6b8fa..b48344c 100644 (file)
@@ -437,11 +437,12 @@ node.fs.stat("/tmp/world").addCallback(function (stats) {
 
 +node.fs.stat(path)+ ::
   See stat(2).
-  - on success: Returns +stats+ object. It looks like this:
+  - on success: Returns +node.fs.Stats+ object. It looks like this:
     +{ dev: 2049, ino: 305352, mode: 16877, nlink: 12, uid: 1000, gid: 1000,
     rdev: 0, size: 4096, blksize: 4096, blocks: 8, atime:
     "2009-06-29T11:11:55Z", mtime: "2009-06-29T11:11:40Z", ctime:
     "2009-06-29T11:11:40Z" }+
+    See the +node.fs.Stats+ section below for more information.
   - on error: no parameters.
 
 +node.fs.unlink(path)+ ::
@@ -518,6 +519,23 @@ node.fs.cat("/etc/passwd", "utf8").addCallback(function (content) {
 - on success: returns +data+, what was read from the file.
 - on error: no parameters.
 
+==== +node.fs.Stats+
+
+Objects returned from +node.fs.stat()+ are of this type.
+
++stats.isFile()+::
+
++stats.isDirectory()+::
+
++stats.isBlockDevice()+::
+
++stats.isCharacterDevice()+::
+
++stats.isSymbolicLink()+::
+
++stats.isFIFO()+::
+
++stats.isSocket()+::
 
 === HTTP
 
index 5012fc6..2c6bb8a 100644 (file)
@@ -5,6 +5,8 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 
 using namespace v8;
 using namespace node;
@@ -21,6 +23,14 @@ node::DefineConstants (Handle<Object> target)
   NODE_DEFINE_CONSTANT(target, O_WRONLY);
   NODE_DEFINE_CONSTANT(target, O_RDWR);
 
+  NODE_DEFINE_CONSTANT(target, S_IFREG);
+  NODE_DEFINE_CONSTANT(target, S_IFDIR);
+  NODE_DEFINE_CONSTANT(target, S_IFCHR);
+  NODE_DEFINE_CONSTANT(target, S_IFBLK);
+  NODE_DEFINE_CONSTANT(target, S_IFIFO);
+  NODE_DEFINE_CONSTANT(target, S_IFLNK);
+  NODE_DEFINE_CONSTANT(target, S_IFSOCK);
+
 #ifdef O_CREAT
   NODE_DEFINE_CONSTANT(target, O_CREAT);
 #endif
index d278099..aa8e645 100644 (file)
@@ -58,6 +58,58 @@ EIOPromise::Create (void)
   return promise;
 }
 
+static Persistent<FunctionTemplate> stats_constructor_template;
+
+static Local<Object>
+BuildStatsObject (struct stat * s)
+{
+  HandleScope scope;
+
+  Local<Object> stats =
+    stats_constructor_template->GetFunction()->NewInstance();
+
+  /* ID of device containing file */
+  stats->Set(DEV_SYMBOL, Integer::New(s->st_dev));
+
+  /* inode number */
+  stats->Set(INO_SYMBOL, Integer::New(s->st_ino));
+
+  /* protection */
+  stats->Set(MODE_SYMBOL, Integer::New(s->st_mode));
+
+  /* number of hard links */
+  stats->Set(NLINK_SYMBOL, Integer::New(s->st_nlink));
+
+  /* user ID of owner */
+  stats->Set(UID_SYMBOL, Integer::New(s->st_uid));
+
+  /* group ID of owner */
+  stats->Set(GID_SYMBOL, Integer::New(s->st_gid));
+
+  /* device ID (if special file) */
+  stats->Set(RDEV_SYMBOL, Integer::New(s->st_rdev));
+
+  /* total size, in bytes */
+  stats->Set(SIZE_SYMBOL, Integer::New(s->st_size));
+
+  /* blocksize for filesystem I/O */
+  stats->Set(BLKSIZE_SYMBOL, Integer::New(s->st_blksize));
+
+  /* number of blocks allocated */
+  stats->Set(BLOCKS_SYMBOL, Integer::New(s->st_blocks));
+
+  /* time of last access */
+  stats->Set(ATIME_SYMBOL, NODE_UNIXTIME_V8(s->st_atime));
+
+  /* time of last modification */
+  stats->Set(MTIME_SYMBOL, NODE_UNIXTIME_V8(s->st_mtime));
+
+  /* time of last status change */
+  stats->Set(CTIME_SYMBOL, NODE_UNIXTIME_V8(s->st_ctime));
+
+  return scope.Close(stats);
+}
+
 int
 EIOPromise::After (eio_req *req)
 {
@@ -93,23 +145,9 @@ EIOPromise::After (eio_req *req)
 
     case EIO_STAT:
     {
-      Local<Object> stats = Object::New();
       struct stat *s = reinterpret_cast<struct stat*>(req->ptr2);
-      stats->Set(DEV_SYMBOL, Integer::New(s->st_dev)); /* ID of device containing file */
-      stats->Set(INO_SYMBOL, Integer::New(s->st_ino)); /* inode number */
-      stats->Set(MODE_SYMBOL, Integer::New(s->st_mode)); /* protection */
-      stats->Set(NLINK_SYMBOL, Integer::New(s->st_nlink)); /* number of hard links */
-      stats->Set(UID_SYMBOL, Integer::New(s->st_uid)); /* user ID of owner */
-      stats->Set(GID_SYMBOL, Integer::New(s->st_gid)); /* group ID of owner */
-      stats->Set(RDEV_SYMBOL, Integer::New(s->st_rdev)); /* device ID (if special file) */
-      stats->Set(SIZE_SYMBOL, Integer::New(s->st_size)); /* total size, in bytes */
-      stats->Set(BLKSIZE_SYMBOL, Integer::New(s->st_blksize)); /* blocksize for filesystem I/O */
-      stats->Set(BLOCKS_SYMBOL, Integer::New(s->st_blocks)); /* number of blocks allocated */
-      stats->Set(ATIME_SYMBOL, NODE_UNIXTIME_V8(s->st_atime)); /* time of last access */
-      stats->Set(MTIME_SYMBOL, NODE_UNIXTIME_V8(s->st_mtime)); /* time of last modification */
-      stats->Set(CTIME_SYMBOL, NODE_UNIXTIME_V8(s->st_ctime)); /* time of last status change */
       argc = 1;
-      argv[0] = stats;
+      argv[0] = BuildStatsObject(s);
       break;
     }
 
@@ -350,4 +388,9 @@ File::Initialize (Handle<Object> target)
   NODE_SET_METHOD(target, "stat", Stat);
   NODE_SET_METHOD(target, "unlink", Unlink);
   NODE_SET_METHOD(target, "write", Write);
+
+  Local<FunctionTemplate> t = FunctionTemplate::New();
+  stats_constructor_template = Persistent<FunctionTemplate>::New(t);
+  target->Set(String::NewSymbol("Stats"),
+      stats_constructor_template->GetFunction());
 }
index 3f58654..84b042a 100644 (file)
@@ -39,3 +39,35 @@ node.fs.cat = function (path, encoding) {
   });
   return cat_promise;
 };
+
+node.fs.Stats.prototype._checkModeProperty = function (property) {
+  return ((this.mode & property) == property);
+};
+
+node.fs.Stats.prototype.isDirectory = function () {
+  return this._checkModeProperty(node.S_IFDIR);
+};
+
+node.fs.Stats.prototype.isFile = function () {
+  return this._checkModeProperty(node.S_IFREG);
+};
+
+node.fs.Stats.prototype.isBlockDevice = function () {
+  return this._checkModeProperty(node.S_IFBLK);
+};
+
+node.fs.Stats.prototype.isCharacterDevice = function () {
+  return this._checkModeProperty(node.S_IFCHR);
+};
+
+node.fs.Stats.prototype.isSymbolicLink = function () {
+  return this._checkModeProperty(node.S_IFLNK);
+};
+
+node.fs.Stats.prototype.isFIFO = function () {
+  return this._checkModeProperty(node.S_IFIFO);
+};
+
+node.fs.Stats.prototype.isSocket = function () {
+  return this._checkModeProperty(node.S_IFSOCK);
+};
index 72c7d62..7867e2d 100644 (file)
@@ -1,7 +1,7 @@
 include("mjsunit.js");
 
 var got_error = false;
-var got_success = false;
+var success_count = 0;
 var stats;
 
 var promise = node.fs.stat(".");
@@ -9,15 +9,45 @@ var promise = node.fs.stat(".");
 promise.addCallback(function (_stats) {
   stats = _stats;
   p(stats);
-  got_success = true;
+  success_count++;
 });
 
 promise.addErrback(function () {
   got_error = true;
 });
 
+puts("stating: " + __filename);
+node.fs.stat(__filename).addCallback(function (s) {
+  p(s);
+  success_count++;
+
+  puts("isDirectory: " + JSON.stringify( s.isDirectory() ) );
+  assertFalse(s.isDirectory());
+
+  puts("isFile: " + JSON.stringify( s.isFile() ) );
+  assertTrue(s.isFile());
+
+  puts("isSocket: " + JSON.stringify( s.isSocket() ) );
+  assertFalse(s.isSocket());
+
+  puts("isBlockDevice: " + JSON.stringify( s.isBlockDevice() ) );
+  assertFalse(s.isBlockDevice());
+
+  puts("isCharacterDevice: " + JSON.stringify( s.isCharacterDevice() ) );
+  assertFalse(s.isCharacterDevice());
+
+  puts("isFIFO: " + JSON.stringify( s.isFIFO() ) );
+  assertFalse(s.isFIFO());
+
+  puts("isSymbolicLink: " + JSON.stringify( s.isSymbolicLink() ) );
+  assertFalse(s.isSymbolicLink());
+}).addErrback(function () {
+  got_error = true;
+});
+
+
 process.addListener("exit", function () {
-  assertTrue(got_success);
+  assertEquals(2, success_count);
   assertFalse(got_error);
   assertTrue(stats.mtime instanceof Date);
 });