summaryrefslogtreecommitdiffstats
path: root/src/main/java/org/openslx/taskmanager/tasks/RecompressArchive.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/org/openslx/taskmanager/tasks/RecompressArchive.java')
-rw-r--r--src/main/java/org/openslx/taskmanager/tasks/RecompressArchive.java193
1 files changed, 193 insertions, 0 deletions
diff --git a/src/main/java/org/openslx/taskmanager/tasks/RecompressArchive.java b/src/main/java/org/openslx/taskmanager/tasks/RecompressArchive.java
new file mode 100644
index 0000000..d428f03
--- /dev/null
+++ b/src/main/java/org/openslx/taskmanager/tasks/RecompressArchive.java
@@ -0,0 +1,193 @@
+package org.openslx.taskmanager.tasks;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.commons.compress.archivers.ArchiveEntry;
+import org.apache.commons.compress.archivers.ArchiveException;
+import org.apache.commons.compress.archivers.ArchiveInputStream;
+import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
+import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.FilenameUtils;
+import org.openslx.satserver.util.Archive;
+import org.openslx.satserver.util.Util;
+import org.openslx.taskmanager.api.AbstractTask;
+
+import com.google.gson.annotations.Expose;
+
+public class RecompressArchive extends AbstractTask
+{
+
+ @Expose
+ private String[] inputFiles;
+
+ @Expose
+ private String outputFile;
+
+ /*
+ * Own vars/constants not being deserialized
+ */
+
+ protected static final String[] ALLOWED_DIRS =
+ { "/tmp/", "/opt/openslx/configs/" };
+
+ private Output status = new Output();
+
+ /*
+ * Code
+ */
+
+ @Override
+ protected boolean execute()
+ {
+ if ( execute2() ) {
+ return true;
+ }
+ FileUtils.deleteQuietly( new File( this.outputFile ) );
+ return false;
+ }
+
+ private boolean execute2()
+ {
+ // Open output file archive
+ TarArchiveOutputStream outArchive = null;
+ try {
+ try {
+ FileUtils.forceMkdir( new File( new File( this.outputFile ).getParent() ) );
+ outArchive = Archive.createTarArchive( this.outputFile );
+ } catch ( IOException e2 ) {
+ status.error = e2.getMessage();
+ status.errorCode = Output.ErrorCode.WRITE_FAILED;
+ return false;
+ }
+
+ // Open input file archives, one by one
+ for ( final String inputFile : this.inputFiles ) {
+ ArchiveInputStream inArchive = null;
+ try {
+ try {
+ inArchive = Archive.getArchiveInputStream( inputFile );
+ } catch ( FileNotFoundException e1 ) {
+ status.error = "(" + inputFile + ") " + e1.getMessage();
+ status.errorCode = Output.ErrorCode.NOT_FOUND;
+ return false;
+ } catch ( IllegalArgumentException e1 ) {
+ status.error = "(" + inputFile + ") " + e1.getMessage();
+ status.errorCode = Output.ErrorCode.UNKNOWN_ERROR;
+ return false;
+ } catch ( ArchiveException e1 ) {
+ status.error = "(" + inputFile + ") " + e1.getMessage();
+ status.errorCode = Output.ErrorCode.UNKNOWN_FORMAT;
+ return false;
+ }
+ // It's open
+ ArchiveEntry inEntry;
+
+ // Remember all files added, so we can issue warnings for duplicate entries
+ Set<String> entries = new HashSet<>();
+ // Iterate over every entry
+ while ( ( inEntry = inArchive.getNextEntry() ) != null ) {
+ if ( !inArchive.canReadEntryData( inEntry ) )
+ continue; // Skip unreadable entries
+ // Construct TarArchiveEntry - we want unix stuff like uid/gid, links, file/dir mode, so try to get from source archive
+ TarArchiveEntry outEntry = Archive.createTarArchiveEntry( inEntry, 0, 0, 0755, 0644 );
+ // Ask lib if the entry can be written
+ if ( !outArchive.canWriteEntryData( outEntry ) ) {
+ status.warnings.add( "Commons-compress says entry '" + outEntry.getName() + "' cannot be written." );
+ continue;
+ }
+ // Dupcheck
+ if ( entries.contains( outEntry.getName() ) ) {
+ status.warnings.add( "Duplicate entry: " + outEntry.getName() );
+ } else {
+ entries.add( outEntry.getName() );
+ }
+ // Actually add entry now
+ outArchive.putArchiveEntry( outEntry );
+ if ( !Util.streamCopy( inArchive, outArchive, outEntry.getSize() ) ) {
+ status.error = "(" + inputFile + ") Could not copy entry '" + inEntry.getName() + "' to destination archive.";
+ status.errorCode = Output.ErrorCode.WRITE_FAILED;
+ return false;
+ }
+ outArchive.closeArchiveEntry();
+ } // End entry
+ } catch ( IOException e ) {
+ return false;
+ } finally {
+ Util.multiClose( inArchive );
+ }
+ } // End of loop over input archives
+
+ return true;
+ } finally {
+ Util.multiClose( outArchive );
+ }
+ }
+
+ @Override
+ protected boolean initTask()
+ {
+ this.setStatusObject( this.status );
+ // Input files
+ if ( this.inputFiles == null ) {
+ status.error = "Input: No archives given";
+ status.errorCode = Output.ErrorCode.UNKNOWN_ERROR;
+ return false;
+ }
+ for ( int i = 0; i < this.inputFiles.length; ++i ) {
+ String inputFile = this.inputFiles[i];
+ if ( inputFile == null || inputFile.length() == 0 || inputFile.charAt( 0 ) != '/' ) {
+ status.error = "Input: Need absolute path (got: " + inputFile + ")";
+ status.errorCode = Output.ErrorCode.INVALID_DIRECTORY;
+ return false;
+ }
+ inputFile = FilenameUtils.normalize( inputFile );
+ if ( inputFile == null || !Util.startsWith( inputFile, ALLOWED_DIRS ) ) {
+ status.error = "Input: File not in allowed directory";
+ status.errorCode = Output.ErrorCode.INVALID_DIRECTORY;
+ return false;
+ }
+ this.inputFiles[i] = inputFile;
+ }
+ // Output file
+ if ( this.outputFile == null || this.outputFile.length() == 0 || this.outputFile.charAt( 0 ) != '/' ) {
+ status.error = "Output: Need absolute path.";
+ status.errorCode = Output.ErrorCode.INVALID_DIRECTORY;
+ return false;
+ }
+ this.outputFile = FilenameUtils.normalize( this.outputFile );
+ if ( !Util.startsWith( this.outputFile, ALLOWED_DIRS ) ) {
+ status.error = "Output: File not in allowed directory";
+ status.errorCode = Output.ErrorCode.INVALID_DIRECTORY;
+ return false;
+ }
+ return true;
+ }
+
+ @SuppressWarnings( "unused" )
+ private static class Output
+ {
+ protected String error = null;
+
+ protected enum ErrorCode
+ {
+ NOT_FOUND, UNKNOWN_FORMAT, UNKNOWN_ERROR, INVALID_DIRECTORY, WRITE_FAILED
+ };
+
+ protected ErrorCode errorCode = null;
+ protected List<String> warnings = null;
+
+ public static class Entry
+ {
+ protected String name = null;
+ protected boolean isdir = false;
+ protected long size = -1;
+ }
+ }
+
+}