I need to add a config file to an existing tar file. I am using apache.commons.compress library. The following code snippet adds the entry correctly but overwrites the existing entries of the tar file.
public static void injectFileToTar () throws IOException, ArchiveException {
String agentSourceFilePath = "C:\\Work\\tar.gz\\";
String fileToBeAdded = "activeSensor.cfg";
String unzippedFileName = "sample.tar";
File f2 = new File(agentSourceFilePath+unzippedFileName); // Refers to the .tar file
File f3 = new File(agentSourceFilePath+fileToBeAdded); // The new entry to be added to the .tar file
// Injecting an entry in the tar
OutputStream tarOut = new FileOutputStream(f2);
TarArchiveOutputStream aos = (TarArchiveOutputStream) new ArchiveStreamFactory().createArchiveOutputStream("tar", tarOut);
TarArchiveEntry entry = new TarArchiveEntry(fileToBeAdded);
entry.setMode(0100000);
entry.setSize(f3.length());
aos.putArchiveEntry(entry);
FileInputStream fis = new FileInputStream(f3);
IOUtils.copy(fis, aos);
fis.close();
aos.closeArchiveEntry();
aos.finish();
aos.close();
tarOut.close();
}
On checking the tar, only "activeSensor.cfg" file is found and the initial content of the tar is found missing. Is the "mode" not set correctly ?
The problem is that the TarArchiveOutputStream
does not automatically read in the existing archive, which is something that you'd need to do. Something along the lines of:
CompressorStreamFactory csf = new CompressorStreamFactory();
ArchiveStreamFactory asf = new ArchiveStreamFactory();
String tarFilename = "test.tgz";
String toAddFilename = "activeSensor.cfg";
File toAddFile = new File(toAddFilename);
File tempFile = File.createTempFile("updateTar", "tgz");
File tarFile = new File(tarFilename);
FileInputStream fis = new FileInputStream(tarFile);
CompressorInputStream cis = csf.createCompressorInputStream(CompressorStreamFactory.GZIP, fis);
ArchiveInputStream ais = asf.createArchiveInputStream(ArchiveStreamFactory.TAR, cis);
FileOutputStream fos = new FileOutputStream(tempFile);
CompressorOutputStream cos = csf.createCompressorOutputStream(CompressorStreamFactory.GZIP, fos);
ArchiveOutputStream aos = asf.createArchiveOutputStream(ArchiveStreamFactory.TAR, cos);
// copy the existing entries
ArchiveEntry nextEntry;
while ((nextEntry = ais.getNextEntry()) != null) {
aos.putArchiveEntry(nextEntry);
IOUtils.copy(ais, aos, (int)nextEntry.getSize());
aos.closeArchiveEntry();
}
// create the new entry
TarArchiveEntry entry = new TarArchiveEntry(toAddFilename);
entry.setSize(toAddFile.length());
aos.putArchiveEntry(entry);
IOUtils.copy(new FileInputStream(toAddFile), aos, (int)toAddFile.length());
aos.closeArchiveEntry();
aos.finish();
ais.close();
aos.close();
// copies the new file over the old
tarFile.delete();
tempFile.renameTo(tarFile);
A couple of notes:
try-catch-finally
blocks)Integer.MAX_VALUE
) as it only reads file sizes to integer precision bytes (see the cast to int). However, that's not a problem as Apache Compress does not handle files over 2 GB anyway.Try changing
OutputStream tarOut = new FileOutputStream(f2);
to
OutputStream tarOut = new FileOutputStream(f2, true);
//Set append to true
So I had to unzip the file first to arrive at .tar format. After injecting the required entry in the tar file as per the suggested manner, I had to re-zip it again.
For unzipping and re-zipping, I used java.util.zip.GZIPInputStream and java.util.zip.GZIPOutputStream utilities - Ankit Sharma 2012-04-04 12:38