@Override
  public void copyFrom(Directory from, String srcFile, String destFile, IOContext context)
      throws IOException {
    final Directory fromUnwrapped = FilterDirectory.unwrap(from);
    final Directory toUnwrapped = FilterDirectory.unwrap(this);
    // try to unwrap to FSDirectory - we might be able to just create hard-links of these files and
    // save copying
    // the entire file.
    Exception suppressedException = null;
    boolean tryCopy = true;
    if (fromUnwrapped instanceof FSDirectory && toUnwrapped instanceof FSDirectory) {
      final Path fromPath = ((FSDirectory) fromUnwrapped).getDirectory();
      final Path toPath = ((FSDirectory) toUnwrapped).getDirectory();

      if (Files.isReadable(fromPath.resolve(srcFile)) && Files.isWritable(toPath)) {
        // only try hardlinks if we have permission to access the files
        // if not super.copyFrom() will give us the right exceptions
        suppressedException =
            AccessController.doPrivileged(
                (PrivilegedAction<Exception>)
                    () -> {
                      try {
                        Files.createLink(toPath.resolve(destFile), fromPath.resolve(srcFile));
                      } catch (FileNotFoundException
                          | NoSuchFileException
                          | FileAlreadyExistsException ex) {
                        return ex; // in these cases we bubble up since it's a true error condition.
                      } catch (IOException
                          | UnsupportedOperationException // if the FS doesn't support hard-links
                          | SecurityException
                              ex // we don't have permission to use hard-links just fall back to
                                 // byte copy
                      ) {
                        // hard-links are not supported or the files are on different filesystems
                        // we could go deeper and check if their filesstores are the same and opt
                        // out earlier but for now we just fall back to normal file-copy
                        return ex;
                      }
                      return null;
                    });
        tryCopy = suppressedException != null;
      }
    }
    if (tryCopy) {
      try {
        super.copyFrom(from, srcFile, destFile, context);
      } catch (Exception ex) {
        if (suppressedException != null) {
          ex.addSuppressed(suppressedException);
        }
        throw ex;
      }
    }
  }
Beispiel #2
0
 public void createSymLink(Path symLink, Path realFile, boolean force) throws IOException {
   symLink = resolve(symLink);
   if (force) {
     Files.deleteIfExists(symLink);
   }
   if (Platform.detect() == Platform.WINDOWS) {
     if (isDirectory(realFile)) {
       // Creating symlinks to directories on Windows requires escalated privileges. We're just
       // going to have to copy things recursively.
       MoreFiles.copyRecursively(realFile, symLink);
     } else {
       // When sourcePath is relative, resolve it from the targetPath. We're creating a hard link
       // anyway.
       realFile = symLink.getParent().resolve(realFile).normalize();
       Files.createLink(symLink, realFile);
     }
   } else {
     Files.createSymbolicLink(symLink, realFile);
   }
 }
Beispiel #3
0
  public static void copyFile(File source, File destination, boolean hardLinks) {
    if (!source.exists()) {
      return;
    }

    if (hardLinks && !Config.getBooleanProperty("CONTENT_VERSION_HARD_LINK", true)) {
      hardLinks = false;
    }

    if ((destination.getParentFile() != null) && (!destination.getParentFile().exists())) {

      destination.getParentFile().mkdirs();
    }

    if (hardLinks) {
      // I think we need to be sure to unlink first
      if (destination.exists()) {
        Path destinationPath = Paths.get(destination.getAbsolutePath());
        try {
          // "If the file is a symbolic link then the symbolic link itself, not the final target of
          // the link, is deleted."
          Files.delete(destinationPath);
        } catch (IOException e) {
          Logger.error(
              FileUtil.class, "Error removing hardLink: " + destination.getAbsolutePath(), e);
        }
      }

      try {

        Path newLink = Paths.get(destination.getAbsolutePath());
        Path existingFile = Paths.get(source.getAbsolutePath());

        Files.createLink(newLink, existingFile);
        // setting this means we will try again if we cannot hard link
        if (!destination.exists()) {
          hardLinks = false;
        }
      } catch (IOException e) {
        Logger.error(
            FileUtil.class,
            "Can't create hardLink. source: "
                + source.getAbsolutePath()
                + ", destination: "
                + destination.getAbsolutePath());
        // setting this means we will try again if we cannot hard link
        hardLinks = false;
      }
    }
    if (!hardLinks) {

      FileChannel srcChannel = null;
      FileChannel dstChannel = null;

      try {
        srcChannel = new FileInputStream(source).getChannel();
        dstChannel = new FileOutputStream(destination).getChannel();

        dstChannel.transferFrom(srcChannel, 0, srcChannel.size());
      } catch (IOException ioe) {
        Logger.error(FileUtil.class, ioe.getMessage(), ioe);
      } finally {
        try {
          srcChannel.close();
          dstChannel.close();
        } catch (IOException ioe) {
          Logger.error(FileUtil.class, ioe.getMessage(), ioe);
        }
      }
    }
  }