https://bz.apache.org/bugzilla/show_bug.cgi?id=43271 Apparently the remote umask still comes into play and the result won't be exactly what we intended it to be. Based on patch by Holly Cumminsmaster
@@ -126,6 +126,10 @@ Other changes: | |||||
https://issues.apache.org/jira/browse/COMPRESS-314 | https://issues.apache.org/jira/browse/COMPRESS-314 | ||||
https://issues.apache.org/jira/browse/COMPRESS-315 | https://issues.apache.org/jira/browse/COMPRESS-315 | ||||
* <scp> has new attributes fileMode and dirMode that control the | |||||
permissions on the remote side when sending data via SSH. | |||||
Bugzilla Report 43271 | |||||
Changes from Ant 1.9.3 TO Ant 1.9.4 | Changes from Ant 1.9.3 TO Ant 1.9.4 | ||||
=================================== | =================================== | ||||
@@ -182,6 +182,24 @@ for more information. This task has been tested with jsch-0.1.2 and later.</p> | |||||
1.8.0</em></td> | 1.8.0</em></td> | ||||
<td valign="top" align="center">No; defaults to false.</td> | <td valign="top" align="center">No; defaults to false.</td> | ||||
</tr> | </tr> | ||||
<tr> | |||||
<td valign="top">filemode</td> | |||||
<td valign="top">A 3 digit octal string, specify the user, group | |||||
and other modes in the standard Unix fashion. Only applies to | |||||
uploaded files. Note the actual permissions of the remote | |||||
file will be governed by this setting and the UMASK on the | |||||
remote server. Default is 644. <em>since Ant 1.9.5</em>.</td> | |||||
<td align="center" valign="top">No</td> | |||||
</tr> | |||||
<tr> | |||||
<td valign="top">dirmode</td> | |||||
<td valign="top">A 3 digit octal string, specify the user, group | |||||
and other modes in the standard Unix fashion. Only applies to | |||||
uploaded dirs. Note the actual permissions of the remote | |||||
dir will be governed by this setting and the UMASK on the | |||||
remote server. Default is 644. <em>since Ant 1.9.5</em>.</td> | |||||
<td align="center" valign="top">No</td> | |||||
</tr> | |||||
</table> | </table> | ||||
<h3>Parameters specified as nested elements</h3> | <h3>Parameters specified as nested elements</h3> | ||||
@@ -261,7 +279,7 @@ system (via the ps command). The best approach is to use the | |||||
<p> | <p> | ||||
<p><strong>Unix Note:</strong> File permissions are not retained when files | <p><strong>Unix Note:</strong> File permissions are not retained when files | ||||
are copied; they end up with the default <code>UMASK</code> permissions | |||||
are downloaded; they end up with the default <code>UMASK</code> permissions | |||||
instead. This is caused by the lack of any means to query or set file | 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- | permissions in the current Java runtimes. If you need a permission- | ||||
preserving copy function, use <code><exec executable="scp" ... ></code> | preserving copy function, use <code><exec executable="scp" ... ></code> | ||||
@@ -52,6 +52,7 @@ public class Scp extends SSHBase { | |||||
private List fileSets = null; | private List fileSets = null; | ||||
private boolean isFromRemote, isToRemote; | private boolean isFromRemote, isToRemote; | ||||
private boolean isSftp = false; | private boolean isSftp = false; | ||||
private Integer fileMode, dirMode; | |||||
/** | /** | ||||
* Sets the file to be transferred. This can either be a remote | * Sets the file to be transferred. This can either be a remote | ||||
@@ -180,6 +181,22 @@ public class Scp extends SSHBase { | |||||
isSftp = yesOrNo; | 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 | * Adds a FileSet transfer to remote host. NOTE: Either | ||||
* addFileSet() or setFile() are required. But, not both. | * addFileSet() or setFile() are required. But, not both. | ||||
@@ -307,6 +324,12 @@ public class Scp extends SSHBase { | |||||
list, file); | list, file); | ||||
} | } | ||||
message.setLogListener(this); | message.setLogListener(this); | ||||
if (fileMode != null) { | |||||
message.setFileMode(fileMode.intValue()); | |||||
} | |||||
if (dirMode != null) { | |||||
message.setDirMode(dirMode.intValue()); | |||||
} | |||||
message.execute(); | message.execute(); | ||||
} | } | ||||
} finally { | } finally { | ||||
@@ -335,6 +358,12 @@ public class Scp extends SSHBase { | |||||
file); | file); | ||||
} | } | ||||
message.setLogListener(this); | message.setLogListener(this); | ||||
if (fileMode != null) { | |||||
message.setFileMode(fileMode.intValue()); | |||||
} | |||||
if (dirMode != null) { | |||||
message.setDirMode(dirMode.intValue()); | |||||
} | |||||
message.execute(); | message.execute(); | ||||
} finally { | } finally { | ||||
if (session != null) { | if (session != null) { | ||||
@@ -37,10 +37,13 @@ public class ScpToMessage extends AbstractSshMessage { | |||||
private static final int HUNDRED_KILOBYTES = 102400; | private static final int HUNDRED_KILOBYTES = 102400; | ||||
private static final int BUFFER_SIZE = 100*1024; | 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 File localFile; | ||||
private String remotePath; | private String remotePath; | ||||
private List directoryList; | private List directoryList; | ||||
private Integer fileMode, dirMode; | |||||
/** | /** | ||||
* Constructor for ScpToMessage | * Constructor for ScpToMessage | ||||
@@ -137,6 +140,7 @@ public class ScpToMessage extends AbstractSshMessage { | |||||
* @throws IOException on i/o errors | * @throws IOException on i/o errors | ||||
* @throws JSchException on errors detected by scp | * @throws JSchException on errors detected by scp | ||||
*/ | */ | ||||
@Override | |||||
public void execute() throws IOException, JSchException { | public void execute() throws IOException, JSchException { | ||||
if (directoryList != null) { | if (directoryList != null) { | ||||
doMultipleTransfer(); | doMultipleTransfer(); | ||||
@@ -201,7 +205,9 @@ public class ScpToMessage extends AbstractSshMessage { | |||||
private void sendDirectoryToRemote(final Directory directory, | private void sendDirectoryToRemote(final Directory directory, | ||||
final InputStream in, | final InputStream in, | ||||
final OutputStream out) throws IOException { | final OutputStream out) throws IOException { | ||||
String command = "D0755 0 "; | |||||
String command = "D0"; | |||||
command += Integer.toOctalString(getDirMode()); | |||||
command += " 0 "; | |||||
command += directory.getDirectory().getName(); | command += directory.getDirectory().getName(); | ||||
command += "\n"; | command += "\n"; | ||||
@@ -220,7 +226,9 @@ public class ScpToMessage extends AbstractSshMessage { | |||||
final OutputStream out) throws IOException { | final OutputStream out) throws IOException { | ||||
// send "C0644 filesize filename", where filename should not include '/' | // send "C0644 filesize filename", where filename should not include '/' | ||||
final long filesize = localFile.length(); | final long filesize = localFile.length(); | ||||
String command = "C0644 " + filesize + " "; | |||||
String command = "C0"; | |||||
command += Integer.toOctalString(getFileMode()); | |||||
command += " " + filesize + " "; | |||||
command += localFile.getName(); | command += localFile.getName(); | ||||
command += "\n"; | command += "\n"; | ||||
@@ -287,4 +295,37 @@ public class ScpToMessage extends AbstractSshMessage { | |||||
public String getRemotePath() { | public String getRemotePath() { | ||||
return remotePath; | 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; | |||||
} | |||||
} | } |
@@ -117,6 +117,7 @@ public class ScpToMessageBySftp extends ScpToMessage/*AbstractSshMessage*/ { | |||||
* @throws IOException on i/o errors | * @throws IOException on i/o errors | ||||
* @throws JSchException on errors detected by scp | * @throws JSchException on errors detected by scp | ||||
*/ | */ | ||||
@Override | |||||
public void execute() throws IOException, JSchException { | public void execute() throws IOException, JSchException { | ||||
if (directoryList != null) { | if (directoryList != null) { | ||||
doMultipleTransfer(); | doMultipleTransfer(); | ||||
@@ -159,6 +160,7 @@ public class ScpToMessageBySftp extends ScpToMessage/*AbstractSshMessage*/ { | |||||
if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) { | if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) { | ||||
// dir does not exist. | // dir does not exist. | ||||
channel.mkdir(remotePath); | channel.mkdir(remotePath); | ||||
channel.chmod(getDirMode(), remotePath); | |||||
} else { | } else { | ||||
throw new JSchException("failed to access remote dir '" | throw new JSchException("failed to access remote dir '" | ||||
+ remotePath + "'", e); | + remotePath + "'", e); | ||||
@@ -214,6 +216,7 @@ public class ScpToMessageBySftp extends ScpToMessage/*AbstractSshMessage*/ { | |||||
// dir does not exist. | // dir does not exist. | ||||
if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) { | if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) { | ||||
channel.mkdir(dir); | channel.mkdir(dir); | ||||
channel.chmod(getDirMode(), dir); | |||||
} | } | ||||
} | } | ||||
channel.cd(dir); | channel.cd(dir); | ||||
@@ -247,6 +250,7 @@ public class ScpToMessageBySftp extends ScpToMessage/*AbstractSshMessage*/ { | |||||
log("Sending: " + localFile.getName() + " : " + filesize); | log("Sending: " + localFile.getName() + " : " + filesize); | ||||
} | } | ||||
channel.put(localFile.getAbsolutePath(), remotePath, monitor); | channel.put(localFile.getAbsolutePath(), remotePath, monitor); | ||||
channel.chmod(getFileMode(), remotePath); | |||||
} finally { | } finally { | ||||
if (this.getVerbose()) { | if (this.getVerbose()) { | ||||
final long endTime = System.currentTimeMillis(); | final long endTime = System.currentTimeMillis(); | ||||