4

I am trying to rename the file in vsftpd server using apache commons vfs, moveTo function is working fine in local system OS (Kubuntu 19.04) and VSFTPD server but when I try to rename the file in a test environment which has ubuntu 18.04 I am not able to rename the file I am getting exception.

With this code:

    public static boolean move(String hostName, String username, String password, String remoteSrcFilePath,
        String remoteDestFilePath, byte [] data) {

    FileObject remoteFile = null;
    FileObject remoteDestFile = null;
    boolean result = false;

    try (StandardFileSystemManager manager = new StandardFileSystemManager()){
        manager.init();

        // Create remote object
        remoteFile = manager.resolveFile(
                createConnectionString(hostName, username, password, remoteSrcFilePath), createDefaultOptions());
        remoteDestFile = manager.resolveFile(
                createConnectionString(hostName, username, password, remoteDestFilePath), createDefaultOptions());

        if (!remoteDestFile.exists() && remoteFile.exists()) {
            remoteFile.moveTo(remoteDestFile);
            if(null != data)
                writeData(remoteDestFile, data);
            result =  true;
        }else {
            throw new DataIntegrityViolationException("Destination path already exists");
        }
    } catch (IOException e) {
        logger.error("Error while renaming/moving file",e);
    }  finally {
        try {
            if(null != remoteDestFile)
                remoteDestFile.close();

            if(null != remoteFile)
                remoteFile.close();

        } catch (FileSystemException e) {
            logger.warn("error while closing fileobject "+e.getMessage());
        }
    }
    return result;
}

    public static FileSystemOptions createDefaultOptions() throws FileSystemException {
    // Create SFTP options
    FileSystemOptions opts = new FileSystemOptions();

    // SSH Key checking
    SftpFileSystemConfigBuilder.getInstance().setStrictHostKeyChecking(opts, "no");

    /*
     * Using the following line will cause VFS to choose File System's Root as VFS's
     * root. If I wanted to use User's home as VFS's root then set 2nd method
     * parameter to "true"
     */
    // Root directory set to user home
    SftpFileSystemConfigBuilder.getInstance().setUserDirIsRoot(opts, true);

    // Timeout is count by Milliseconds
    SftpFileSystemConfigBuilder.getInstance().setConnectTimeoutMillis(opts, 10000);

    return opts;
    }
}

I have this exception

org.apache.commons.vfs2.FileSystemException: Could not determine if file "sftp://ftpuser:***@ip_address/home/ftpuser/ftp/1/Documents/test1/test2" is writeable

Please note the above code is working very well local.

vincenzopalazzo
  • 1,487
  • 2
  • 7
  • 35
pise
  • 849
  • 6
  • 24
  • 51
  • I have an question, because I can not reproducing the your code. The Apache Commons VFSi will check parent directory's permission before remote operation files on SFTP server, you have the permission with the command on the server? – vincenzopalazzo Oct 11 '19 at 08:48
  • @vincenzopalazzo the user has access because the file was created by the same user. – pise Oct 12 '19 at 11:28

2 Answers2

3

If you follow the source code for apache commons vfs for moveTo() you will find:

if (canRenameTo(destFile)) {            //src and dest have the same FS
  if (!getParent().isWriteable()) {     // <-- it could throw the same exception here
    throw new FileSystemException("vfs.provider/rename-parent-read-only.error", getName(),
                    getParent().getName());
  }
} else {
  if (!isWriteable()) {    // <---- it throws inside here (IMO) rather than returning false 
    throw new FileSystemException("vfs.provider/rename-read-only.error", getName());
  }
}

..., you will find that moveTo() will throw the exception that you see, if the destination file is not writeable but in a catastrophic sort of way as in isWriteable(file) throws exception inside its body rather than returning false.

My first call would be to verify that the both the sftpd process and the ftp user can write to the directory where you want your file to be moved to.

HTH!

Community
  • 1
  • 1
diginoise
  • 7,352
  • 2
  • 31
  • 39
  • the file was created by same user, is SSH blocking or Ubuntu blocking in VPS Server to rename as ftpuser can create and delete file – pise Oct 12 '19 at 11:30
  • @pise did you try moving that file via `sftp` from the command line or any other sftp client? – diginoise Oct 14 '19 at 08:20
  • 1
    I tried to rename file with filezilla and it worked. – pise Oct 14 '19 at 12:06
0

@diginoise I tried all the way using apache commons vfs but that didn't work and only for rename I switch to Jsch below is the working code for local as well as remote server

private static ChannelSftp setupJsch(String hostName, String username, String password) throws JSchException  {
    JSch jsch = new JSch();
    JSch.setConfig("StrictHostKeyChecking", "no");
    jsch.setKnownHosts("/home/"+username+"/.ssh/known_hosts");
    Session jschSession = jsch.getSession(username, hostName);
    jschSession.setPassword(password);
    jschSession.connect();
    return (ChannelSftp) jschSession.openChannel("sftp");
}

public static boolean renameFile(String hostName, String username, String password, String remoteSrcFilePath,
        String remoteDestFilePath) {

    boolean result = false;

    ChannelSftp channelSftp = null;
    try {

        channelSftp = setupJsch(hostName,username,password);
        channelSftp.connect();
        channelSftp.rename(remoteSrcFilePath, remoteDestFilePath);
        result = true;
    }catch(JSchException | SftpException  e) {
        logger.error("Error while renaming file sftp ",e);
    }finally {
        sftpCleanUp(channelSftp);
    }

    return result;  
}

private static void sftpCleanUp(ChannelSftp channelSftp) {
    if(null != channelSftp) {
        channelSftp.disconnect();
        channelSftp.exit();
    }
}
pise
  • 849
  • 6
  • 24
  • 51