diff --git a/source/java/ch/systemsx/cisd/base/unix/Unix.java b/source/java/ch/systemsx/cisd/base/unix/Unix.java
index d2d03b4ab02eddfe070a7c6ec5b25f4c7ab38d8a..fc02834a5edcd28fa11d4e99e68b727aa378b317 100644
--- a/source/java/ch/systemsx/cisd/base/unix/Unix.java
+++ b/source/java/ch/systemsx/cisd/base/unix/Unix.java
@@ -458,6 +458,16 @@ public final class Unix
         return processDetection != ProcessDetection.NONE;
     }
 
+    /**
+     * Returns the last error that occurred in this class. Use this to find out what went wrong
+     * after {@link #tryGetLinkInfo(String)} or {@link #tryGetFileInfo(String)} returned
+     * <code>null</code>.
+     */
+    public static String getLastError()
+    {
+        return strerror();
+    }
+
     //
     // Process functions
     //
@@ -572,6 +582,15 @@ public final class Unix
         }
     }
 
+    private static Stat tryGetStat(String fileName) throws IOExceptionUnchecked
+    {
+        if (fileName == null)
+        {
+            throw new NullPointerException("fileName");
+        }
+        return stat(fileName);
+    }
+
     private static Stat getStat(String fileName) throws IOExceptionUnchecked
     {
         if (fileName == null)
@@ -586,6 +605,15 @@ public final class Unix
         return result;
     }
 
+    private static Stat tryGetLStat(String linkName) throws IOExceptionUnchecked
+    {
+        if (linkName == null)
+        {
+            throw new NullPointerException("linkName");
+        }
+        return lstat(linkName);
+    }
+
     private static Stat getLStat(String linkName) throws IOExceptionUnchecked
     {
         if (linkName == null)
@@ -648,25 +676,35 @@ public final class Unix
     }
 
     /**
-     * Returns the information about <var>linkName</var>.
+     * Returns the information about <var>fileName</var>.
      * 
-     * @throws IOExceptionUnchecked If the information could not be obtained, e.g. because the link
+     * @throws IOExceptionUnchecked If the information could not be obtained, e.g. because the file
      *             does not exist.
      */
-    public static final Stat getLinkInfo(String linkName) throws IOExceptionUnchecked
+    public static final Stat getFileInfo(String fileName) throws IOExceptionUnchecked
     {
-        return getLinkInfo(linkName, true);
+        return getStat(fileName);
     }
 
     /**
-     * Returns the information about <var>fileName</var>.
+     * Returns the information about <var>fileName</var>, or {@link NullPointerException}, if the
+     * information could not be obtained, e.g. because the file does not exist (call
+     * {@link #getLastError()} to find out what went wrong).
+     */
+    public static final Stat tryGetFileInfo(String fileName) throws IOExceptionUnchecked
+    {
+        return tryGetStat(fileName);
+    }
+
+    /**
+     * Returns the information about <var>linkName</var>.
      * 
-     * @throws IOExceptionUnchecked If the information could not be obtained, e.g. because the file
+     * @throws IOExceptionUnchecked If the information could not be obtained, e.g. because the link
      *             does not exist.
      */
-    public static final Stat getFileInfo(String fileName) throws IOExceptionUnchecked
+    public static final Stat getLinkInfo(String linkName) throws IOExceptionUnchecked
     {
-        return getStat(fileName);
+        return getLinkInfo(linkName, true);
     }
 
     /**
@@ -682,8 +720,39 @@ public final class Unix
     {
         final Stat stat = getLStat(linkName);
         final String symbolicLinkOrNull =
-                (readSymbolicLinkTarget && stat.isSymbolicLink()) ? readlink(linkName, (int) stat
-                        .getSize()) : null;
+                (readSymbolicLinkTarget && stat.isSymbolicLink()) ? readlink(linkName,
+                        (int) stat.getSize()) : null;
+        stat.setSymbolicLinkOrNull(symbolicLinkOrNull);
+        return stat;
+    }
+
+    /**
+     * Returns the information about <var>linkName</var>, or {@link NullPointerException}, if the
+     * information could not be obtained, e.g. because the link does not exist (call
+     * {@link #getLastError()} to find out what went wrong).
+     */
+    public static final Stat tryGetLinkInfo(String linkName) throws IOExceptionUnchecked
+    {
+        return tryGetLinkInfo(linkName, true);
+    }
+
+    /**
+     * Returns the information about <var>linkName</var>, or <code>null</code> if the information
+     * can not be obtained, e.g. because the link does not exist (call {@link #getLastError()} to
+     * find out what went wrong). If <code>readSymbolicLinkTarget == true</code>, then the symbolic
+     * link target is read when <var>linkName</var> is a symbolic link.
+     */
+    public static final Stat tryGetLinkInfo(String linkName, boolean readSymbolicLinkTarget)
+            throws IOExceptionUnchecked
+    {
+        final Stat stat = tryGetLStat(linkName);
+        if (stat == null)
+        {
+            return null;
+        }
+        final String symbolicLinkOrNull =
+                (readSymbolicLinkTarget && stat.isSymbolicLink()) ? readlink(linkName,
+                        (int) stat.getSize()) : null;
         stat.setSymbolicLinkOrNull(symbolicLinkOrNull);
         return stat;
     }
@@ -708,7 +777,8 @@ public final class Unix
      * Sets the owner of <var>filename</var> to the specified <var>uid</var> and <var>gid</var>
      * values.
      */
-    public static final void setOwner(String fileName, int uid, int gid) throws IOExceptionUnchecked
+    public static final void setOwner(String fileName, int uid, int gid)
+            throws IOExceptionUnchecked
     {
         if (fileName == null)
         {
diff --git a/sourceTest/java/ch/systemsx/cisd/base/unix/UnixTests.java b/sourceTest/java/ch/systemsx/cisd/base/unix/UnixTests.java
index d1a20c5634e499b6f938f93e672d0b59b06052da..33714885700ddbd3b0d778180d22986b7e2f21cc 100644
--- a/sourceTest/java/ch/systemsx/cisd/base/unix/UnixTests.java
+++ b/sourceTest/java/ch/systemsx/cisd/base/unix/UnixTests.java
@@ -104,6 +104,35 @@ public class UnixTests extends AbstractFileSystemTestCase
         assertNull(info2.tryGetSymbolicLink());
     }
 
+    @Test(groups =
+        { "requires_unix" })
+    public void testGetLinkInfoSymLinkDanglingLink() throws IOException
+    {
+        final File s = new File(workingDirectory, "someDanglingLink");
+        Unix.createSymbolicLink("link_to_nowhere", s.getAbsolutePath());
+        final Stat info = Unix.tryGetLinkInfo(s.getAbsolutePath());
+        assertNotNull(info);
+        assertEquals(1, info.getNumberOfHardLinks());
+        assertEquals(FileLinkType.SYMLINK, info.getLinkType());
+        assertTrue(info.isSymbolicLink());
+        final Stat info2 = Unix.tryGetFileInfo(s.getAbsolutePath());
+        assertNull(info2);
+        assertEquals("No such file or directory", Unix.getLastError());
+    }
+
+    @Test(groups =
+        { "requires_unix" })
+    public void testGetLinkInfoNonExistent() throws IOException
+    {
+        final File s = new File(workingDirectory, "nonExistent");
+        final Stat info = Unix.tryGetLinkInfo(s.getAbsolutePath());
+        assertNull(info);
+        assertEquals("No such file or directory", Unix.getLastError());
+        final Stat info2 = Unix.tryGetFileInfo(s.getAbsolutePath());
+        assertNull(info2);
+        assertEquals("No such file or directory", Unix.getLastError());
+    }
+
     @Test(groups =
         { "requires_unix" }, expectedExceptions = NullPointerException.class)
     public void testCreateSymbolicLinkNull() throws IOException
@@ -268,7 +297,7 @@ public class UnixTests extends AbstractFileSystemTestCase
         assertTrue(Unix.canDetectProcesses());
         assertTrue(Unix.isProcessRunningPS(Unix.getPid()));
     }
-    
+
     public static void main(String[] args) throws Throwable
     {
         System.out.println(BuildAndEnvironmentInfo.INSTANCE);