Cannot rename file using apache commons vfs for vsftpd in ubuntu 18.04

Viewed 1376

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.

2 Answers

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!

@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();
    }
}
Related