diff --git a/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/Directory.java b/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/Directory.java
index fb8fa52b7df6367e89ecc95bec0d45ab1cd3661b..ea47436d12890d9cf0dde8fdcba57dd6105976ae 100644
--- a/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/Directory.java
+++ b/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/Directory.java
@@ -158,9 +158,9 @@ final class Directory extends AbstractNode implements IDirectory
         assert node != null : "Node can not be null.";
         assert name != null : "Name can not be null.";
         final java.io.File file = getNodeFile(node);
-        final java.io.File fileLink =
-                LinkMakerProvider.getLinkMaker().tryImmutableCopy(file, nodeFile, name);
-        if (fileLink != null)
+        final boolean ok =
+                LinkMakerProvider.getLinkMaker().copyFileImmutably(file, nodeFile, name);
+        if (ok)
         {
             final Link link = (Link) NodeFactory.createLinkNode(name, file);
             link.setParent(this);
@@ -237,6 +237,6 @@ final class Directory extends AbstractNode implements IDirectory
     @Override
     public final boolean isValid()
     {
-        return super.isValid() && FileUtilities.tryCheckDirectoryFullyAccessible(nodeFile, "") == null;
+        return super.isValid() && FileUtilities.checkDirectoryFullyAccessible(nodeFile, "") == null;
     }
 }
diff --git a/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/LinkMakerProvider.java b/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/LinkMakerProvider.java
index 4ce7a2b7bbb79903d7716eb06222f6c89fe48336..40f2f3263f94a91bff7c3b6d46db65069bf6179e 100644
--- a/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/LinkMakerProvider.java
+++ b/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/LinkMakerProvider.java
@@ -18,11 +18,11 @@ package ch.systemsx.cisd.bds.storage.filesystem;
 
 import ch.systemsx.cisd.common.Constants;
 import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException;
-import ch.systemsx.cisd.common.utilities.IPathImmutableCopier;
+import ch.systemsx.cisd.common.utilities.IFileImmutableCopier;
 import ch.systemsx.cisd.common.utilities.RecursiveHardLinkMaker;
 
 /**
- * A provider of {@link IPathImmutableCopier} implementations.
+ * A provider of {@link IFileImmutableCopier} implementations.
  * 
  * @author Christian Ribeaud
  */
@@ -33,16 +33,16 @@ public final class LinkMakerProvider
 
     private static final int MAX_COPY_RETRIES = 7;
 
-    private static IPathImmutableCopier hardLinkMaker;
+    private static IFileImmutableCopier hardLinkMaker;
 
     private LinkMakerProvider()
     {
         // This class can not be instantiated.
     }
 
-    private final static IPathImmutableCopier tryCreateHardLinkMaker()
+    private final static IFileImmutableCopier tryCreateHardLinkMaker()
     {
-        final IPathImmutableCopier copier =
+        final IFileImmutableCopier copier =
                 RecursiveHardLinkMaker.tryCreateRetrying(Constants.MILLIS_TO_WAIT_BEFORE_TIMEOUT,
                         MAX_COPY_RETRIES, Constants.MILLIS_TO_SLEEP_BEFORE_RETRYING);
         if (copier != null)
@@ -58,7 +58,7 @@ public final class LinkMakerProvider
      * Returns an <code>IPathImmutableCopier</code> implementation which makes <i>hard links</i>
      * using the underlying <i>operating system</i>.
      */
-    public final static IPathImmutableCopier getLinkMaker()
+    public final static IFileImmutableCopier getLinkMaker()
     {
         if (hardLinkMaker == null)
         {
diff --git a/common/source/java/ch/systemsx/cisd/common/utilities/FileUtilities.java b/common/source/java/ch/systemsx/cisd/common/utilities/FileUtilities.java
index b3583c537f9caf1409b7b729dd179d78559a373c..708adfee72897580b56ab28230181bb30ec2e377 100644
--- a/common/source/java/ch/systemsx/cisd/common/utilities/FileUtilities.java
+++ b/common/source/java/ch/systemsx/cisd/common/utilities/FileUtilities.java
@@ -378,7 +378,45 @@ public final class FileUtilities
         assert path != null;
         assert kindOfPath != null;
 
-        return checkPathFullyAccessible(path, kindOfPath, "path");
+        return checkPathAccessible(path, kindOfPath, "path", true);
+    }
+
+    /**
+     * Checks whether a <var>path</var> of some <var>kind</var> is accessible for reading to the
+     * program.
+     * 
+     * @param kindOfPath description of given <var>path</var>. Mainly used for error messages.
+     * @return <code>null</code> if the <var>directory</var> is fully accessible and an error
+     *         message describing the problem with the <var>directory</var> otherwise.
+     */
+    public static String checkPathReadAccessible(final File path, final String kindOfPath)
+    {
+        assert path != null;
+        assert kindOfPath != null;
+
+        return checkPathAccessible(path, kindOfPath, "path", false);
+    }
+
+    /**
+     * Checks whether a <var>directory</var> of some <var>kind</var> is accessible for reading to
+     * the program (it's a directory, you can read and write in it)
+     * 
+     * @return <code>null</code> if the <var>directory</var> is accessible for reading and an
+     *         error message describing the problem with the <var>directory</var> otherwise.
+     */
+    public static String checkDirectoryReadAccessible(final File directory,
+            final String kindOfDirectory)
+    {
+        assert directory != null;
+        assert kindOfDirectory != null;
+
+        final String msg = checkPathAccessible(directory, kindOfDirectory, "directory", false);
+        if (msg == null && directory.isDirectory() == false)
+        {
+            return String.format("Path '%s' is supposed to be a %s directory but isn't.",
+                    directory.getPath(), kindOfDirectory);
+        }
+        return msg;
     }
 
     /**
@@ -388,23 +426,65 @@ public final class FileUtilities
      * @return <code>null</code> if the <var>directory</var> is fully accessible and an error
      *         message describing the problem with the <var>directory</var> otherwise.
      */
-    public static String tryCheckDirectoryFullyAccessible(final File directory,
+    public static String checkDirectoryFullyAccessible(final File directory,
             final String kindOfDirectory)
     {
         assert directory != null;
         assert kindOfDirectory != null;
 
-        final String msg = checkPathFullyAccessible(directory, kindOfDirectory, "directory");
+        final String msg = checkPathAccessible(directory, kindOfDirectory, "directory", true);
         if (msg == null && directory.isDirectory() == false)
         {
-            return String.format("Path '%s' is supposed to be a %s directory, but is a file.",
+            return String.format("Path '%s' is supposed to be a %s directory but isn't.",
                     directory.getPath(), kindOfDirectory);
         }
         return msg;
     }
 
-    private static String checkPathFullyAccessible(final File path, final String kindOfPath,
-            final String directoryOrFile)
+    /**
+     * Checks whether a <var>file</var> of some <var>kindOfFile</var> is accessible for reading to
+     * the program (so it's a file and you can read it)
+     * 
+     * @return <code>null</code> if the <var>file</var> is accessible to reading and an error
+     *         message describing the problem with the <var>file</var> otherwise.
+     */
+    public static String checkFileReadAccessible(final File file, final String kindOfFile)
+    {
+        assert file != null;
+        assert kindOfFile != null;
+
+        final String msg = checkPathAccessible(file, kindOfFile, "directory", false);
+        if (msg == null && file.isFile() == false)
+        {
+            return String.format("Path '%s' is supposed to be a %s file but isn't.",
+                    file.getPath(), kindOfFile);
+        }
+        return msg;
+    }
+
+    /**
+     * Checks whether a <var>file</var> of some <var>kindOfFile</var> is accessible for reading
+     * and writing to the program (so it's a file and you can read and write it)
+     * 
+     * @return <code>null</code> if the <var>file</var> is fully accessible and an error message
+     *         describing the problem with the <var>file</var> otherwise.
+     */
+    public static String checkFileFullyAccessible(final File file, final String kindOfFile)
+    {
+        assert file != null;
+        assert kindOfFile != null;
+
+        final String msg = checkPathAccessible(file, kindOfFile, "file", true);
+        if (msg == null && file.isFile() == false)
+        {
+            return String.format("Path '%s' is supposed to be a %s file but isn't.",
+                    file.getPath(), kindOfFile);
+        }
+        return msg;
+    }
+
+    private static String checkPathAccessible(final File path, final String kindOfPath,
+            final String directoryOrFile, boolean readAndWrite)
     {
         assert path != null;
         assert kindOfPath != null;
@@ -422,7 +502,7 @@ public final class FileUtilities
                         .capitalize(kindOfPath), directoryOrFile, path.getPath());
             }
         }
-        if (path.canWrite() == false)
+        if (readAndWrite && path.canWrite() == false)
         {
             return String.format("%s directory '%s' is not writable.", StringUtilities
                     .capitalize(kindOfPath), path.getPath());
diff --git a/common/source/java/ch/systemsx/cisd/common/utilities/IDirectoryImmutableCopier.java b/common/source/java/ch/systemsx/cisd/common/utilities/IDirectoryImmutableCopier.java
new file mode 100644
index 0000000000000000000000000000000000000000..96ce8ccee7b6155c6badb017efd48a6c7f5d1eb7
--- /dev/null
+++ b/common/source/java/ch/systemsx/cisd/common/utilities/IDirectoryImmutableCopier.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2008 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.common.utilities;
+
+import java.io.File;
+
+/**
+ * A role which can perform an immutable copy of a direcoty. <i>Immutable</i> here means, that none
+ * of the copied file must be changed or else the corresponding original file may be changed, tool
+ * 
+ * @author Bernd Rinn
+ */
+public interface IDirectoryImmutableCopier
+{
+    /**
+     * Creates a copy of the directory <code>file</code> (which may be a file or a directory) in
+     * <code>destinationDirectory</code>, which must not be modified later.
+     * <p>
+     * Note that this method don't do any checks about whether paths are directories and whether
+     * they exist or not. Use methods like
+     * {@link FileUtilities#checkDirectoryFullyAccessible(File, String)} for checking prior to
+     * calling this method where appropriate.
+     * </p>
+     * <p>
+     * <i>Can use hard links if available.</i>
+     * </p>
+     * 
+     * @param sourceDirectory The source directory. Really has to be a directory. Can not be
+     *            <code>null</code> and needs to exists.
+     * @param destinationDirectory The directory to copy <var>sourceDirectory</var> to. Can not be
+     *            <code>null</code> and must be an existing directory.
+     * @param targetNameOrNull The target name of the source directory. If <code>null</code>, the
+     *            name of the source directory itself is used.
+     * @return <code>true</code> if the operation was successful, <code>false</code> otherwise.
+     */
+    boolean copyDirectoryImmutably(final File sourceDirectory, final File destinationDirectory,
+            String targetNameOrNull);
+
+}
diff --git a/common/source/java/ch/systemsx/cisd/common/utilities/IFileImmutableCopier.java b/common/source/java/ch/systemsx/cisd/common/utilities/IFileImmutableCopier.java
new file mode 100644
index 0000000000000000000000000000000000000000..6a20d6ca36c040ed9ff97a5fc55a735cf24146e3
--- /dev/null
+++ b/common/source/java/ch/systemsx/cisd/common/utilities/IFileImmutableCopier.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2008 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.common.utilities;
+
+import java.io.File;
+
+/**
+ * A role which can perform an immutable copy of a file. <i>Immutable</i> here means, that the
+ * copied file must not be changed or else the original file may be changed, too.
+ * 
+ * @author Bernd Rinn
+ */
+public interface IFileImmutableCopier
+{
+    /**
+     * Creates a copy of the file <code>file</code> (which may be a file or a directory) in
+     * <code>destinationDirectory</code>, which must not be modified later.
+     * <p>
+     * Note that this method don't do any checks about whether paths are files and whether
+     * they exist or not. Use methods like
+     * {@link FileUtilities#checkPathFullyAccessible(File, String)} for checking prior to
+     * calling this method where appropriate.
+     * </p>
+     * <p>
+     * <i>Can use hard links if available.</i>
+     * </p>
+     * 
+     * @param file The source file. This really has to be a file. Can not be <code>null</code>.
+     * @param destinationDirectory The directory where given <var>path</var> should be copied. Can
+     *            not be <code>null</code> and must be an existing directory.
+     * @param nameOrNull The link name in the destination directory. If it is <code>null</code>,
+     *            the name of <var>file</var> will be used instead.
+     * @return <code>true</code>, if the file was copied successfully, <code>false</code> otherwise.
+     */
+    boolean copyFileImmutably(final File file, final File destinationDirectory,
+            final String nameOrNull);
+}
diff --git a/common/source/java/ch/systemsx/cisd/common/utilities/IPathImmutableCopier.java b/common/source/java/ch/systemsx/cisd/common/utilities/IPathImmutableCopier.java
index 699d15d8231d55c60982004cbc52875ac26d283d..89f881dfa506b78dcee2cd007545900828fd9ddf 100644
--- a/common/source/java/ch/systemsx/cisd/common/utilities/IPathImmutableCopier.java
+++ b/common/source/java/ch/systemsx/cisd/common/utilities/IPathImmutableCopier.java
@@ -16,27 +16,11 @@
 
 package ch.systemsx.cisd.common.utilities;
 
-import java.io.File;
-
 /**
  * Utility to create copies of files/resources, which should not be modified later.
  * 
  * @author Tomasz Pylak
  */
-public interface IPathImmutableCopier
+public interface IPathImmutableCopier extends IFileImmutableCopier, IDirectoryImmutableCopier
 {
-    /**
-     * Creates a copy of <code>path</code> (which may be a file or a directory) in
-     * <code>destinationDirectory</code>, which must not be modified later.
-     * <p>
-     * <i>Can use hard links if available.</i>
-     * </p>
-     * 
-     * @param path the source path. Can be a file or a directory. Can not be <code>null</code>.
-     * @param destinationDirectory the directory where given <var>path</var> should be copied. Can
-     *            not be <code>null</code> and must be an existing directory.
-     * @param nameOrNull the link name in the destination directory.
-     * @return the new path created, or <code>null</code> if the operation fails.
-     */
-    File tryImmutableCopy(final File path, final File destinationDirectory, final String nameOrNull);
 }
diff --git a/common/source/java/ch/systemsx/cisd/common/utilities/PathPrefixPrepender.java b/common/source/java/ch/systemsx/cisd/common/utilities/PathPrefixPrepender.java
index adc20b8116740d65f9afc5111d185bf9a668267a..8a358e59b3156168996e8003f09d9df9c4a326a1 100644
--- a/common/source/java/ch/systemsx/cisd/common/utilities/PathPrefixPrepender.java
+++ b/common/source/java/ch/systemsx/cisd/common/utilities/PathPrefixPrepender.java
@@ -79,7 +79,7 @@ public final class PathPrefixPrepender
         {
             final File file = new File(prefix);
             final String response =
-                    FileUtilities.tryCheckDirectoryFullyAccessible(file, type + " prefix path");
+                    FileUtilities.checkDirectoryFullyAccessible(file, type + " prefix path");
             if (response != null)
             {
                 throw new ConfigurationFailureException(response);
diff --git a/common/source/java/ch/systemsx/cisd/common/utilities/RecursiveHardLinkMaker.java b/common/source/java/ch/systemsx/cisd/common/utilities/RecursiveHardLinkMaker.java
index 411b98372f13e30bd2e92755a48762fb45e5a41a..1144cbdc8fab3380cb6955d2b81907bec824c568 100644
--- a/common/source/java/ch/systemsx/cisd/common/utilities/RecursiveHardLinkMaker.java
+++ b/common/source/java/ch/systemsx/cisd/common/utilities/RecursiveHardLinkMaker.java
@@ -38,10 +38,11 @@ import ch.systemsx.cisd.common.process.ProcessExecutionHelper;
  * 
  * @author Tomasz Pylak
  */
-public final class RecursiveHardLinkMaker implements IPathImmutableCopier
+public final class RecursiveHardLinkMaker implements IPathImmutableCopier,
+        IDirectoryImmutableCopier, IFileImmutableCopier
 {
     private static final String HARD_LINK_EXEC = "ln";
-    
+
     private static final Logger operationLog =
             LogFactory.getLogger(LogCategory.OPERATION, RecursiveHardLinkMaker.class);
 
@@ -101,7 +102,7 @@ public final class RecursiveHardLinkMaker implements IPathImmutableCopier
     //
     // Factory methods
     //
-    
+
     /**
      * Creates copier which won't retry an operation if it fails.
      * 
@@ -112,10 +113,10 @@ public final class RecursiveHardLinkMaker implements IPathImmutableCopier
         return new RecursiveHardLinkMaker(linkExecPath, null);
     }
 
-    /** 
+    /**
      * Creates copier trying to find the path to the <code>ln</code> executable.
      * 
-     * @return <code>null</code> if the <code>ln</code> executable was not found. 
+     * @return <code>null</code> if the <code>ln</code> executable was not found.
      */
     public static final IPathImmutableCopier tryCreate()
     {
@@ -155,10 +156,6 @@ public final class RecursiveHardLinkMaker implements IPathImmutableCopier
         return new RecursiveHardLinkMaker(lnExec.getAbsolutePath(), singleFileLinkTimeoutOrNull);
     }
 
-    //
-    // IPathImmutableCopier
-    //
-    
     /**
      * Copies <var>path</var> (file or directory) to <var>destinationDirectory</var> by
      * duplicating directory structure and creating hard link for each file.
@@ -166,12 +163,12 @@ public final class RecursiveHardLinkMaker implements IPathImmutableCopier
      * <i>Note that <var>nameOrNull</var> cannot already exist in given <var>destinationDirectory</var>.</i>
      * </p>
      */
-    public final File tryImmutableCopy(final File path, final File destinationDirectory,
+    private final File tryImmutableCopy(final File path, final File destinationDirectory,
             final String nameOrNull)
     {
         assert path != null : "Given path can not be null.";
         assert destinationDirectory != null && destinationDirectory.isDirectory() : "Given destination directory can not be null and must be a directory.";
-        final String destName = nameOrNull == null ? path.getName() : nameOrNull;
+        final String destName = (nameOrNull == null) ? path.getName() : nameOrNull;
         final File destFile = new File(destinationDirectory, destName);
         if (destFile.exists())
         {
@@ -188,6 +185,29 @@ public final class RecursiveHardLinkMaker implements IPathImmutableCopier
         return tryMakeCopy(path, destinationDirectory, nameOrNull);
     }
 
+    //
+    // IDirectoryImmutableCopier
+    //
+
+    public boolean copyDirectoryImmutably(File sourceDirectory, File destinationDirectory,
+            String targetNameOrNull)
+    {
+        assert sourceDirectory != null && sourceDirectory.isDirectory();
+        assert destinationDirectory != null && destinationDirectory.isDirectory();
+        return (tryImmutableCopy(sourceDirectory, destinationDirectory, targetNameOrNull) != null);
+    }
+
+    //
+    // IFileImmutableCopier
+    //
+
+    public boolean copyFileImmutably(File file, File destinationDirectory, String nameOrNull)
+    {
+        assert file != null && file.isFile();
+        assert destinationDirectory != null && destinationDirectory.isDirectory();
+        return (tryImmutableCopy(file, destinationDirectory, nameOrNull) != null);
+    }
+
     private final File tryMakeCopy(final File resource, final File destinationDirectory,
             final String nameOrNull)
     {
diff --git a/common/sourceTest/java/ch/systemsx/cisd/common/utilities/FileUtilitiesTest.java b/common/sourceTest/java/ch/systemsx/cisd/common/utilities/FileUtilitiesTest.java
index fc7a020daa9617cf6c92ce875c027afba6f39909..f83938daf24be44db5530700866db9852b5e4662 100644
--- a/common/sourceTest/java/ch/systemsx/cisd/common/utilities/FileUtilitiesTest.java
+++ b/common/sourceTest/java/ch/systemsx/cisd/common/utilities/FileUtilitiesTest.java
@@ -53,7 +53,7 @@ public final class FileUtilitiesTest extends AbstractFileSystemTestCase
     {
         final File nonExistentFile = new File(workingDirectory, "non-existent");
         nonExistentFile.delete();
-        String errorMsg = FileUtilities.tryCheckDirectoryFullyAccessible(nonExistentFile, "test");
+        String errorMsg = FileUtilities.checkDirectoryFullyAccessible(nonExistentFile, "test");
         assertNotNull(errorMsg);
     }
 
@@ -64,7 +64,7 @@ public final class FileUtilitiesTest extends AbstractFileSystemTestCase
         file.delete();
         file.deleteOnExit();
         file.createNewFile();
-        String errorMsg = FileUtilities.tryCheckDirectoryFullyAccessible(file, "test");
+        String errorMsg = FileUtilities.checkDirectoryFullyAccessible(file, "test");
         assertNotNull(errorMsg);
     }
 
@@ -78,7 +78,7 @@ public final class FileUtilitiesTest extends AbstractFileSystemTestCase
         readOnlyDirectory.deleteOnExit();
         assert readOnlyDirectory.setReadOnly();
 
-        String errorMsg = FileUtilities.tryCheckDirectoryFullyAccessible(readOnlyDirectory, "test");
+        String errorMsg = FileUtilities.checkDirectoryFullyAccessible(readOnlyDirectory, "test");
 
         // --- clean before checking results
         // Unfortunately, with JDK 5 there is no portable way to set a file or directory read/write,
diff --git a/common/sourceTest/java/ch/systemsx/cisd/common/utilities/RecursiveHardLinkMakerTest.java b/common/sourceTest/java/ch/systemsx/cisd/common/utilities/RecursiveHardLinkMakerTest.java
index 0aea53f1c30f594de3afaafae3eadb1ce843ed8e..d41290fe7418e8e9d0785722722d3f387701cadb 100644
--- a/common/sourceTest/java/ch/systemsx/cisd/common/utilities/RecursiveHardLinkMakerTest.java
+++ b/common/sourceTest/java/ch/systemsx/cisd/common/utilities/RecursiveHardLinkMakerTest.java
@@ -16,7 +16,7 @@
 
 package ch.systemsx.cisd.common.utilities;
 
-import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.*;
 
 import java.io.File;
 import java.io.IOException;
@@ -143,8 +143,8 @@ public class RecursiveHardLinkMakerTest
     {
         File inputDir = createDirectory(workingDirectory, "resource-to-copy");
         createStructure(inputDir);
-        File newInput = createHardLinkCopier().tryImmutableCopy(inputDir, outputDir, null);
-        assert newInput != null;
+        assertTrue(createHardLinkCopier().copyDirectoryImmutably(inputDir, outputDir, null));
+        File newInput = new File(outputDir, inputDir.getName());
 
         assertStructureExists(newInput);
         boolean deleted = FileUtilities.deleteRecursively(inputDir);
@@ -170,7 +170,8 @@ public class RecursiveHardLinkMakerTest
         File src = createFile(workingDirectory, "fileXXX");
         assertFileExists(src);
 
-        File dest = createHardLinkCopier().tryImmutableCopy(src, outputDir, null);
+        assertTrue(createHardLinkCopier().copyFileImmutably(src, outputDir, null));
+        File dest = new File(outputDir, src.getName());
         assertFileExists(dest);
 
         modifyDest(dest);
diff --git a/datamover/source/java/ch/systemsx/cisd/datamover/LocalProcessor.java b/datamover/source/java/ch/systemsx/cisd/datamover/LocalProcessor.java
index e12f5ef751520fcb4c5069da062109283e6c145c..bc6c9a27a514be2b1e1c79c7aa100580a3b48f7f 100644
--- a/datamover/source/java/ch/systemsx/cisd/datamover/LocalProcessor.java
+++ b/datamover/source/java/ch/systemsx/cisd/datamover/LocalProcessor.java
@@ -31,8 +31,8 @@ import ch.systemsx.cisd.common.logging.Log4jSimpleLogger;
 import ch.systemsx.cisd.common.logging.LogCategory;
 import ch.systemsx.cisd.common.logging.LogFactory;
 import ch.systemsx.cisd.common.utilities.FileUtilities;
+import ch.systemsx.cisd.common.utilities.IDirectoryImmutableCopier;
 import ch.systemsx.cisd.common.utilities.IPathHandler;
-import ch.systemsx.cisd.common.utilities.IPathImmutableCopier;
 import ch.systemsx.cisd.datamover.filesystem.intf.IPathMover;
 import ch.systemsx.cisd.datamover.filesystem.intf.IRecoverableTimerTaskFactory;
 import ch.systemsx.cisd.datamover.utils.LocalBufferDirs;
@@ -56,7 +56,7 @@ public final class LocalProcessor implements IPathHandler, IRecoverableTimerTask
     private static final Logger notificationLog =
             LogFactory.getLogger(LogCategory.NOTIFY, LocalProcessor.class);
 
-    private final IPathImmutableCopier copier;
+    private final IDirectoryImmutableCopier copier;
 
     private final IPathMover mover;
 
@@ -81,7 +81,7 @@ public final class LocalProcessor implements IPathHandler, IRecoverableTimerTask
     private final File manualInterventionDir;
 
     LocalProcessor(final Parameters parameters, final LocalBufferDirs bufferDirs,
-            final IPathImmutableCopier copier, final IPathMover mover)
+            final IDirectoryImmutableCopier copier, final IPathMover mover)
     {
         this.inputDir = bufferDirs.getCopyCompleteDir();
         this.outputDir = bufferDirs.getReadyToMoveDir();
@@ -272,8 +272,8 @@ public final class LocalProcessor implements IPathHandler, IRecoverableTimerTask
                     return;
                 }
             }
-            extraTmpCopy = copier.tryImmutableCopy(path, tempDir, null);
-            if (extraTmpCopy == null)
+            final boolean ok = copier.copyDirectoryImmutably(path, tempDir, null);
+            if (ok == false)
             {
                 notificationLog.error(String.format("Creating extra copy of '%s' failed.", path));
                 return;
diff --git a/datamover/source/java/ch/systemsx/cisd/datamover/filesystem/FileSysOperationsFactory.java b/datamover/source/java/ch/systemsx/cisd/datamover/filesystem/FileSysOperationsFactory.java
index d78427c5a84d03e8632c75df9343cd3db3524131..9f502bb627025d79b0e6ced0ec4475b78d3d02c0 100644
--- a/datamover/source/java/ch/systemsx/cisd/datamover/filesystem/FileSysOperationsFactory.java
+++ b/datamover/source/java/ch/systemsx/cisd/datamover/filesystem/FileSysOperationsFactory.java
@@ -27,7 +27,7 @@ import ch.systemsx.cisd.common.exceptions.Status;
 import ch.systemsx.cisd.common.exceptions.StatusFlag;
 import ch.systemsx.cisd.common.logging.LogCategory;
 import ch.systemsx.cisd.common.logging.LogFactory;
-import ch.systemsx.cisd.common.utilities.IPathImmutableCopier;
+import ch.systemsx.cisd.common.utilities.IDirectoryImmutableCopier;
 import ch.systemsx.cisd.common.utilities.OSUtilities;
 import ch.systemsx.cisd.common.utilities.RecursiveHardLinkMaker;
 import ch.systemsx.cisd.datamover.filesystem.intf.IFileSysOperationsFactory;
@@ -76,27 +76,27 @@ public class FileSysOperationsFactory implements IFileSysOperationsFactory
         return executableFile;
     }
 
-    private final IPathImmutableCopier createFakedImmCopier()
+    private final IDirectoryImmutableCopier createFakedImmCopier()
     {
         final IPathCopier normalCopier = getCopier(false);
-        return new IPathImmutableCopier()
+        return new IDirectoryImmutableCopier()
             {
                 //
-                // IPathImmutableCopier
+                // IDirectoryImmutableCopier
                 //
 
-                public final File tryImmutableCopy(final File file, final File destinationDirectory,
-                        final String nameOrNull)
+                public final boolean copyDirectoryImmutably(final File file,
+                        final File destinationDirectory, String targetNameOrNull)
                 {
                     final Status status = normalCopier.copy(file, destinationDirectory);
                     if (StatusFlag.OK.equals(status.getFlag()))
                     {
-                        return new File(destinationDirectory, file.getName());
+                        return true;
                     } else
                     {
                         notificationLog.error(String.format("Copy of '%s' to '%s' failed: %s.",
                                 file.getPath(), destinationDirectory.getPath(), status));
-                        return null;
+                        return false;
                     }
                 }
             };
@@ -112,7 +112,7 @@ public class FileSysOperationsFactory implements IFileSysOperationsFactory
                 Constants.MILLIS_TO_SLEEP_BEFORE_RETRYING);
     }
 
-    public final IPathImmutableCopier getImmutableCopier()
+    public final IDirectoryImmutableCopier getImmutableCopier()
     {
         final String lnExec = parameters.getHardLinkExecutable();
         if (lnExec != null)
@@ -120,7 +120,7 @@ public class FileSysOperationsFactory implements IFileSysOperationsFactory
             return RecursiveHardLinkMaker.create(lnExec);
         }
 
-        IPathImmutableCopier copier = null;
+        IDirectoryImmutableCopier copier = null;
         if (OSUtilities.isWindows() == false)
         {
             copier = RecursiveHardLinkMaker.tryCreate();
diff --git a/datamover/source/java/ch/systemsx/cisd/datamover/filesystem/RetryingPathMover.java b/datamover/source/java/ch/systemsx/cisd/datamover/filesystem/RetryingPathMover.java
index 5dc21f2c386164a17dde25a4f70ce52f673750da..e01e32afe75d33e38cb6e3a102924000e992f9f2 100644
--- a/datamover/source/java/ch/systemsx/cisd/datamover/filesystem/RetryingPathMover.java
+++ b/datamover/source/java/ch/systemsx/cisd/datamover/filesystem/RetryingPathMover.java
@@ -94,7 +94,7 @@ class RetryingPathMover implements IPathMover
     private boolean checkDirectoryAccesible(final File destinationDirectory)
     {
         String errorMessage =
-                FileUtilities.tryCheckDirectoryFullyAccessible(destinationDirectory, "destination");
+                FileUtilities.checkDirectoryFullyAccessible(destinationDirectory, "destination");
         if (errorMessage != null)
         {
             operationLog.error("Unaccessible directory: " + errorMessage);
diff --git a/datamover/source/java/ch/systemsx/cisd/datamover/filesystem/intf/IFileSysOperationsFactory.java b/datamover/source/java/ch/systemsx/cisd/datamover/filesystem/intf/IFileSysOperationsFactory.java
index e1c7a5e9327908fe87db6f0bc8a668bd5136c0ff..949666bc00cc074765ec2cc5570278cbc70acb34 100644
--- a/datamover/source/java/ch/systemsx/cisd/datamover/filesystem/intf/IFileSysOperationsFactory.java
+++ b/datamover/source/java/ch/systemsx/cisd/datamover/filesystem/intf/IFileSysOperationsFactory.java
@@ -17,7 +17,7 @@ package ch.systemsx.cisd.datamover.filesystem.intf;
 
 import java.io.File;
 
-import ch.systemsx.cisd.common.utilities.IPathImmutableCopier;
+import ch.systemsx.cisd.common.utilities.IDirectoryImmutableCopier;
 
 /**
  * A role that provides access to the roles which perform file system operations.
@@ -28,7 +28,7 @@ public interface IFileSysOperationsFactory
 {
     public IPathCopier getCopier(boolean requiresDeletionBeforeCreation);
 
-    public IPathImmutableCopier getImmutableCopier();
+    public IDirectoryImmutableCopier getImmutableCopier();
 
     public IPathRemover getRemover();
 
diff --git a/datamover/source/java/ch/systemsx/cisd/datamover/filesystem/store/FileStoreLocal.java b/datamover/source/java/ch/systemsx/cisd/datamover/filesystem/store/FileStoreLocal.java
index 3df9ba26decfd3bf3f22d3c5c679736c44475a13..24f78d224b2206b09c695f6c716eda7899834110 100644
--- a/datamover/source/java/ch/systemsx/cisd/datamover/filesystem/store/FileStoreLocal.java
+++ b/datamover/source/java/ch/systemsx/cisd/datamover/filesystem/store/FileStoreLocal.java
@@ -140,7 +140,7 @@ public class FileStoreLocal extends AbstractFileStore implements IExtendedFileSt
         } else
         {
             unaccesibleMsg =
-                    FileUtilities.tryCheckDirectoryFullyAccessible(getPath(), getDescription());
+                    FileUtilities.checkDirectoryFullyAccessible(getPath(), getDescription());
         }
         if (unaccesibleMsg != null)
         {