2
votes

I am trying to use Jsch Sftp Channel to upload a file to an IBM Mainframe, and the directory has to be "//", where the mainframe will automatically route the file where it needs to go.

In an sftp command session on the IBM mainframe, I can do this:

sftp [email protected]
connecting to 1.2.3.4...
[email protected]'s password:
sftp> pwd
Remote working directory: /users/home/myuser
sftp> cd //
sftp> pwd
Remote working directory: //
sftp> put "#12345.abcdef.xxx.xxx"
uploading #12345.abcdef.xxx.xxx to //#12345.abcdef.xxx.xxx
#12345.abcdef.xxx.xxx               100%  403   0.4KB/s 00:00

So I created a JSch sftp session (version 0.1.5.1) to attempt the same upload, but it does not work:

JSch jsch = new JSch();
Session session = jsch.getSession("myuser", "1.2.3.4");
session.setPassword("mypass");
session.connect();
Channel channel = session.openChannel("sftp");
channel.connect();

ChannelSftp sftp = (ChannelSftp)channel;
log.info(" user home pwd " + sftp.pwd());  //prints /users/home/myuser
sftp.cd("//")
log.info(" pwd after cd " + sftp.pwd()); //only prints /
sftp.put(filename);   //get sftp error, no such file

So I cannot get to that // structure through the JSch library. Is there a certain mode or flag that needs to be set for the sftp session to know it's on a mainframe?

I have no issue at all doing a JSch sftp session to my /users/home/myuser directory, just can't get it to go to the //

2
Doesn't "No such file" mean there is a problem with filename? Anyway, don't you have a bunch of technical support people you can ask? People at your site who've done the same thing? A program spec?Bill Woodger
Unfortunately we don't have a FTP-server running on our z/OS, so I can't play around a bit. Trying a wild guess: have you tried using an "absolute" filename like //#12345.abcdef.xxx.xxx instead of cd-ing to your z/OS filesystem?piet.t
Thanks for the suggestion, @piet.t I've tried as many variations as I can think of, but the sftp session will not recognize that // directoryDio H
Can you copy/paste the exact output of your manual transfer and your attempted programmatic transfer (exact except for sensitive information)? What did your techies say?Bill Woodger
I finally got ahold of the IBM mainframe system people, but could still not find a way to use JSch SftpChannel to get the file where I needed it to be. What I finally decided to do was sftp the file to my home directory, and then create an exec channel to move the file. So a mv command like mv ./SMPL.DATA "//'SMPL.DATA'" is what finally worked in the JSch exec channelDio H

2 Answers

2
votes

I had a similar issue with pseudofolder "//". Avoid this sftp.cd("//") and better try this sftp.put("/-/"+filename); instead, that solved my problem. Hopefully will help you as well.

1
votes

Try it without calling ChannelSftp.cd():

ChannelSftp sftp = (ChannelSftp)channel;
sftp.put("//" + filename);  // Put to //#12345.abcdef.xxx.xxx

The SFTP protocol doesn't actually have a chdir-type operation. At the protocol level, pathnames which don't start with "/" are always interpreted relative to the directory where the SFTP session started. There's no protocol command to change that starting directory.

SFTP clients, including Jsch, emulate chdir-like behavior client-side. When you call ChannelSftp.cd(), Jsch stores the new remote directory locally. When you later call put() or get(), and give a pathname that doesn't start with "/", Jsch prepends the remote directory onto the filename and passes the altered name to the remote server.

I think what's happening to you is that Jsch's chdir emulation is being a little too clever. When you call cd("//"), it's collapsing the "//" into a single "/" and storing that. Then you call put() for a relative pathname, it's prepending the single "/" instead of the double "//" that you want.

Based on inspecting the Jsch source code, it looks like Jsch never alters remote names that start with "/". If you call put("//somefile"), Jsch should use the name you specified as-is.