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-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 | |||
=================================== | |||
@@ -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> | |||
<td valign="top" align="center">No; defaults to false.</td> | |||
</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> | |||
<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><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 | |||
permissions in the current Java runtimes. If you need a permission- | |||
preserving copy function, use <code><exec executable="scp" ... ></code> | |||
@@ -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) { | |||
@@ -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; | |||
} | |||
} |
@@ -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(); | |||