为什么LockFile()阻止在nas上的远程文件夹的同一线程中写入?

时间:2018-09-27 13:22:49

标签: c++ winapi filesystems nas synology

在Synology NAS的远程文件夹上工作时,我遇到c ++ WinAPI方法LockFile()和WriteFile()的异常行为。 网络设置:

  • Windows 10客户端
  • Synology NAS(RS812)
  • Synology NAS(DS1815 +)

RS812从DS1815 +挂载一个文件夹作为CIFS远程文件夹(请参见https://www.synology.com/en-global/knowledgebase/DSM/help/FileStation/mountremotevolume)。

当我从Windows客户端访问RS812上的该远程文件夹并锁定该文件夹中的文件时,我无法再从同一线程对其进行写入。我非常确定没有其他线程/进程正在访问文件。

有趣的事实:我只能使用WinAPI方法来复制它-尽管使用PowerShell脚本不能复制它。

这是c ++ googletest,在将“ tempPath”设置为该远程文件夹中的文件时可以观察到该问题

TEST( FileLockTest, RemoteFolderTest ) {
    auto tempPath = "\\\\nas\\Data\\RemoteFolder\\subfolder\\example.txt";
    if(boost::filesystem::exists(tempPath)) {
        boost::filesystem::remove(tempPath);
    }
    FileLock::Entity ent = CreateFile(tempPath,
                              GENERIC_ALL,
                              0,
                              NULL,
                              CREATE_NEW,
                              FILE_ATTRIBUTE_NORMAL,
                              NULL );
    ASSERT_EQ(0, GetLastError());

    bool hasLock = LockFile( ent, 0, 0, MAXDWORD, MAXDWORD );
    ASSERT_TRUE(hasLock);
    ASSERT_EQ(0, GetLastError());

    char DataBuffer[] = "some example data";
    DWORD bytesToWrite = (DWORD)strlen(DataBuffer);
    DWORD bytesWritten = 0;

    bool success = WriteFile(
                    ent,
                    DataBuffer,
                    bytesToWrite,
                    &bytesWritten,
                    NULL);

    ASSERT_EQ(0, GetLastError());
    ASSERT_TRUE(success);
}

测试失败,因为在调用WriteFile()之后getLastError()返回代码33(ERROR_LOCK_VIOLATION)。还可以观察到没有任何内容写入文件。 将路径更改为NAS上常规文件夹的路径时,测试不会失败。

这是PowerShell脚本,允许您设置文件锁,然后将其写入该文件夹中。任何暗示为什么该脚本与我的c ++实现行为不同的提示也都欢迎!

    $path = $args[0]
    if([System.IO.File]::Exists($path)) {
      [System.IO.File]::Delete($path)
    }
    $file = [System.IO.File]::Create($path)

    $file.lock(0, [Int64].MaxValue)

    $enc = [system.Text.Encoding]::UTF8
    $text = "Some example text"
    $data = $enc.GetBytes($text) 
    $file.Write($data, 0, $data.length)
    $file.close()

0 个答案:

没有答案