Skip to content

Instantly share code, notes, and snippets.

@joeshaw
Created January 29, 2011 03:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joeshaw/801475 to your computer and use it in GitHub Desktop.
Save joeshaw/801475 to your computer and use it in GitHub Desktop.
add access(2) to node
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");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment