mirror of
https://github.com/jenkinsci/jenkins.git
synced 2026-11-10 02:26:18 +00:00
[JENKINS-9118]
Tar/untar now correctly supports symlinks.
This commit is contained in:
1 parent
48daab0f0b
commit
d184d53b24
6 files changed
+118
-4
No files matched your search
@@ -46,8 +46,9 @@ import hudson.util.IOException2;
|
||||
import hudson.util.HeadBufferingStream;
|
||||
import hudson.util.FormValidation;
|
||||
import hudson.util.IOUtils;
|
||||
|
||||
import static hudson.Util.*;
|
||||
import static hudson.util.jna.GNUCLibrary.LIBC;
|
||||
import static hudson.Util.fixEmpty;
|
||||
import static hudson.FilePath.TarCompression.GZIP;
|
||||
import hudson.org.apache.tools.tar.TarInputStream;
|
||||
import hudson.util.io.Archiver;
|
||||
@@ -75,6 +76,7 @@ import java.io.OutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.io.Writer;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
@@ -331,6 +333,15 @@ public final class FilePath implements Serializable {
|
||||
zip(os,(FileFilter)null);
|
||||
}
|
||||
|
||||
public void zip(FilePath dst) throws IOException, InterruptedException {
|
||||
OutputStream os = dst.write();
|
||||
try {
|
||||
zip(os);
|
||||
} finally {
|
||||
os.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a zip file from this directory by using the specified filter,
|
||||
* and sends the result to the given output stream.
|
||||
@@ -529,6 +540,39 @@ public final class FilePath implements Serializable {
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a symlink to the specified target.
|
||||
*
|
||||
* @param target
|
||||
* The file that the symlink should point to.
|
||||
* @param listener
|
||||
* If symlink creation requires a help of an external process, the error will be reported here.
|
||||
* @since 1.456
|
||||
*/
|
||||
public void symlinkTo(final String target, final TaskListener listener) throws IOException, InterruptedException {
|
||||
act(new FileCallable<Void>() {
|
||||
public Void invoke(File f, VirtualChannel channel) throws IOException, InterruptedException {
|
||||
Util.createSymlink(f.getParentFile(),target,f.getName(),listener);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves symlink, if the given file is a symlink. Otherwise return null.
|
||||
* <p>
|
||||
* If the resolution fails, report an error.
|
||||
*
|
||||
* @since 1.456
|
||||
*/
|
||||
public String readLink() throws IOException, InterruptedException {
|
||||
return act(new FileCallable<String>() {
|
||||
public String invoke(File f, VirtualChannel channel) throws IOException, InterruptedException {
|
||||
return Util.resolveSymlink(f);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
@@ -1756,7 +1800,13 @@ public final class FilePath implements Serializable {
|
||||
File parent = f.getParentFile();
|
||||
if (parent != null) parent.mkdirs();
|
||||
|
||||
IOUtils.copy(t,f);
|
||||
byte linkFlag = (Byte) LINKFLAG_FIELD.get(te);
|
||||
if (linkFlag==TarEntry.LF_SYMLINK) {
|
||||
new FilePath(f).symlinkTo(te.getLinkName(), TaskListener.NULL);
|
||||
} else {
|
||||
IOUtils.copy(t,f);
|
||||
}
|
||||
|
||||
f.setLastModified(te.getModTime().getTime());
|
||||
int mode = te.getMode()&0777;
|
||||
if(mode!=0 && !Functions.isWindows()) // be defensive
|
||||
@@ -1765,6 +1815,11 @@ public final class FilePath implements Serializable {
|
||||
}
|
||||
} catch(IOException e) {
|
||||
throw new IOException2("Failed to extract "+name,e);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt(); // process this later
|
||||
throw new IOException2("Failed to extract "+name,e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new IOException2("Failed to extract "+name,e);
|
||||
} finally {
|
||||
t.close();
|
||||
}
|
||||
@@ -2124,4 +2179,18 @@ public final class FilePath implements Serializable {
|
||||
return o1.length()-o2.length();
|
||||
}
|
||||
};
|
||||
|
||||
private static final Field LINKFLAG_FIELD = getTarEntryLinkFlagField();
|
||||
|
||||
private static Field getTarEntryLinkFlagField() {
|
||||
try {
|
||||
Field f = TarEntry.class.getDeclaredField("linkFlag");
|
||||
f.setAccessible(true);
|
||||
return f;
|
||||
} catch (SecurityException e) {
|
||||
throw new AssertionError(e);
|
||||
} catch (NoSuchFieldException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user