private String putDirectoryBlob(final String containerName, final Blob blob) throws IOException {
    String blobKey = blob.getMetadata().getName();
    ContentMetadata metadata = blob.getMetadata().getContentMetadata();
    Long contentLength = metadata.getContentLength();
    if (contentLength != null && contentLength != 0) {
      throw new IllegalArgumentException("Directory blob cannot have content: " + blobKey);
    }
    File outputFile = getFileForBlobKey(containerName, blobKey);
    Path outputPath = outputFile.toPath();
    if (!outputFile.isDirectory() && !outputFile.mkdirs()) {
      throw new IOException("Unable to mkdir: " + outputPath);
    }

    UserDefinedFileAttributeView view = getUserDefinedFileAttributeView(outputPath);
    if (view != null) {
      try {
        view.write(XATTR_CONTENT_MD5, ByteBuffer.wrap(DIRECTORY_MD5));
        writeCommonMetadataAttr(view, blob);
      } catch (IOException e) {
        logger.debug("xattrs not supported on %s", outputPath);
      }
    } else {
      logger.warn("xattr not supported on %s", blobKey);
    }

    return base16().lowerCase().encode(DIRECTORY_MD5);
  }
  // "randomize" the file attributes of the given file.
  static void randomizeAttributes(Path file) throws IOException {
    String os = System.getProperty("os.name");
    boolean isWindows = os.startsWith("Windows");
    boolean isUnix = os.equals("SunOS") || os.equals("Linux");
    boolean isDirectory = isDirectory(file, NOFOLLOW_LINKS);

    if (isUnix) {
      Set<PosixFilePermission> perms = getPosixFilePermissions(file, NOFOLLOW_LINKS);
      PosixFilePermission[] toChange = {
        PosixFilePermission.GROUP_READ,
        PosixFilePermission.GROUP_WRITE,
        PosixFilePermission.GROUP_EXECUTE,
        PosixFilePermission.OTHERS_READ,
        PosixFilePermission.OTHERS_WRITE,
        PosixFilePermission.OTHERS_EXECUTE
      };
      for (PosixFilePermission perm : toChange) {
        if (heads()) {
          perms.add(perm);
        } else {
          perms.remove(perm);
        }
      }
      setPosixFilePermissions(file, perms);
    }

    if (isWindows) {
      DosFileAttributeView view =
          getFileAttributeView(file, DosFileAttributeView.class, NOFOLLOW_LINKS);
      // only set or unset the hidden attribute
      view.setHidden(heads());
    }

    boolean addUserDefinedFileAttributes =
        heads() && getFileStore(file).supportsFileAttributeView("xattr");

    // remove this when copying a direcory copies its named streams
    if (isWindows && isDirectory) addUserDefinedFileAttributes = false;

    if (addUserDefinedFileAttributes) {
      UserDefinedFileAttributeView view =
          getFileAttributeView(file, UserDefinedFileAttributeView.class);
      int n = rand.nextInt(16);
      while (n > 0) {
        byte[] value = new byte[1 + rand.nextInt(100)];
        view.write("user." + Integer.toString(n), ByteBuffer.wrap(value));
        n--;
      }
    }
  }
Exemple #3
0
  public static void writeFileKey(Path filePath, String fileKey) {
    if (!OSDetector.isWindows()) {
      return;
    }

    File file = filePath.toFile();

    if (!file.canWrite()) {
      file.setWritable(true);
    }

    UserDefinedFileAttributeView userDefinedFileAttributeView =
        Files.getFileAttributeView(filePath, UserDefinedFileAttributeView.class);

    try {
      userDefinedFileAttributeView.write("fileKey", _CHARSET.encode(CharBuffer.wrap(fileKey)));
    } catch (Exception e) {
      _logger.error(e.getMessage(), e);
    }
  }
 private void writeCommonMetadataAttr(UserDefinedFileAttributeView view, Blob blob)
     throws IOException {
   ContentMetadata metadata = blob.getMetadata().getContentMetadata();
   writeStringAttributeIfPresent(view, XATTR_CACHE_CONTROL, metadata.getCacheControl());
   writeStringAttributeIfPresent(
       view, XATTR_CONTENT_DISPOSITION, metadata.getContentDisposition());
   writeStringAttributeIfPresent(view, XATTR_CONTENT_ENCODING, metadata.getContentEncoding());
   writeStringAttributeIfPresent(view, XATTR_CONTENT_LANGUAGE, metadata.getContentLanguage());
   writeStringAttributeIfPresent(view, XATTR_CONTENT_TYPE, metadata.getContentType());
   Date expires = metadata.getExpires();
   if (expires != null) {
     ByteBuffer buf = ByteBuffer.allocate(Longs.BYTES).putLong(expires.getTime());
     buf.flip();
     view.write(XATTR_EXPIRES, buf);
   }
   for (Map.Entry<String, String> entry : blob.getMetadata().getUserMetadata().entrySet()) {
     writeStringAttributeIfPresent(
         view, XATTR_USER_METADATA_PREFIX + entry.getKey(), entry.getValue());
   }
 }
  protected static void doWriteFileKey(Path filePath, String fileKey) {
    if (hasFileKey(filePath, Long.parseLong(fileKey))) {
      return;
    }

    if (OSDetector.isApple()) {
      Xattrj xattrj = getXattrj();

      if (xattrj == null) {
        return;
      }

      File file = filePath.toFile();

      if (!file.canWrite()) {
        file.setWritable(true);
      }

      xattrj.writeAttribute(file, "fileKey", fileKey);
    } else {
      File file = filePath.toFile();

      if (!file.canWrite()) {
        file.setWritable(true);
      }

      UserDefinedFileAttributeView userDefinedFileAttributeView =
          Files.getFileAttributeView(filePath, UserDefinedFileAttributeView.class);

      try {
        userDefinedFileAttributeView.write("fileKey", _CHARSET.encode(CharBuffer.wrap(fileKey)));
      } catch (Exception e) {
        _logger.error(e.getMessage(), e);
      }
    }
  }
 /** Write an filesystem attribute, if its value is non-null. */
 private static void writeStringAttributeIfPresent(
     UserDefinedFileAttributeView view, String name, String value) throws IOException {
   if (value != null) {
     view.write(name, ByteBuffer.wrap(value.getBytes(StandardCharsets.UTF_8)));
   }
 }
  @Override
  public String putBlob(final String containerName, final Blob blob) throws IOException {
    String blobKey = blob.getMetadata().getName();
    Payload payload = blob.getPayload();
    filesystemContainerNameValidator.validate(containerName);
    filesystemBlobKeyValidator.validate(blobKey);
    if (getDirectoryBlobSuffix(blobKey) != null) {
      return putDirectoryBlob(containerName, blob);
    }
    File outputFile = getFileForBlobKey(containerName, blobKey);
    // TODO: should we use a known suffix to filter these out during list?
    String tmpBlobName = blobKey + "-" + UUID.randomUUID();
    File tmpFile = getFileForBlobKey(containerName, tmpBlobName);
    Path tmpPath = tmpFile.toPath();
    HashingInputStream his = null;
    try {
      Files.createParentDirs(tmpFile);
      his = new HashingInputStream(Hashing.md5(), payload.openStream());
      long actualSize = Files.asByteSink(tmpFile).writeFrom(his);
      Long expectedSize = blob.getMetadata().getContentMetadata().getContentLength();
      if (expectedSize != null && actualSize != expectedSize) {
        throw new IOException(
            "Content-Length mismatch, actual: " + actualSize + " expected: " + expectedSize);
      }
      HashCode actualHashCode = his.hash();
      HashCode expectedHashCode = payload.getContentMetadata().getContentMD5AsHashCode();
      if (expectedHashCode != null && !actualHashCode.equals(expectedHashCode)) {
        throw new IOException(
            "MD5 hash code mismatch, actual: " + actualHashCode + " expected: " + expectedHashCode);
      }
      payload.getContentMetadata().setContentMD5(actualHashCode);

      if (outputFile.exists()) {
        delete(outputFile);
      }

      UserDefinedFileAttributeView view = getUserDefinedFileAttributeView(tmpPath);
      if (view != null) {
        try {
          view.write(XATTR_CONTENT_MD5, ByteBuffer.wrap(actualHashCode.asBytes()));
          writeCommonMetadataAttr(view, blob);
        } catch (IOException e) {
          logger.debug("xattrs not supported on %s", tmpPath);
        }
      }

      setBlobAccess(containerName, tmpBlobName, BlobAccess.PRIVATE);

      if (!tmpFile.renameTo(outputFile)) {
        throw new RuntimeException("Could not rename file " + tmpFile + " to " + outputFile);
      }

      return base16().lowerCase().encode(actualHashCode.asBytes());
    } catch (IOException ex) {
      if (tmpFile != null) {
        try {
          delete(tmpFile);
        } catch (IOException e) {
          logger.debug("Could not delete %s: %s", tmpFile, e);
        }
      }
      throw ex;
    } finally {
      closeQuietly(his);
      if (payload != null) {
        payload.release();
      }
    }
  }