Created
January 29, 2011 03:21
-
-
Save joeshaw/801475 to your computer and use it in GitHub Desktop.
add access(2) to node
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git i/lib/fs.js w/lib/fs.js | |
index d094462..ed21d56 100644 | |
--- i/lib/fs.js | |
+++ w/lib/fs.js | |
@@ -401,6 +401,14 @@ fs.chownSync = function(path, uid, gid) { | |
return binding.chown(path, uid, gid); | |
}; | |
+fs.access = function(path, amode, callback) { | |
+ binding.access(path, amode, callback || noop); | |
+}; | |
+ | |
+fs.accessSync = function(path, amode) { | |
+ return binding.access(path, amode); | |
+}; | |
+ | |
function writeAll(fd, buffer, offset, length, callback) { | |
// write(fd, buffer, offset, length, position, callback) | |
fs.write(fd, buffer, offset, length, offset, function(writeErr, written) { | |
diff --git i/src/node_constants.cc w/src/node_constants.cc | |
index 7ea3722..4df3552 100644 | |
--- i/src/node_constants.cc | |
+++ w/src/node_constants.cc | |
@@ -28,6 +28,12 @@ void DefineConstants(Handle<Object> target) { | |
NODE_DEFINE_CONSTANT(target, O_WRONLY); | |
NODE_DEFINE_CONSTANT(target, O_RDWR); | |
+ // access(2) amodes | |
+ NODE_DEFINE_CONSTANT(target, R_OK); | |
+ NODE_DEFINE_CONSTANT(target, W_OK); | |
+ NODE_DEFINE_CONSTANT(target, X_OK); | |
+ NODE_DEFINE_CONSTANT(target, F_OK); | |
+ | |
NODE_DEFINE_CONSTANT(target, S_IFMT); | |
NODE_DEFINE_CONSTANT(target, S_IFREG); | |
NODE_DEFINE_CONSTANT(target, S_IFDIR); | |
diff --git i/src/node_file.cc w/src/node_file.cc | |
index 5cc1f22..ae4c408 100644 | |
--- i/src/node_file.cc | |
+++ w/src/node_file.cc | |
@@ -824,6 +824,118 @@ static Handle<Value> Chown(const Arguments& args) { | |
} | |
#endif // __POSIX__ | |
+/* fs.access(path, amode) | |
+ * Wrapper for access(2) | |
+ */ | |
+#ifdef __POSIX__ | |
+struct access_request { | |
+ Persistent<Function> cb; | |
+ char *path; | |
+ int amode; | |
+ int result; | |
+ int errorno; | |
+}; | |
+ | |
+static int EIO_Access(eio_req *req) { | |
+ struct access_request *areq = (struct access_request *) req->data; | |
+ | |
+ areq->result = access(areq->path, areq->amode); | |
+ areq->errorno = errno; | |
+ return 0; | |
+} | |
+ | |
+static int EIO_AfterAccess(eio_req *req) { | |
+ ev_unref(EV_DEFAULT_UC); | |
+ | |
+ struct access_request *areq = (struct access_request *) req->data; | |
+ | |
+ HandleScope scope; | |
+ Local<Value> argv[2]; | |
+ | |
+ if (areq->result != 0) { | |
+ switch (areq->errorno) { | |
+ case EACCES: | |
+ case EROFS: | |
+ argv[0] = Local<Value>::New(Null()); | |
+ argv[1] = Local<Value>::New(False()); | |
+ break; | |
+ | |
+ default: | |
+ argv[0] = ErrnoException(areq->errorno, | |
+ "access", | |
+ "", | |
+ areq->path); | |
+ argv[1] = Local<Value>::New(False()); | |
+ break; | |
+ } | |
+ } else { | |
+ argv[0] = Local<Value>::New(Null()); | |
+ argv[1] = Local<Value>::New(True()); | |
+ } | |
+ | |
+ TryCatch try_catch; | |
+ | |
+ areq->cb->Call(Context::GetCurrent()->Global(), 2, argv); | |
+ | |
+ if (try_catch.HasCaught()) { | |
+ FatalException(try_catch); | |
+ } | |
+ | |
+ free(areq->path); | |
+ areq->cb.Dispose(); | |
+ free(areq); | |
+ | |
+ return 0; | |
+} | |
+ | |
+static Handle<Value> Access(const Arguments& args) { | |
+ HandleScope scope; | |
+ | |
+ if (args.Length() < 2 || !args[0]->IsString() || !args[1]->IsInt32()) { | |
+ return THROW_BAD_ARGS; | |
+ } | |
+ | |
+ String::Utf8Value path(args[0]->ToString()); | |
+ int amode = args[1]->Int32Value(); | |
+ | |
+ if (args[2]->IsFunction()) { | |
+ struct access_request *areq = (struct access_request *) | |
+ calloc(1, sizeof(struct access_request)); | |
+ | |
+ if (!areq) { | |
+ V8::LowMemoryNotification(); | |
+ return ThrowException(Exception::Error( | |
+ String::New("Could not allocate enough memory"))); | |
+ } | |
+ | |
+ Local<Function> cb = Local<Function>::Cast(args[2]); | |
+ | |
+ areq->path = (char *) calloc(1, path.length() + 1); | |
+ strncpy(areq->path, *path, path.length() + 1); | |
+ areq->amode = amode; | |
+ areq->cb = Persistent<Function>::New(cb); | |
+ | |
+ eio_custom(EIO_Access, EIO_PRI_DEFAULT, EIO_AfterAccess, areq); | |
+ ev_ref(EV_DEFAULT_UC); | |
+ } else { | |
+ int ret = access(*path, amode); | |
+ | |
+ if (ret != 0) { | |
+ switch (errno) { | |
+ case EACCES: | |
+ case EROFS: | |
+ return False(); | |
+ | |
+ default: | |
+ return ThrowException(ErrnoException(errno, NULL, "", *path)); | |
+ } | |
+ } else { | |
+ return True(); | |
+ } | |
+ } | |
+} | |
+#endif // __POSIX__ | |
+ | |
void File::Initialize(Handle<Object> target) { | |
HandleScope scope; | |
@@ -854,6 +966,7 @@ void File::Initialize(Handle<Object> target) { | |
NODE_SET_METHOD(target, "chmod", Chmod); | |
#ifdef __POSIX__ | |
NODE_SET_METHOD(target, "chown", Chown); | |
+ NODE_SET_METHOD(target, "access", Access); | |
#endif // __POSIX__ | |
errno_symbol = NODE_PSYMBOL("errno"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment