From afa786098a440c5eb4c106f0e5475b083b85106c Mon Sep 17 00:00:00 2001 From: Suresh Srinivas Date: Thu, 2 May 2013 22:39:56 +0000 Subject: [PATCH] HADOOP-9483. winutils support for readlink command. Contributed by Arpit Agarwal. git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1478592 13f79535-47bb-0310-9956-ffa450edef68 --- .../hadoop-common/CHANGES.txt | 3 + .../src/main/winutils/include/winutils.h | 3 + .../hadoop-common/src/main/winutils/main.c | 8 ++ .../src/main/winutils/winutils.vcxproj | 3 +- .../org/apache/hadoop/util/TestWinUtils.java | 83 +++++++++++++++++++ 5 files changed, 99 insertions(+), 1 deletion(-) diff --git a/hadoop-common-project/hadoop-common/CHANGES.txt b/hadoop-common-project/hadoop-common/CHANGES.txt index 91b0191037..04b862e4e6 100644 --- a/hadoop-common-project/hadoop-common/CHANGES.txt +++ b/hadoop-common-project/hadoop-common/CHANGES.txt @@ -542,6 +542,9 @@ Trunk (Unreleased) HADOOP-9043. Disallow in winutils creating symlinks with forwards slashes. (Chris Nauroth and Arpit Agarwal via suresh) + + HADOOP-9483. winutils support for readlink command. + (Arpit Agarwal via suresh) Release 2.0.5-beta - UNRELEASED diff --git a/hadoop-common-project/hadoop-common/src/main/winutils/include/winutils.h b/hadoop-common-project/hadoop-common/src/main/winutils/include/winutils.h index 86406d0dd5..76859475ed 100644 --- a/hadoop-common-project/hadoop-common/src/main/winutils/include/winutils.h +++ b/hadoop-common-project/hadoop-common/src/main/winutils/include/winutils.h @@ -104,6 +104,9 @@ void TaskUsage(); int Symlink(__in int argc, __in_ecount(argc) wchar_t *argv[]); void SymlinkUsage(); +int Readlink(__in int argc, __in_ecount(argc) wchar_t *argv[]); +void ReadlinkUsage(); + int SystemInfo(); void SystemInfoUsage(); diff --git a/hadoop-common-project/hadoop-common/src/main/winutils/main.c b/hadoop-common-project/hadoop-common/src/main/winutils/main.c index 94c374b407..0f407743ff 100644 --- a/hadoop-common-project/hadoop-common/src/main/winutils/main.c +++ b/hadoop-common-project/hadoop-common/src/main/winutils/main.c @@ -55,6 +55,10 @@ int wmain(__in int argc, __in_ecount(argc) wchar_t* argv[]) { return Symlink(argc - 1, argv + 1); } + else if (wcscmp(L"readlink", cmd) == 0) + { + return Readlink(argc - 1, argv + 1); + } else if (wcscmp(L"task", cmd) == 0) { return Task(argc - 1, argv + 1); @@ -105,6 +109,10 @@ The available commands and their usages are:\n\n", program); SymlinkUsage(); fwprintf(stdout, L"\n\n"); + fwprintf(stdout, L"%-10s%s\n\n", L"readlink", L"Print the target of a symbolic link."); + ReadlinkUsage(); + fwprintf(stdout, L"\n\n"); + fwprintf(stdout, L"%-15s%s\n\n", L"systeminfo", L"System information."); SystemInfoUsage(); fwprintf(stdout, L"\n\n"); diff --git a/hadoop-common-project/hadoop-common/src/main/winutils/winutils.vcxproj b/hadoop-common-project/hadoop-common/src/main/winutils/winutils.vcxproj index 9ae4c8745e..5b9a195aea 100644 --- a/hadoop-common-project/hadoop-common/src/main/winutils/winutils.vcxproj +++ b/hadoop-common-project/hadoop-common/src/main/winutils/winutils.vcxproj @@ -160,6 +160,7 @@ + @@ -178,4 +179,4 @@ - + \ No newline at end of file diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/util/TestWinUtils.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/util/TestWinUtils.java index 3a0f8b00f2..cae3406364 100644 --- a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/util/TestWinUtils.java +++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/util/TestWinUtils.java @@ -33,6 +33,8 @@ import org.apache.hadoop.fs.FileUtil; import org.junit.After; import org.junit.Before; import org.junit.Test; +import static org.junit.Assume.*; +import static org.hamcrest.CoreMatchers.*; /** * Test cases for helper Windows winutils.exe utility. @@ -359,4 +361,85 @@ public class TestWinUtils { "Expected: Failed to create symlink with forward slashes in target"); } } + + @Test (timeout = 30000) + public void testReadLink() throws IOException { + // Create TEST_DIR\dir1\file1.txt + // + File dir1 = new File(TEST_DIR, "dir1"); + assertTrue(dir1.mkdirs()); + + File file1 = new File(dir1, "file1.txt"); + assertTrue(file1.createNewFile()); + + File dirLink = new File(TEST_DIR, "dlink"); + File fileLink = new File(TEST_DIR, "flink"); + + // Next create a directory symlink to dir1 and a file + // symlink to file1.txt. + // + Shell.execCommand( + Shell.WINUTILS, "symlink", dirLink.toString(), dir1.toString()); + Shell.execCommand( + Shell.WINUTILS, "symlink", fileLink.toString(), file1.toString()); + + // Read back the two links and ensure we get what we expected. + // + String readLinkOutput = Shell.execCommand(Shell.WINUTILS, + "readlink", + dirLink.toString()); + assertThat(readLinkOutput, equalTo(dir1.toString())); + + readLinkOutput = Shell.execCommand(Shell.WINUTILS, + "readlink", + fileLink.toString()); + assertThat(readLinkOutput, equalTo(file1.toString())); + + // Try a few invalid inputs and verify we get an ExitCodeException for each. + // + try { + // No link name specified. + // + Shell.execCommand(Shell.WINUTILS, "readlink", ""); + fail("Failed to get Shell.ExitCodeException when reading bad symlink"); + } catch (Shell.ExitCodeException ece) { + assertThat(ece.getExitCode(), is(1)); + } + + try { + // Bad link name. + // + Shell.execCommand(Shell.WINUTILS, "readlink", "ThereIsNoSuchLink"); + fail("Failed to get Shell.ExitCodeException when reading bad symlink"); + } catch (Shell.ExitCodeException ece) { + assertThat(ece.getExitCode(), is(1)); + } + + try { + // Non-symlink directory target. + // + Shell.execCommand(Shell.WINUTILS, "readlink", dir1.toString()); + fail("Failed to get Shell.ExitCodeException when reading bad symlink"); + } catch (Shell.ExitCodeException ece) { + assertThat(ece.getExitCode(), is(1)); + } + + try { + // Non-symlink file target. + // + Shell.execCommand(Shell.WINUTILS, "readlink", file1.toString()); + fail("Failed to get Shell.ExitCodeException when reading bad symlink"); + } catch (Shell.ExitCodeException ece) { + assertThat(ece.getExitCode(), is(1)); + } + + try { + // Too many parameters. + // + Shell.execCommand(Shell.WINUTILS, "readlink", "a", "b"); + fail("Failed to get Shell.ExitCodeException with bad parameters"); + } catch (Shell.ExitCodeException ece) { + assertThat(ece.getExitCode(), is(1)); + } + } }