Skip to content

Instantly share code, notes, and snippets.

@isaacs
Created March 29, 2011 23:35
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 isaacs/893568 to your computer and use it in GitHub Desktop.
Save isaacs/893568 to your computer and use it in GitHub Desktop.
From b528e076cedc7c37a9eaea7c635eebbf7a50f25f Mon Sep 17 00:00:00 2001
From: isaacs <i@izs.me>
Date: Tue, 29 Mar 2011 15:31:41 -0700
Subject: [PATCH 1/2] GH-853 fs.fchmod and fs.fchown
---
lib/fs.js | 16 ++++++++++
src/node_file.cc | 69 ++++++++++++++++++++++++++++++++++++++---
test/simple/test-fs-chmod.js | 22 +++++++++++++-
3 files changed, 101 insertions(+), 6 deletions(-)
diff --git a/lib/fs.js b/lib/fs.js
index 062b4a3..bfa6ebf 100644
--- a/lib/fs.js
+++ b/lib/fs.js
@@ -422,6 +422,14 @@ fs.unlinkSync = function(path) {
return binding.unlink(path);
};
+fs.fchmod = function(fd, mode, callback) {
+ binding.fchmod(fd, modeNum(mode), callback || noop);
+};
+
+fs.fchmodSync = function(fd, mode) {
+ return binding.fchmod(fd, modeNum(mode));
+};
+
fs.chmod = function(path, mode, callback) {
binding.chmod(path, modeNum(mode), callback || noop);
};
@@ -430,6 +438,14 @@ fs.chmodSync = function(path, mode) {
return binding.chmod(path, modeNum(mode));
};
+fs.fchown = function(fd, uid, gid, callback) {
+ binding.fchown(fd, uid, gid, callback || noop);
+};
+
+fs.fchownSync = function(fd, uid, gid) {
+ return binding.fchown(fd, uid, gid);
+};
+
fs.chown = function(path, uid, gid, callback) {
binding.chown(path, uid, gid, callback || noop);
};
diff --git a/src/node_file.cc b/src/node_file.cc
index 8b7f374..4b23c4f 100644
--- a/src/node_file.cc
+++ b/src/node_file.cc
@@ -126,7 +126,9 @@ static int After(eio_req *req) {
case EIO_LINK:
case EIO_SYMLINK:
case EIO_CHMOD:
+ case EIO_FCHMOD:
case EIO_CHOWN:
+ case EIO_FCHOWN:
// These, however, don't.
argc = 1;
break;
@@ -799,7 +801,7 @@ static Handle<Value> Read(const Arguments& args) {
}
-/* fs.chmod(fd, mode);
+/* fs.chmod(path, mode);
* Wrapper for chmod(1) / EIO_CHMOD
*/
static Handle<Value> Chmod(const Arguments& args) {
@@ -815,16 +817,38 @@ static Handle<Value> Chmod(const Arguments& args) {
ASYNC_CALL(chmod, args[2], *path, mode);
} else {
int ret = chmod(*path, mode);
- if (ret != 0) return ThrowException(ErrnoException(errno, NULL, "", *path));
+ if (ret != 0) return ThrowException(ErrnoException(errno, "chmod", "", *path));
return Undefined();
}
}
-/* fs.chown(fd, uid, gid);
- * Wrapper for chown(1) / EIO_CHOWN
+/* fs.fchmod(fd, mode);
+ * Wrapper for fchmod(1) / EIO_FCHMOD
*/
+static Handle<Value> FChmod(const Arguments& args) {
+ HandleScope scope;
+
+ if(args.Length() < 2 || !args[0]->IsInt32() || !args[1]->IsInt32()) {
+ return THROW_BAD_ARGS;
+ }
+ int fd = args[0]->Int32Value();
+ mode_t mode = static_cast<mode_t>(args[1]->Int32Value());
+
+ if(args[2]->IsFunction()) {
+ ASYNC_CALL(fchmod, args[2], fd, mode);
+ } else {
+ int ret = fchmod(fd, mode);
+ if (ret != 0) return ThrowException(ErrnoException(errno, "fchmod", "", 0));
+ return Undefined();
+ }
+}
+
+
#ifdef __POSIX__
+/* fs.chown(path, uid, gid);
+ * Wrapper for chown(1) / EIO_CHOWN
+ */
static Handle<Value> Chown(const Arguments& args) {
HandleScope scope;
@@ -844,7 +868,37 @@ static Handle<Value> Chown(const Arguments& args) {
ASYNC_CALL(chown, args[3], *path, uid, gid);
} else {
int ret = chown(*path, uid, gid);
- if (ret != 0) return ThrowException(ErrnoException(errno, NULL, "", *path));
+ if (ret != 0) return ThrowException(ErrnoException(errno, "chown", "", *path));
+ return Undefined();
+ }
+}
+#endif // __POSIX__
+
+
+#ifdef __POSIX__
+/* fs.fchown(fd, uid, gid);
+ * Wrapper for fchown(1) / EIO_FCHOWN
+ */
+static Handle<Value> FChown(const Arguments& args) {
+ HandleScope scope;
+
+ if (args.Length() < 3 || !args[0]->IsInt32()) {
+ return THROW_BAD_ARGS;
+ }
+
+ if (!args[1]->IsInt32() || !args[2]->IsInt32()) {
+ return ThrowException(Exception::Error(String::New("User and Group IDs must be an integer.")));
+ }
+
+ int fd = args[0]->Int32Value();
+ uid_t uid = static_cast<uid_t>(args[1]->Int32Value());
+ gid_t gid = static_cast<gid_t>(args[2]->Int32Value());
+
+ if (args[3]->IsFunction()) {
+ ASYNC_CALL(fchown, args[3], fd, uid, gid);
+ } else {
+ int ret = fchown(fd, uid, gid);
+ if (ret != 0) return ThrowException(ErrnoException(errno, "fchown", "", 0));
return Undefined();
}
}
@@ -955,8 +1009,13 @@ void File::Initialize(Handle<Object> target) {
NODE_SET_METHOD(target, "write", Write);
NODE_SET_METHOD(target, "chmod", Chmod);
+ NODE_SET_METHOD(target, "fchmod", FChmod);
#ifdef __POSIX__
+ //NODE_SET_METHOD(target, "lchmod", LChmod);
+
NODE_SET_METHOD(target, "chown", Chown);
+ NODE_SET_METHOD(target, "fchown", FChown);
+ //NODE_SET_METHOD(target, "lchown", LChown);
#endif // __POSIX__
NODE_SET_METHOD(target, "utimes", UTimes);
diff --git a/test/simple/test-fs-chmod.js b/test/simple/test-fs-chmod.js
index 7616c8b..12afc47 100644
--- a/test/simple/test-fs-chmod.js
+++ b/test/simple/test-fs-chmod.js
@@ -41,8 +41,28 @@ fs.chmod(file, '0777', function(err) {
}
});
+fs.open(file, 'w', function(err, fd) {
+ if (err) {
+ got_error = true;
+ console.error(err.stack);
+ return;
+ }
+ fs.fchmod(fd, '0777', function(err) {
+ if (err) {
+ got_error = true;
+ } else {
+ console.log(fs.fstatSync(fd).mode);
+ assert.equal(0777, fs.fstatSync(fd).mode & 0777);
+
+ fs.fchmodSync(fd, 0644);
+ assert.equal(0644, fs.fstatSync(fd).mode & 0777);
+ success_count++;
+ }
+ });
+});
+
process.addListener('exit', function() {
- assert.equal(1, success_count);
+ assert.equal(2, success_count);
assert.equal(false, got_error);
});
--
1.7.2.3
From 84d5deae3798daf3fd7c5560c0c17fada99eb60c Mon Sep 17 00:00:00 2001
From: isaacs <i@izs.me>
Date: Tue, 29 Mar 2011 16:34:05 -0700
Subject: [PATCH 2/2] GH-853 fs.lchown and fs.lchmod
---
lib/fs.js | 37 +++++++++++++++++++++++++++++++++++++
src/node_constants.cc | 5 +++++
2 files changed, 42 insertions(+), 0 deletions(-)
diff --git a/lib/fs.js b/lib/fs.js
index bfa6ebf..aba2940 100644
--- a/lib/fs.js
+++ b/lib/fs.js
@@ -430,6 +430,25 @@ fs.fchmodSync = function(fd, mode) {
return binding.fchmod(fd, modeNum(mode));
};
+if (constants.hasOwnProperty('O_SYMLINK')) {
+ fs.lchmod = function(path, mode, callback) {
+ callback = callback || noop;
+ fs.open(path, constants.O_WRONLY | constants.O_SYMLINK, function (err, fd) {
+ if (err) {
+ callback(err);
+ return;
+ }
+ fs.fchmod(fd, mode, callback);
+ });
+ };
+
+ fs.lchmodSync = function(path, mode) {
+ var fd = fs.openSync(path, constants.O_WRONLY | constants.O_SYMLINK);
+ return fs.fchmodSync(fd, mode);
+ };
+}
+
+
fs.chmod = function(path, mode, callback) {
binding.chmod(path, modeNum(mode), callback || noop);
};
@@ -438,6 +457,24 @@ fs.chmodSync = function(path, mode) {
return binding.chmod(path, modeNum(mode));
};
+if (constants.hasOwnProperty('O_SYMLINK')) {
+ fs.lchown = function(path, uid, gid, callback) {
+ callback = callback || noop;
+ fs.open(path, constants.O_WRONLY | constants.O_SYMLINK, function (err, fd) {
+ if (err) {
+ callback(err);
+ return;
+ }
+ fs.fchown(fd, uid, gid, callback);
+ });
+ };
+
+ fs.lchownSync = function(path, uid, gid) {
+ var fd = fs.openSync(path, constants.O_WRONLY | constants.O_SYMLINK);
+ return fs.fchownSync(fd, uid, gid);
+ };
+}
+
fs.fchown = function(fd, uid, gid, callback) {
binding.fchown(fd, uid, gid, callback || noop);
};
diff --git a/src/node_constants.cc b/src/node_constants.cc
index ecb34a6..832b9e4 100644
--- a/src/node_constants.cc
+++ b/src/node_constants.cc
@@ -99,6 +99,11 @@ void DefineConstants(Handle<Object> target) {
NODE_DEFINE_CONSTANT(target, O_SYNC);
#endif
+#ifdef O_SYMLINK
+ NODE_DEFINE_CONSTANT(target, O_SYMLINK);
+#endif
+
+
#ifdef S_IRWXU
NODE_DEFINE_CONSTANT(target, S_IRWXU);
#endif
--
1.7.2.3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment