@GuardedBy("lock") Optional<OutputStream> getOutputStream(byte[] checksum, Path to) throws IOException { Path temp = tempFile(TEMP_FILE_RETRY); // Possibly superfluous. Is user likely to delete the temp folder whilst a backup is in progress? if (!DirectoryAssistant.create(tempFolder)) { logger.warn("-- getOutputStream() - failed to create temp folder: {}", tempFolder); return Optional.empty(); } OutputStream os = Files.newOutputStream(temp); DigestOutputStream dos = new DigestOutputStream(digests.get()); TeeOutputStream tos = new TeeOutputStream(os, dos); HookOutputStream<OutputStream> hos = new HookOutputStream<>(tos, callback(checksum, dos, temp, to)); return Optional.of(hos); }
public void engineStore(OutputStream stream, char[] password) throws IOException { Cipher cipher; DataOutputStream dOut = new DataOutputStream(stream); byte[] salt = new byte[STORE_SALT_SIZE]; int iterationCount = MIN_ITERATIONS + (random.nextInt() & 0x3ff); random.nextBytes(salt); dOut.writeInt(version); dOut.writeInt(salt.length); dOut.write(salt); dOut.writeInt(iterationCount); cipher = this.makePBECipher(STORE_CIPHER, Cipher.ENCRYPT_MODE, password, salt, iterationCount); CipherOutputStream cOut = new CipherOutputStream(dOut, cipher); DigestOutputStream dgOut = new DigestOutputStream(new SHA1Digest()); this.saveStore(new TeeOutputStream(cOut, dgOut)); byte[] dig = dgOut.getDigest(); cOut.write(dig); cOut.close(); }
void copy(byte[] checksum, DigestOutputStream dos, OutputStream os, Path temp, Path to) throws IOException { synchronized (lock) { byte[] digest = dos.getDigest(); if (testDigest.test(digest, checksum)) { logger.debug("-- copy() - positive checksum match: {}", Hex.toHexString(digest)); } else { Files.deleteIfExists(temp); throw new IOException("DiskChunkStore copy, bad digest/ corrupt data: " + Hex.toHexString(digest)); } if (Files.exists(to)) { logger.debug("-- copy() - duplicate chunk ignored: {}", to); Files.deleteIfExists(temp); return; } if (!Files.exists(temp)) { throw new IOException("DiskChunkStore copy, temporary file missing: " + temp); } if (!DirectoryAssistant.createParent(to)) { throw new IOException("DiskChunkStore copy, failed to create cache directory: " + to); } try { Files.move(temp, to); } catch (IOException ex) { logger.warn("-- copy() - IOException: {}", ex); throw new IOException("DiskChunkStore copy, failed", ex); } logger.debug("-- copy() - chunk created: {}", to); } }
IOConsumer<OutputStream> callback(byte[] checksum, DigestOutputStream dos, Path temp, Path to) { return os -> copy(checksum, dos, os, temp, to); }