diff --git a/SystemTools.cxx b/SystemTools.cxx
index d5616d919b2059c59598fc03255cf675858da3ca..1359bc34039362c2bdeb59f9e34dc4117fbb4c33 100644
--- a/SystemTools.cxx
+++ b/SystemTools.cxx
@@ -2356,6 +2356,44 @@ bool SystemTools::FileIsSymlink(const char* name)
 #endif
 }
 
+#if defined(_WIN32) && !defined(__CYGWIN__)
+bool SystemTools::CreateSymlink(const char*, const char*)
+{
+  return false;
+}
+#else
+bool SystemTools::CreateSymlink(const char* origName, const char* newName)
+{
+  return symlink(origName, newName) >= 0;
+}
+#endif
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+bool SystemTools::ReadSymlink(const char*, kwsys_stl::string&)
+{
+  return false;
+}
+#else
+bool SystemTools::ReadSymlink(const char* newName,
+                              kwsys_stl::string& origName)
+{
+  char buf[KWSYS_SYSTEMTOOLS_MAXPATH+1];
+  int count =
+    static_cast<int>(readlink(newName, buf, KWSYS_SYSTEMTOOLS_MAXPATH));
+  if(count >= 0)
+    {
+    // Add null-terminator.
+    buf[count] = 0;
+    origName = buf;
+    return true;
+    }
+  else
+    {
+    return false;
+    }
+}
+#endif
+
 int SystemTools::ChangeDirectory(const char *dir)
 {
   return Chdir(dir);
diff --git a/SystemTools.hxx.in b/SystemTools.hxx.in
index 9c3ea0e90ba5838758f148df967207e224064459..453936474e95617e760096420df3ac01509b77c2 100644
--- a/SystemTools.hxx.in
+++ b/SystemTools.hxx.in
@@ -588,6 +588,18 @@ public:
     unsigned long length = 256, 
     double percent_bin = 0.05);
 
+  /**
+   * Create a symbolic link if the platform supports it.  Returns whether
+   * creation succeded.
+   */
+  static bool CreateSymlink(const char* origName, const char* newName);
+
+  /**
+   * Read the contents of a symbolic link.  Returns whether reading
+   * succeded.
+   */
+  static bool ReadSymlink(const char* newName, kwsys_stl::string& origName);
+
   /**
    * Try to locate the file 'filename' in the directory 'dir'.
    * If 'filename' is a fully qualified filename, the basename of the file is