Browse Source

os: add userInfo() method

os.userInfo() calls libuv's uv_os_get_passwd() function. It returns
an object containing the current effective user's username, uid,
gid, shell, and home directory. On Windows, the uid and gid are
-1, and the shell is null.

Refs: https://github.com/nodejs/node/issues/5582
PR-URL: https://github.com/nodejs/node/pull/6104
Reviewed-By: James M Snell <jasnell@gmail.com>
v6.x
cjihrig 9 years ago
committed by James M Snell
parent
commit
e052096ee0
  1. 16
      doc/api/os.markdown
  2. 1
      lib/os.js
  3. 4
      src/env.h
  4. 69
      src/node_os.cc
  5. 24
      test/parallel/test-os.js

16
doc/api/os.markdown

@ -182,5 +182,21 @@ on OS X and `'Windows_NT'` on Windows.
Returns the system uptime in seconds.
## os.userInfo([options])
* `options` {Object}
* `encoding` {String} Character encoding used to interpret resulting strings.
If `encoding` is set to `'buffer'`, the `username`, `shell`, and `homedir`
values will be `Buffer` instances. (Default: 'utf8')
Returns a subset of the password file entry for the current effective user. The
returned object includes the `username`, `uid`, `gid`, `shell`, and `homedir`.
On Windows, the `uid` and `gid` fields are `-1`, and `shell` is `null`.
The value of `homedir` returned by `userInfo()` comes directly from the
operating system. This differs from the result of `os.homedir()`, which queries
several environment variables for the home directory before falling back to the
operating system response.
[`process.arch`]: process.html#process_process_arch
[`process.platform`]: process.html#process_process_platform

1
lib/os.js

@ -14,6 +14,7 @@ exports.type = binding.getOSType;
exports.release = binding.getOSRelease;
exports.networkInterfaces = binding.getInterfaceAddresses;
exports.homedir = binding.getHomeDirectory;
exports.userInfo = binding.getUserInfo;
exports.arch = function() {

4
src/env.h

@ -94,6 +94,7 @@ namespace node {
V(exchange_string, "exchange") \
V(idle_string, "idle") \
V(irq_string, "irq") \
V(encoding_string, "encoding") \
V(enter_string, "enter") \
V(env_pairs_string, "envPairs") \
V(env_string, "env") \
@ -121,6 +122,7 @@ namespace node {
V(handle_string, "handle") \
V(heap_total_string, "heapTotal") \
V(heap_used_string, "heapUsed") \
V(homedir_string, "homedir") \
V(hostmaster_string, "hostmaster") \
V(ignore_string, "ignore") \
V(immediate_callback_string, "_immediateCallback") \
@ -206,6 +208,7 @@ namespace node {
V(service_string, "service") \
V(servername_string, "servername") \
V(session_id_string, "sessionId") \
V(shell_string, "shell") \
V(signal_string, "signal") \
V(size_string, "size") \
V(sni_context_err_string, "Invalid SNI context") \
@ -235,6 +238,7 @@ namespace node {
V(uid_string, "uid") \
V(unknown_string, "<unknown>") \
V(user_string, "user") \
V(username_string, "username") \
V(uv_string, "uv") \
V(valid_from_string, "valid_from") \
V(valid_to_string, "valid_to") \

69
src/node_os.cc

@ -2,6 +2,7 @@
#include "v8.h"
#include "env.h"
#include "env-inl.h"
#include "string_bytes.h"
#include <errno.h>
#include <string.h>
@ -32,6 +33,7 @@ using v8::Context;
using v8::FunctionCallbackInfo;
using v8::Integer;
using v8::Local;
using v8::Null;
using v8::Number;
using v8::Object;
using v8::String;
@ -290,6 +292,72 @@ static void GetHomeDirectory(const FunctionCallbackInfo<Value>& args) {
}
static void GetUserInfo(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
uv_passwd_t pwd;
enum encoding encoding;
if (args[0]->IsObject()) {
Local<Object> options = args[0].As<Object>();
Local<Value> encoding_opt = options->Get(env->encoding_string());
encoding = ParseEncoding(env->isolate(), encoding_opt, UTF8);
} else {
encoding = UTF8;
}
const int err = uv_os_get_passwd(&pwd);
if (err) {
return env->ThrowUVException(err, "uv_os_get_passwd");
}
Local<Value> uid = Number::New(env->isolate(), pwd.uid);
Local<Value> gid = Number::New(env->isolate(), pwd.gid);
Local<Value> username = StringBytes::Encode(env->isolate(),
pwd.username,
encoding);
Local<Value> homedir = StringBytes::Encode(env->isolate(),
pwd.homedir,
encoding);
Local<Value> shell;
if (pwd.shell == NULL)
shell = Null(env->isolate());
else
shell = StringBytes::Encode(env->isolate(), pwd.shell, encoding);
uv_os_free_passwd(&pwd);
if (username.IsEmpty()) {
return env->ThrowUVException(UV_EINVAL,
"uv_os_get_passwd",
"Invalid character encoding for username");
}
if (homedir.IsEmpty()) {
return env->ThrowUVException(UV_EINVAL,
"uv_os_get_passwd",
"Invalid character encoding for homedir");
}
if (shell.IsEmpty()) {
return env->ThrowUVException(UV_EINVAL,
"uv_os_get_passwd",
"Invalid character encoding for shell");
}
Local<Object> entry = Object::New(env->isolate());
entry->Set(env->uid_string(), uid);
entry->Set(env->gid_string(), gid);
entry->Set(env->username_string(), username);
entry->Set(env->homedir_string(), homedir);
entry->Set(env->shell_string(), shell);
args.GetReturnValue().Set(entry);
}
void Initialize(Local<Object> target,
Local<Value> unused,
Local<Context> context) {
@ -304,6 +372,7 @@ void Initialize(Local<Object> target,
env->SetMethod(target, "getOSRelease", GetOSRelease);
env->SetMethod(target, "getInterfaceAddresses", GetInterfaceAddresses);
env->SetMethod(target, "getHomeDirectory", GetHomeDirectory);
env->SetMethod(target, "getUserInfo", GetUserInfo);
target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "isBigEndian"),
Boolean::New(env->isolate(), IsBigEndian()));
}

24
test/parallel/test-os.js

@ -125,3 +125,27 @@ if (common.isWindows && process.env.USERPROFILE) {
assert.ok(os.homedir().indexOf(path.sep) !== -1);
process.env.HOME = home;
}
const pwd = os.userInfo();
const pwdBuf = os.userInfo({ encoding: 'buffer' });
if (common.isWindows) {
assert.strictEqual(pwd.uid, -1);
assert.strictEqual(pwd.gid, -1);
assert.strictEqual(pwd.shell, null);
assert.strictEqual(pwdBuf.uid, -1);
assert.strictEqual(pwdBuf.gid, -1);
assert.strictEqual(pwdBuf.shell, null);
} else {
assert.strictEqual(typeof pwd.uid, 'number');
assert.strictEqual(typeof pwd.gid, 'number');
assert.notStrictEqual(pwd.shell.indexOf(path.sep), -1);
assert.strictEqual(pwd.uid, pwdBuf.uid);
assert.strictEqual(pwd.gid, pwdBuf.gid);
assert.strictEqual(pwd.shell, pwdBuf.shell.toString('utf8'));
}
assert.strictEqual(typeof pwd.username, 'string');
assert.notStrictEqual(pwd.homedir.indexOf(path.sep), -1);
assert.strictEqual(pwd.username, pwdBuf.username.toString('utf8'));
assert.strictEqual(pwd.homedir, pwdBuf.homedir.toString('utf8'));

Loading…
Cancel
Save