Permalink
Browse files

Add utime(2) functions.

The attempt to include fs.utimes() into node finds that utimes() is explicitly
not supported by Windows. utime() is better supported. Add that here.
  • Loading branch information...
1 parent 6d3a971 commit e3300eb8ee4639dab9015c04290e8245bb185e3c @tshinnic tshinnic committed Jun 27, 2011
Showing with 779 additions and 5 deletions.
  1. +20 −0 README.md
  2. +68 −1 fs-ext.cc
  3. +32 −4 fs-ext.js
  4. +2 −0 run_tests
  5. +365 −0 tests/test-fs-utime.js
  6. +292 −0 tests/test-fs-utime_stress.js
View
@@ -53,3 +53,23 @@ plus offset bytes (usually negative or zero to seek to the end of the file).
Synchronous lseek(2). Throws an exception on error. Returns current
file position.
+
+
+### fs.utime(path [, atime, mtime] [, callback])
+
+Asynchronous utime(2).
+
+Arguments `atime` and `mtime` are in seconds as for the system call. Note
+that the number value of Date() is in milliseconds, so to use the 'now'
+value with `fs.utime()` you would have to divide by 1000 first, e.g.
+Date.now()/1000
+
+Just like for utime(2), the absence of the `atime` and `mtime` means 'now'.
+
+### fs.utimeSync(path [, atime, mtime])
+
+Synchronous version of utime(). Throws an exception on error.
+
+
+
+
View
@@ -24,6 +24,9 @@
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <utime.h>
#ifdef _WIN32
#include <windows.h>
@@ -41,6 +44,8 @@ struct store_data_t {
int fd;
int oper;
off_t offset;
+ struct utimbuf utime_buf;
+ char *path;
};
enum
@@ -63,7 +68,7 @@ static int After(eio_req *req) {
// Allocate space for two args: error plus possible additional result
Local<Value> argv[2];
- // NOTE: This may be needed to be changed if something returns a -1
+ // NOTE: This may need to be changed if something returns a -1
// for a success, which is possible.
if (req->result == -1) {
// If the request doesn't have a path parameter set.
@@ -75,6 +80,7 @@ static int After(eio_req *req) {
switch (store_data->fs_op) {
// These operations have no data to pass other than "error".
case FS_OP_FLOCK:
+ case FS_OP_UTIME:
argc = 1;
break;
@@ -270,6 +276,66 @@ static Handle<Value> Seek(const Arguments& args) {
return Undefined();
}
+
+static int EIO_UTime(eio_req *req) {
+ store_data_t* utime_data = static_cast<store_data_t *>(req->data);
+
+ off_t i = utime(utime_data->path, &utime_data->utime_buf);
+ free( utime_data->path );
+
+ if (i == (off_t)-1) {
+ req->result = -1;
+ req->errorno = errno;
+ } else {
+ req->result = i;
+ }
+
+ return 0;
+}
+
+// Wrapper for utime(2).
+// fs.utime( path, atime, mtime, [callback] )
+
+static Handle<Value> UTime(const Arguments& args) {
+ HandleScope scope;
+
+ if (args.Length() < 3 ||
+ args.Length() > 4 ||
+ !args[0]->IsString() ||
+ !args[1]->IsNumber() ||
+ !args[2]->IsNumber() ) {
+ return THROW_BAD_ARGS;
+ }
+
+ String::Utf8Value path(args[0]->ToString());
+ time_t atime = args[1]->IntegerValue();
+ time_t mtime = args[2]->IntegerValue();
+
+ // Synchronous call needs much less work
+ if ( ! args[3]->IsFunction()) {
+ struct utimbuf buf;
+ buf.actime = atime;
+ buf.modtime = mtime;
+ int ret = utime(*path, &buf);
+ if (ret != 0) return ThrowException(ErrnoException(errno, "utime", "", *path));
+ return Undefined();
+ }
+
+ store_data_t* utime_data = new store_data_t();
+
+ utime_data->cb = cb_persist(args[3]);
+ utime_data->fs_op = FS_OP_UTIME;
+ utime_data->path = strdup(*path);
+ utime_data->utime_buf.actime = atime;
+ utime_data->utime_buf.modtime = mtime;
+
+ eio_custom(EIO_UTime, EIO_PRI_DEFAULT, After, utime_data);
+ ev_ref(EV_DEFAULT_UC);
+ return Undefined();
+}
+
+
+
extern "C" void
init (Handle<Object> target)
{
@@ -305,4 +371,5 @@ init (Handle<Object> target)
NODE_SET_METHOD(target, "seek", Seek);
NODE_SET_METHOD(target, "flock", Flock);
+ NODE_SET_METHOD(target, "utime", UTime);
}
View
@@ -59,13 +59,13 @@ exports.flock = function(fd, flags, callback) {
var oper = stringToFlockFlags(flags);
binding.flock(fd, oper, callback);
-}
+};
exports.flockSync = function(fd, flags) {
var oper = stringToFlockFlags(flags);
return binding.flock(fd, oper);
-}
+};
exports.seek = function(fd, position, whence, callback) {
callback = arguments[arguments.length - 1];
@@ -74,11 +74,39 @@ exports.seek = function(fd, position, whence, callback) {
}
binding.seek(fd, position, whence, callback);
-}
+};
exports.seekSync = function(fd, position, whence) {
return binding.seek(fd, position, whence);
-}
+};
+
+
+// fs.utime('foo' [, atime, mtime] [, func] )
+
+exports.utime = function(path, atime, mtime, callback) {
+ callback = arguments[arguments.length - 1];
+ if (typeof(callback) !== 'function') {
+ callback = noop;
+ }
+
+ if (typeof(atime) !== 'number' && typeof(mtime) !== 'number') {
+ atime = mtime = Date.now() / 1000;
+ }
+
+ binding.utime(path, atime, mtime, callback);
+};
+
+// fs.utimeSync('foo' [, atime, mtime] )
+
+exports.utimeSync = function(path, atime, mtime) {
+
+ if (typeof(atime) !== 'number' && typeof(mtime) !== 'number') {
+ atime = mtime = Date.now() / 1000;
+ }
+
+ return binding.utime(path, atime, mtime);
+};
+
// populate with fs functions from there
for (var key in fs) {
View
@@ -4,6 +4,8 @@ node tests/test-fs-seek.js
node tests/test-fs-flock.js
+node tests/test-fs-utime.js
+
# for stress testing only
# node tests/test-fs-seek_stress.js
# node tests/test-fs-flock_stress.js
Oops, something went wrong.

0 comments on commit e3300eb

Please sign in to comment.