Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 692c5008a079
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 005a9027a595
Choose a head ref
  • 2 commits
  • 1 file changed
  • 1 contributor

Commits on Sep 13, 2016

  1. Synchronize all of Etc because UNIX is dumb. Fixes #4057.

    This also incorporates diffs from master, aligning both
    Etc implementations.
    headius committed Sep 13, 2016
    Copy the full SHA
    3f2bf93 View commit details
  2. Incorporate remaining diffs from master.

    Only diff is calling RubyArray.newArrayNoCopy instead of the
    9k-only newArrayMayCopy.
    headius committed Sep 13, 2016
    Copy the full SHA
    005a902 View commit details
Showing with 94 additions and 61 deletions.
  1. +94 −61 core/src/main/java/org/jruby/ext/etc/RubyEtc.java
155 changes: 94 additions & 61 deletions core/src/main/java/org/jruby/ext/etc/RubyEtc.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
package org.jruby.ext.etc;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.concurrent.atomic.AtomicBoolean;

import org.jruby.RubyArray;
import org.jruby.RubyHash;
import org.jruby.anno.JRubyMethod;
import org.jruby.anno.JRubyModule;
import org.jruby.common.IRubyWarnings.ID;
@@ -9,8 +14,8 @@
import jnr.posix.Group;
import jnr.posix.POSIX;
import jnr.posix.util.Platform;
import org.jruby.CompatVersion;
import org.jruby.Ruby;
import org.jruby.RubyFixnum;
import org.jruby.RubyModule;
import org.jruby.RubyNumeric;
import org.jruby.RubyString;
@@ -20,23 +25,23 @@
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.ByteList;
import org.jruby.util.NormalizedFile;
import org.jruby.util.SafePropertyAccessor;

@JRubyModule(name="Etc")
public class RubyEtc {
public static RubyModule createEtcModule(Ruby runtime) {
RubyModule etcModule = runtime.defineModule("Etc");

runtime.setEtc(etcModule);

etcModule.defineAnnotatedMethods(RubyEtc.class);

definePasswdStruct(runtime);
defineGroupStruct(runtime);

return etcModule;
}

private static void definePasswdStruct(Ruby runtime) {
IRubyObject[] args = new IRubyObject[] {
runtime.newString("Passwd"),
@@ -51,11 +56,9 @@ private static void definePasswdStruct(Ruby runtime) {
runtime.newSymbol("uclass"),
runtime.newSymbol("expire")
};

runtime.setPasswdStruct(RubyStruct.newInstance(runtime.getStructClass(), args, Block.NULL_BLOCK));
if (runtime.is1_9()) {
runtime.getEtc().defineConstant("Passwd", runtime.getPasswdStruct());
}
runtime.getEtc().defineConstant("Passwd", runtime.getPasswdStruct());
}

private static void defineGroupStruct(Ruby runtime) {
@@ -66,13 +69,11 @@ private static void defineGroupStruct(Ruby runtime) {
runtime.newSymbol("gid"),
runtime.newSymbol("mem")
};

runtime.setGroupStruct(RubyStruct.newInstance(runtime.getStructClass(), args, Block.NULL_BLOCK));
if (runtime.is1_9()) {
runtime.getEtc().defineConstant("Group", runtime.getGroupStruct());
}
runtime.getEtc().defineConstant("Group", runtime.getGroupStruct());
}

private static IRubyObject setupPasswd(Ruby runtime, Passwd passwd) {
IRubyObject[] args = new IRubyObject[] {
runtime.newString(passwd.getLoginName()),
@@ -87,19 +88,19 @@ private static IRubyObject setupPasswd(Ruby runtime, Passwd passwd) {
runtime.newFixnum(passwd.getExpire())

};

return RubyStruct.newStruct(runtime.getPasswdStruct(), args, Block.NULL_BLOCK);
}


private static IRubyObject setupGroup(Ruby runtime, Group group) {
IRubyObject[] args = new IRubyObject[] {
runtime.newString(group.getName()),
runtime.newString(group.getPassword()),
runtime.newFixnum(group.getGID()),
intoStringArray(runtime, group.getMembers())
};

return RubyStruct.newStruct(runtime.getGroupStruct(), args, Block.NULL_BLOCK);
}

@@ -108,14 +109,15 @@ private static IRubyObject intoStringArray(Ruby runtime, String[] members) {
for(int i = 0; i<arr.length; i++) {
arr[i] = runtime.newString(members[i]);
}
return runtime.newArrayNoCopy(arr);
return RubyArray.newArrayNoCopy(runtime, arr);
}


@JRubyMethod(name = "getpwuid", optional=1, module = true)
public static IRubyObject getpwuid(IRubyObject recv, IRubyObject[] args) {
@JRubyMethod(optional=1, module = true)
public static synchronized IRubyObject getpwuid(IRubyObject recv, IRubyObject[] args) {
Ruby runtime = recv.getRuntime();
POSIX posix = runtime.getPosix();
IRubyObject oldExc = runtime.getGlobalVariables().get("$!"); // Save $!
try {
int uid = args.length == 0 ? posix.getuid() : RubyNumeric.fix2int(args[0]);
Passwd pwd = posix.getpwuid(uid);
@@ -128,6 +130,7 @@ public static IRubyObject getpwuid(IRubyObject recv, IRubyObject[] args) {
return setupPasswd(runtime, pwd);
} catch (RaiseException re) {
if (runtime.getNotImplementedError().isInstance(re.getException())) {
runtime.getGlobalVariables().set("$!", oldExc); // Restore $!
return runtime.getNil();
}
throw re;
@@ -139,19 +142,21 @@ public static IRubyObject getpwuid(IRubyObject recv, IRubyObject[] args) {
}
}

@JRubyMethod(name = "getpwnam", required=1, module = true)
public static IRubyObject getpwnam(IRubyObject recv, IRubyObject name) {
@JRubyMethod(required=1, module = true)
public static synchronized IRubyObject getpwnam(IRubyObject recv, IRubyObject name) {
Ruby runtime = recv.getRuntime();
String nam = name.convertToString().toString();
try {
Passwd pwd = runtime.getPosix().getpwnam(nam);
if(pwd == null) {
if (pwd == null) {
if (Platform.IS_WINDOWS) { // MRI behavior
return runtime.getNil();
}
throw runtime.newArgumentError("can't find user for " + nam);
}
return setupPasswd(recv.getRuntime(), pwd);
} catch (RaiseException e) {
throw e;
} catch (Exception e) {
if (runtime.getDebug().isTrue()) {
runtime.getWarnings().warn(ID.NOT_IMPLEMENTED, "Etc.getpwnam is not supported by JRuby on this platform");
@@ -161,19 +166,19 @@ public static IRubyObject getpwnam(IRubyObject recv, IRubyObject name) {
}

@JRubyMethod(module = true)
public static IRubyObject passwd(IRubyObject recv, Block block) {
public static synchronized IRubyObject passwd(IRubyObject recv, Block block) {
Ruby runtime = recv.getRuntime();
POSIX posix = runtime.getPosix();
try {
// call getpwent to fail early if unsupported
posix.getpwent();
if(block.isGiven()) {
ThreadContext context = runtime.getCurrentContext();

if (!iteratingPasswd.compareAndSet(false, true)) {
throw runtime.newRuntimeError("parallel passwd iteration");
}

posix.setpwent();
try {
Passwd pw;
@@ -200,8 +205,8 @@ public static IRubyObject passwd(IRubyObject recv, Block block) {
}
}

@JRubyMethod(name = "getlogin", module = true)
public static IRubyObject getlogin(IRubyObject recv) {
@JRubyMethod(module = true)
public static synchronized IRubyObject getlogin(IRubyObject recv) {
Ruby runtime = recv.getRuntime();

try {
@@ -214,16 +219,16 @@ public static IRubyObject getlogin(IRubyObject recv) {
if (login != null) {
return runtime.newString(login);
}

return runtime.getNil();
} catch (Exception e) {
// fall back on env entry for USER
return runtime.newString(System.getProperty("user.name"));
}
}

@JRubyMethod(name = "endpwent", module = true)
public static IRubyObject endpwent(IRubyObject recv) {
@JRubyMethod(module = true)
public static synchronized IRubyObject endpwent(IRubyObject recv) {
Ruby runtime = recv.getRuntime();
try {
runtime.getPosix().endpwent();
@@ -235,8 +240,8 @@ public static IRubyObject endpwent(IRubyObject recv) {
return runtime.getNil();
}

@JRubyMethod(name = "setpwent", module = true)
public static IRubyObject setpwent(IRubyObject recv) {
@JRubyMethod(module = true)
public static synchronized IRubyObject setpwent(IRubyObject recv) {
Ruby runtime = recv.getRuntime();
try {
runtime.getPosix().setpwent();
@@ -248,8 +253,8 @@ public static IRubyObject setpwent(IRubyObject recv) {
return runtime.getNil();
}

@JRubyMethod(name = "getpwent", module = true)
public static IRubyObject getpwent(IRubyObject recv) {
@JRubyMethod(module = true)
public static synchronized IRubyObject getpwent(IRubyObject recv) {
Ruby runtime = recv.getRuntime();
try {
Passwd passwd = runtime.getPosix().getpwent();
@@ -266,19 +271,21 @@ public static IRubyObject getpwent(IRubyObject recv) {
}
}

@JRubyMethod(name = "getgrnam", required=1, module = true)
public static IRubyObject getgrnam(IRubyObject recv, IRubyObject name) {
@JRubyMethod(required=1, module = true)
public static synchronized IRubyObject getgrnam(IRubyObject recv, IRubyObject name) {
Ruby runtime = recv.getRuntime();
String nam = name.convertToString().toString();
try {
Group grp = runtime.getPosix().getgrnam(nam);
if(grp == null) {
if (grp == null) {
if (Platform.IS_WINDOWS) { // MRI behavior
return runtime.getNil();
}
throw runtime.newArgumentError("can't find group for " + nam);
}
return setupGroup(runtime, grp);
} catch (RaiseException e) {
throw e;
} catch (Exception e) {
if (runtime.getDebug().isTrue()) {
runtime.getWarnings().warn(ID.NOT_IMPLEMENTED, "Etc.getgrnam is not supported by JRuby on this platform");
@@ -287,8 +294,8 @@ public static IRubyObject getgrnam(IRubyObject recv, IRubyObject name) {
}
}

@JRubyMethod(name = "getgrgid", optional=1, module = true)
public static IRubyObject getgrgid(IRubyObject recv, IRubyObject[] args) {
@JRubyMethod(optional=1, module = true)
public static synchronized IRubyObject getgrgid(IRubyObject recv, IRubyObject[] args) {
Ruby runtime = recv.getRuntime();
POSIX posix = runtime.getPosix();

@@ -312,8 +319,8 @@ public static IRubyObject getgrgid(IRubyObject recv, IRubyObject[] args) {
}
}

@JRubyMethod(name = "endgrent", module = true)
public static IRubyObject endgrent(IRubyObject recv) {
@JRubyMethod(module = true)
public static synchronized IRubyObject endgrent(IRubyObject recv) {
Ruby runtime = recv.getRuntime();
try {
runtime.getPosix().endgrent();
@@ -326,7 +333,7 @@ public static IRubyObject endgrent(IRubyObject recv) {
}

@JRubyMethod(module = true)
public static IRubyObject setgrent(IRubyObject recv) {
public static synchronized IRubyObject setgrent(IRubyObject recv) {
Ruby runtime = recv.getRuntime();
try {
runtime.getPosix().setgrent();
@@ -339,7 +346,7 @@ public static IRubyObject setgrent(IRubyObject recv) {
}

@JRubyMethod(module = true)
public static IRubyObject group(IRubyObject recv, Block block) {
public static synchronized IRubyObject group(IRubyObject recv, Block block) {
Ruby runtime = recv.getRuntime();
POSIX posix = runtime.getPosix();

@@ -383,8 +390,8 @@ public static IRubyObject group(IRubyObject recv, Block block) {
return runtime.getNil();
}

@JRubyMethod(name = "getgrent", module = true)
public static IRubyObject getgrent(IRubyObject recv) {
@JRubyMethod(module = true)
public static synchronized IRubyObject getgrent(IRubyObject recv) {
Ruby runtime = recv.getRuntime();
try {
Group gr;
@@ -407,40 +414,66 @@ public static IRubyObject getgrent(IRubyObject recv) {
return runtime.getNil();
}
}
@JRubyMethod(name = "systmpdir", module = true, compat = CompatVersion.RUBY1_9)
public static IRubyObject systmpdir(ThreadContext context, IRubyObject recv) {

@JRubyMethod(module = true)
public static synchronized IRubyObject systmpdir(ThreadContext context, IRubyObject recv) {
Ruby runtime = context.getRuntime();
ByteList tmp = ByteList.create(System.getProperty("java.io.tmpdir")); // default for all platforms except Windows

if (Platform.IS_WINDOWS) {
String commonAppData = System.getenv("CSIDL_COMMON_APPDATA");
// TODO: need fallback mechanism
if (commonAppData != null) tmp = ByteList.create(commonAppData);
}
RubyString ret = RubyString.newString(runtime, tmp, runtime.getDefaultExternalEncoding());
ret.untaint(context);
ret.trust(context);


return ret;
}
@JRubyMethod(name = "sysconfdir", module = true, compat = CompatVersion.RUBY1_9)
public static IRubyObject sysconfdir(ThreadContext context, IRubyObject recv) {

@JRubyMethod(module = true)
public static synchronized IRubyObject sysconfdir(ThreadContext context, IRubyObject recv) {
Ruby runtime = context.getRuntime();
ByteList tmp = ByteList.create(RbConfigLibrary.getSysConfDir(runtime)); // default for all platforms except Windows

if (Platform.IS_WINDOWS) {
String localAppData = System.getenv("CSIDL_LOCAL_APPDATA");
// TODO: need fallback mechanism
if (localAppData != null) tmp = ByteList.create(localAppData);
}
RubyString ret = RubyString.newString(runtime, tmp, runtime.getDefaultExternalEncoding());
ret.untaint(context);
ret.trust(context);


return ret;
}


@JRubyMethod(module = true)
public static synchronized IRubyObject nprocessors(ThreadContext context, IRubyObject recv) {
int nprocs = Runtime.getRuntime().availableProcessors();
return RubyFixnum.newFixnum(context.getRuntime(), nprocs);
}

@JRubyMethod(module = true)
public static synchronized IRubyObject uname(ThreadContext context, IRubyObject self) {
Ruby runtime = context.runtime;
RubyHash uname = RubyHash.newHash(runtime);

uname.op_aset(context,
runtime.newSymbol("sysname"),
runtime.newString(SafePropertyAccessor.getProperty("os.name", "unknown")));
try {
uname.op_aset(context,
runtime.newSymbol("nodename"),
runtime.newString(InetAddress.getLocalHost().getHostName()));
} catch (UnknownHostException uhe) {
uname.op_aset(context,
runtime.newSymbol("nodename"),
runtime.newString("unknown"));
}
uname.put(runtime.newSymbol("release"), runtime.newString("unknown"));
uname.put(runtime.newSymbol("version"), runtime.newString(SafePropertyAccessor.getProperty("os.version")));
uname.put(runtime.newSymbol("machine"), runtime.newString(SafePropertyAccessor.getProperty("os.arch")));

return uname;
}

private static final AtomicBoolean iteratingPasswd = new AtomicBoolean(false);
}