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);