Skip to content
This repository has been archived by the owner on Apr 22, 2023. It is now read-only.

Commit

Permalink
Support octal strings for modes
Browse files Browse the repository at this point in the history
This allows the various fs utilities and process.umask to be used in
ECMAScript 5 Strict Mode, where the octal literal format is verboten,
without requiring users to litter their code with a bunch of parseInt
calls.
  • Loading branch information
isaacs authored and ry committed Feb 7, 2011
1 parent 57fa247 commit 5f2e909
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 19 deletions.
31 changes: 22 additions & 9 deletions lib/fs.js
Expand Up @@ -171,16 +171,29 @@ fs.closeSync = function(fd) {
return binding.close(fd);
};

fs.open = function(path, flags, mode_, callback) {
var mode = (typeof(mode_) == 'number' ? mode_ : 0666);
function modeNum(m, def) {
switch(typeof m) {
case 'number': return m;
case 'string': return parseInt(m, 8);
default:
if (def) {
return modeNum(def);
} else {
return undefined;
}
}
}

fs.open = function(path, flags, mode, callback) {
mode = modeNum(mode, '0666');
var callback_ = arguments[arguments.length - 1];
var callback = (typeof(callback_) == 'function' ? callback_ : null);

binding.open(path, stringToFlags(flags), mode, callback || noop);
};

fs.openSync = function(path, flags, mode) {
if (mode === undefined) { mode = 0666; }
mode = modeNum(mode, '0666');
return binding.open(path, stringToFlags(flags), mode);
};

Expand Down Expand Up @@ -306,11 +319,11 @@ fs.fsyncSync = function(fd) {
};

fs.mkdir = function(path, mode, callback) {
binding.mkdir(path, mode, callback || noop);
binding.mkdir(path, modeNum(mode), callback || noop);
};

fs.mkdirSync = function(path, mode) {
return binding.mkdir(path, mode);
return binding.mkdir(path, modeNum(mode));
};

fs.sendfile = function(outFd, inFd, inOffset, length, callback) {
Expand Down Expand Up @@ -386,11 +399,11 @@ fs.unlinkSync = function(path) {
};

fs.chmod = function(path, mode, callback) {
binding.chmod(path, mode, callback || noop);
binding.chmod(path, modeNum(mode), callback || noop);
};

fs.chmodSync = function(path, mode) {
return binding.chmod(path, mode);
return binding.chmod(path, modeNum(mode));
};

fs.chown = function(path, uid, gid, callback) {
Expand Down Expand Up @@ -684,7 +697,7 @@ var ReadStream = fs.ReadStream = function(path, options) {
this.paused = false;

this.flags = 'r';
this.mode = 0666;
this.mode = parseInt('0666', 8);
this.bufferSize = 64 * 1024;

options = options || {};
Expand Down Expand Up @@ -871,7 +884,7 @@ var WriteStream = fs.WriteStream = function(path, options) {

this.flags = 'w';
this.encoding = 'binary';
this.mode = 0666;
this.mode = parseInt('0666', 8);

options = options || {};

Expand Down
34 changes: 27 additions & 7 deletions src/node.cc
Expand Up @@ -1329,17 +1329,37 @@ static Handle<Value> Cwd(const Arguments& args) {
static Handle<Value> Umask(const Arguments& args){
HandleScope scope;
unsigned int old;
if(args.Length() < 1) {

if(args.Length() < 1 || args[0]->IsUndefined()) {
old = umask(0);
umask((mode_t)old);
}
else if(!args[0]->IsInt32()) {

} else if(!args[0]->IsInt32() && !args[0]->IsString()) {
return ThrowException(Exception::TypeError(
String::New("argument must be an integer.")));
}
else {
old = umask((mode_t)args[0]->Uint32Value());
String::New("argument must be an integer or octal string.")));

} else {
int oct;
if(args[0]->IsInt32()) {
oct = args[0]->Uint32Value();
} else {
oct = 0;
String::Utf8Value str(args[0]);

// Parse the octal string.
for (int i = 0; i < str.length(); i++) {
char c = (*str)[i];
if (c > '7' || c < '0') {
return ThrowException(Exception::TypeError(
String::New("invalid octal string")));
}
oct *= 8;
oct += c - '0';
}
}
old = umask(static_cast<mode_t>(oct));
}

return scope.Close(Uint32::New(old));
}

Expand Down
2 changes: 1 addition & 1 deletion test/simple/test-fs-chmod.js
Expand Up @@ -7,7 +7,7 @@ var success_count = 0;

var file = path.join(common.fixturesDir, 'a.js');

fs.chmod(file, 0777, function(err) {
fs.chmod(file, '0777', function(err) {
if (err) {
got_error = true;
} else {
Expand Down
4 changes: 2 additions & 2 deletions test/simple/test-umask.js
@@ -1,10 +1,10 @@
var common = require('../common');
var assert = require('assert');

var mask = 0664;
var mask = '0664';
var old = process.umask(mask);

assert.equal(mask, process.umask(old));
assert.equal(parseInt(mask, 8), process.umask(old));

// confirm reading the umask does not modify it.
// 1. If the test fails, this call will succeed, but the mask will be set to 0
Expand Down

0 comments on commit 5f2e909

Please sign in to comment.