

jcifs-
ngを利用してandroid端末からSMBサーバーに接続し、SmbFileクラスのlistFilesメソッドの結果を利用しようとすると「SmbException:
The system cannot find the file specified」というエラーが出ました。  
単純化した下記のコードで調べたら、最初のSmbFileインスタンスは正しいものの、listFiles().pathメソッドで得られる子ファイルのフルパスは、各ファイルの直上の親ディレクトリ（最初のSmbFileインスタンスのファイル名）が脱落していました。  
listFiles()で得られるSmbFile型インスタンスも間違ったパスを保持しているものと思われます。  
listFiles()で正しい結果を得る方法がわかりませんでしょうか。  
  

#### MainActivity.kt

[code]

    import android.os.Bundle
    import android.util.Log
    import androidx.appcompat.app.AppCompatActivity
    import jcifs.CIFSContext
    import jcifs.config.PropertyConfiguration
    import jcifs.context.BaseContext
    import jcifs.smb.NtlmPasswordAuthentication
    import jcifs.smb.SmbFile
    import kotlinx.coroutines.*
    import java.util.*
    import kotlin.coroutines.CoroutineContext
    
    
    class MainActivity : AppCompatActivity(), CoroutineScope {
        // 認証情報
        //////////////////////////////////////////////
        // Please replace these values to your data //
        val user = "USER"
        val password = "PASS"
        val domain = "192.168.1.1"
        val smbroot = "smb://" + domain + "/smb/my/tmp"
        //////////////////////////////////////////////
    
        val TAG: String = "MySMB"
    
        // coroutine準備
        private val job = Job()
        override val coroutineContext: CoroutineContext
            get() = Dispatchers.Main + job
    
        // 終了時のcoroutineのキャンセル設定
        override fun onDestroy() {
            job.cancel()
            super.onDestroy()
        }
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            launch {
                withContext(Dispatchers.IO) {
                    val smb = connectSMB(user, password, domain, smbroot)
                    Log.d(TAG, "Got SMB: " + smb.path)
    
    
                    if (smb.isDirectory) {
                        for (eachFile in smb.listFiles()) {
                            Log.d(TAG, "CASE1 " + eachFile.path)
                        }
                    } else {
                        Log.d(TAG, "CASE2 " + smb.path)
                    }
                }
            }
        }
    
        private suspend fun connectSMB(user: String, password: String, domain: String, smbroot: String): SmbFile {
            lateinit var smb: SmbFile
            coroutineScope {
                smb = async(Dispatchers.IO) {
                    val prop = Properties()
                    prop.setProperty("jcifs.smb.client.minVersion", "SMB202")
                    prop.setProperty("jcifs.smb.client.maxVersion", "SMB300")
                    val bc = BaseContext(PropertyConfiguration(prop))
                    val creds = NtlmPasswordAuthentication(bc, domain, user, password)
                    val auth: CIFSContext = bc.withCredentials(creds)
                    SmbFile(smbroot, auth)
                }.await()
            }
            return smb
        }
    }
    
    
[/code]

  

#### Logcat出力

[code]

    2021-08-13 18:33:56.249 18700-18700/PACKAGE.PROJECT.smbclient D/MySMB: Got SMB: smb://192.168.1.1/smb/my/tmp
    2021-08-13 18:33:57.807 18700-18914/PACKAGE.PROJECT.smbclient D/MySMB: CASE1 smb://192.168.1.1/smb/my/file2
    2021-08-13 18:33:57.807 18700-18914/PACKAGE.PROJECT.smbclient D/MySMB: CASE1 smb://192.168.1.1/smb/my/file1
    2021-08-13 18:33:57.808 18700-18914/PACKAGE.PROJECT.smbclient D/MySMB: CASE1 smb://192.168.1.1/smb/my/tmp1/
    2021-08-13 18:33:57.808 18700-18914/PACKAGE.PROJECT.smbclient D/MySMB: CASE1 smb://192.168.1.1/smb/my/tmp2/
    
[/code]

smb/my/tmp/file2がsmb/my/file2と、smb/my/tmp/file1がsmb/my/file1と、smb/my/tmp/tmp1/がsmb/my/tmp1/と、smb/my/tmp/tmp2/がsmb/my/tmp2/と、誤った出力となっている。

  

#### 実際のファイル構成

smb/my/  
└─tmp  
│  
├── file1  
├── file2  
├── tmp1/  
└── tmp2/


CC BY-SA 4.0
2021-08-13T11:08:42.570
80774
2021-08-14T04:42:15.680
2021-08-13T15:32:39.233
32105
32105
question
android samba smb
jcifs-ngのSmbFile#listFiles()で得られるファイルが実際と異なるもの（フルパスから直上の親ディレクトリが失われたもの）となる


以下ページの記述を参考に修正したところ、正しい出力を得られました。

<https://javadoc.io/static/eu.agno3.jcifs/jcifs-
ng/2.0.3/jcifs/smb/SmbFile.html>

> all SMB URLs that represent workgroups, servers, shares, or directories
> require a trailing slash '/'.

**変更前:**

[code]

    val smbroot = "smb://" + domain + "/smb/my/tmp"
    
[/code]

**変更後:**

[code]

    val smbroot = "smb://" + domain + "/smb/my/tmp/"
    
[/code]


CC BY-SA 4.0
2021-08-13T14:34:36.133
80779
2021-08-14T04:42:15.680
2021-08-14T04:42:15.680
3060
32105
80774
answer