Search code examples
javaapachesftpapache-commons-vfs

Why Apache VFS (SFTP) tries to switch to root directory even when not needed And how to avoid it


I am using apache VFS for uploading files to sftp server. But one sftp server has a limitation that it's root directory doesn't have any permission. But the directory which is allowed for my application is let's say "/ftp/abc/". This directory is accessible using command line. But Apache VFS first tries to switch to root directory "/" which fails due to lack of permissions in my case.

Edit: Setting userDirIsRoot to true prevents vfs from switching to root directory. But in that case we have to specify path relative to user's root directory. Which means userDirIsRoot is either true or else you can't specify absolute path. This doesn't sound right. Is there a simple way, using which we can specify absolute path, without vfs trying to switch to bare root directory of base filesystem.


Solution

  • The relevant source code is in getChannel() in org.apache.commons.vfs.provider.sftp.SftpFileSystem

    Boolean userDirIsRoot = SftpFileSystemConfigBuilder.getInstance().getUserDirIsRoot(getFileSystemOptions());
    String workingDirectory = getRootName().getPath();
    if (workingDirectory != null && (userDirIsRoot == null || !userDirIsRoot.booleanValue()))
    {
        try
        {
            channel.cd(workingDirectory);
        }
        catch (SftpException e)
        {
            throw new FileSystemException("vfs.provider.sftp/change-work-directory.error", workingDirectory);
        }
    }
    

    The issue in your case is that getUserDirIsRoot(getFileSystemOptions()) evaluates to true.

    Is there anyway to tell Apache VFS library not to switch to root directory?

    In order to not enter in the if statement and not invoke channel.cd(workingDirectory), userDirIsRoot.booleanValue() should evaluate to true.

    According to the documentation, you can set the SftpFileSystem options using SftpFileSystemConfigBuilder.

    Example:

    SftpFileSystemConfigBuilder
    .getInstance()
    .setUserDirIsRoot(options, true);