diff --git a/hadoop-common-project/hadoop-common/CHANGES.txt b/hadoop-common-project/hadoop-common/CHANGES.txt index f43db1987a7..8fa6594e795 100644 --- a/hadoop-common-project/hadoop-common/CHANGES.txt +++ b/hadoop-common-project/hadoop-common/CHANGES.txt @@ -141,6 +141,9 @@ Release 2.5.0 - UNRELEASED HADOOP-10585. Retry polices ignore interrupted exceptions (Daryn Sharp via jeagles) + HADOOP-10401. ShellBasedUnixGroupsMapping#getGroups does not always return + primary group first (Akira AJISAKA via Colin Patrick McCabe) + Release 2.4.1 - UNRELEASED INCOMPATIBLE CHANGES diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/ShellBasedUnixGroupsMapping.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/ShellBasedUnixGroupsMapping.java index 3689ebaa06e..11056eb00f6 100644 --- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/ShellBasedUnixGroupsMapping.java +++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/ShellBasedUnixGroupsMapping.java @@ -74,7 +74,8 @@ public void cacheGroupsAdd(List groups) throws IOException { * Get the current user's group list from Unix by running the command 'groups' * NOTE. For non-existing user it will return EMPTY list * @param user user name - * @return the groups list that the user belongs to + * @return the groups list that the user belongs to. The primary + * group is returned first. * @throws IOException if encounter any error when running the command */ private static List getUnixGroups(final String user) throws IOException { @@ -84,6 +85,7 @@ private static List getUnixGroups(final String user) throws IOException } catch (ExitCodeException e) { // if we didn't get the group - just return empty list; LOG.warn("got exception trying to get groups for user " + user, e); + return new LinkedList(); } StringTokenizer tokenizer = @@ -92,6 +94,17 @@ private static List getUnixGroups(final String user) throws IOException while (tokenizer.hasMoreTokens()) { groups.add(tokenizer.nextToken()); } + + // remove duplicated primary group + if (!Shell.WINDOWS) { + for (int i = 1; i < groups.size(); i++) { + if (groups.get(i).equals(groups.get(0))) { + groups.remove(i); + break; + } + } + } + return groups; } } diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/Shell.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/Shell.java index 61c0e8ddc31..0117fe5f117 100644 --- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/Shell.java +++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/Shell.java @@ -132,11 +132,17 @@ public static String[] getGroupsCommand() { : new String[]{"bash", "-c", "groups"}; } - /** a Unix command to get a given user's groups list */ + /** + * a Unix command to get a given user's groups list. + * If the OS is not WINDOWS, the command will get the user's primary group + * first and finally get the groups list which includes the primary group. + * i.e. the user's primary group will be included twice. + */ public static String[] getGroupsForUserCommand(final String user) { //'groups username' command return is non-consistent across different unixes return (WINDOWS)? new String[] { WINUTILS, "groups", "-F", "\"" + user + "\""} - : new String [] {"bash", "-c", "id -Gn " + user}; + : new String [] {"bash", "-c", "id -gn " + user + + "&& id -Gn " + user}; } /** a Unix command to get a given netgroup's user list */