From 5f2e90934e523b2fe102e3e5bae3ea76535ab8b5 Mon Sep 17 00:00:00 2001 From: isaacs Date: Tue, 25 Jan 2011 10:40:12 -0800 Subject: [PATCH] Support octal strings for modes 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. --- lib/fs.js | 31 ++++++++++++++++++++++--------- src/node.cc | 34 +++++++++++++++++++++++++++------- test/simple/test-fs-chmod.js | 2 +- test/simple/test-umask.js | 4 ++-- 4 files changed, 52 insertions(+), 19 deletions(-) diff --git a/lib/fs.js b/lib/fs.js index d0944620bd..9645b7679a 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -171,8 +171,21 @@ 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); @@ -180,7 +193,7 @@ fs.open = function(path, flags, mode_, callback) { }; fs.openSync = function(path, flags, mode) { - if (mode === undefined) { mode = 0666; } + mode = modeNum(mode, '0666'); return binding.open(path, stringToFlags(flags), mode); }; @@ -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) { @@ -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) { @@ -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 || {}; @@ -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 || {}; diff --git a/src/node.cc b/src/node.cc index a52d3e3f5a..ea55aa795c 100644 --- a/src/node.cc +++ b/src/node.cc @@ -1329,17 +1329,37 @@ static Handle Cwd(const Arguments& args) { static Handle 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(oct)); } + return scope.Close(Uint32::New(old)); } diff --git a/test/simple/test-fs-chmod.js b/test/simple/test-fs-chmod.js index 65268503b0..ded7bf6724 100644 --- a/test/simple/test-fs-chmod.js +++ b/test/simple/test-fs-chmod.js @@ -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 { diff --git a/test/simple/test-umask.js b/test/simple/test-umask.js index cbb42ee2f9..cd6d6c997a 100644 --- a/test/simple/test-umask.js +++ b/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