diff --git a/WHATSNEW b/WHATSNEW
index da0c8d1f0..00b65fcd3 100644
--- a/WHATSNEW
+++ b/WHATSNEW
@@ -126,6 +126,10 @@ Other changes:
https://issues.apache.org/jira/browse/COMPRESS-314
https://issues.apache.org/jira/browse/COMPRESS-315
+ *
Unix Note: File permissions are not retained when files
-are copied; they end up with the default UMASK
permissions
+are downloaded; they end up with the default UMASK
permissions
instead. This is caused by the lack of any means to query or set file
permissions in the current Java runtimes. If you need a permission-
preserving copy function, use <exec executable="scp" ... >
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/ssh/Scp.java b/src/main/org/apache/tools/ant/taskdefs/optional/ssh/Scp.java
index 7a09f68ac..46e2ac64a 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/ssh/Scp.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/ssh/Scp.java
@@ -52,6 +52,7 @@ public class Scp extends SSHBase {
private List fileSets = null;
private boolean isFromRemote, isToRemote;
private boolean isSftp = false;
+ private Integer fileMode, dirMode;
/**
* Sets the file to be transferred. This can either be a remote
@@ -180,6 +181,22 @@ public class Scp extends SSHBase {
isSftp = yesOrNo;
}
+ /**
+ * Set the file mode, defaults to "644".
+ * @since Ant 1.9.5
+ */
+ public void setFileMode(String fileMode) {
+ this.fileMode = Integer.parseInt(fileMode, 8);
+ }
+
+ /**
+ * Set the dir mode, defaults to "755".
+ * @since Ant 1.9.5
+ */
+ public void setDirMode(String dirMode) {
+ this.dirMode = Integer.parseInt(dirMode, 8);
+ }
+
/**
* Adds a FileSet transfer to remote host. NOTE: Either
* addFileSet() or setFile() are required. But, not both.
@@ -307,6 +324,12 @@ public class Scp extends SSHBase {
list, file);
}
message.setLogListener(this);
+ if (fileMode != null) {
+ message.setFileMode(fileMode.intValue());
+ }
+ if (dirMode != null) {
+ message.setDirMode(dirMode.intValue());
+ }
message.execute();
}
} finally {
@@ -335,6 +358,12 @@ public class Scp extends SSHBase {
file);
}
message.setLogListener(this);
+ if (fileMode != null) {
+ message.setFileMode(fileMode.intValue());
+ }
+ if (dirMode != null) {
+ message.setDirMode(dirMode.intValue());
+ }
message.execute();
} finally {
if (session != null) {
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/ssh/ScpToMessage.java b/src/main/org/apache/tools/ant/taskdefs/optional/ssh/ScpToMessage.java
index 5d4271d25..5ba6b5596 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/ssh/ScpToMessage.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/ssh/ScpToMessage.java
@@ -37,10 +37,13 @@ public class ScpToMessage extends AbstractSshMessage {
private static final int HUNDRED_KILOBYTES = 102400;
private static final int BUFFER_SIZE = 100*1024;
+ private static final int DEFAULT_DIR_MODE = 0755;
+ private static final int DEFAULT_FILE_MODE = 0644;
private File localFile;
private String remotePath;
private List directoryList;
+ private Integer fileMode, dirMode;
/**
* Constructor for ScpToMessage
@@ -137,6 +140,7 @@ public class ScpToMessage extends AbstractSshMessage {
* @throws IOException on i/o errors
* @throws JSchException on errors detected by scp
*/
+ @Override
public void execute() throws IOException, JSchException {
if (directoryList != null) {
doMultipleTransfer();
@@ -201,7 +205,9 @@ public class ScpToMessage extends AbstractSshMessage {
private void sendDirectoryToRemote(final Directory directory,
final InputStream in,
final OutputStream out) throws IOException {
- String command = "D0755 0 ";
+ String command = "D0";
+ command += Integer.toOctalString(getDirMode());
+ command += " 0 ";
command += directory.getDirectory().getName();
command += "\n";
@@ -220,7 +226,9 @@ public class ScpToMessage extends AbstractSshMessage {
final OutputStream out) throws IOException {
// send "C0644 filesize filename", where filename should not include '/'
final long filesize = localFile.length();
- String command = "C0644 " + filesize + " ";
+ String command = "C0";
+ command += Integer.toOctalString(getFileMode());
+ command += " " + filesize + " ";
command += localFile.getName();
command += "\n";
@@ -287,4 +295,37 @@ public class ScpToMessage extends AbstractSshMessage {
public String getRemotePath() {
return remotePath;
}
+
+ /**
+ * Set the file mode, defaults to 0644.
+ * @since Ant 1.9.5
+ */
+ public void setFileMode(int fileMode) {
+ this.fileMode = fileMode;
+ }
+
+ /**
+ * Get the file mode.
+ * @since Ant 1.9.5
+ */
+ public int getFileMode() {
+ return fileMode != null ? fileMode.intValue() : DEFAULT_FILE_MODE;
+ }
+
+ /**
+ * Set the dir mode, defaults to 0755.
+ * @since Ant 1.9.5
+ */
+ public void setDirMode(int dirMode) {
+ this.dirMode = dirMode;
+ }
+
+ /**
+ * Get the dir mode.
+ * @since Ant 1.9.5
+ */
+ public int getDirMode() {
+ return dirMode != null ? dirMode.intValue() : DEFAULT_DIR_MODE;
+ }
+
}
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/ssh/ScpToMessageBySftp.java b/src/main/org/apache/tools/ant/taskdefs/optional/ssh/ScpToMessageBySftp.java
index a3a35fa93..2b32907d7 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/ssh/ScpToMessageBySftp.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/ssh/ScpToMessageBySftp.java
@@ -117,6 +117,7 @@ public class ScpToMessageBySftp extends ScpToMessage/*AbstractSshMessage*/ {
* @throws IOException on i/o errors
* @throws JSchException on errors detected by scp
*/
+ @Override
public void execute() throws IOException, JSchException {
if (directoryList != null) {
doMultipleTransfer();
@@ -159,6 +160,7 @@ public class ScpToMessageBySftp extends ScpToMessage/*AbstractSshMessage*/ {
if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) {
// dir does not exist.
channel.mkdir(remotePath);
+ channel.chmod(getDirMode(), remotePath);
} else {
throw new JSchException("failed to access remote dir '"
+ remotePath + "'", e);
@@ -214,6 +216,7 @@ public class ScpToMessageBySftp extends ScpToMessage/*AbstractSshMessage*/ {
// dir does not exist.
if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) {
channel.mkdir(dir);
+ channel.chmod(getDirMode(), dir);
}
}
channel.cd(dir);
@@ -247,6 +250,7 @@ public class ScpToMessageBySftp extends ScpToMessage/*AbstractSshMessage*/ {
log("Sending: " + localFile.getName() + " : " + filesize);
}
channel.put(localFile.getAbsolutePath(), remotePath, monitor);
+ channel.chmod(getFileMode(), remotePath);
} finally {
if (this.getVerbose()) {
final long endTime = System.currentTimeMillis();