Closed phobeus closed 4 years ago
Hi @phobeus ,
You are right, -1 should be taken as an "APPEND_DATA"! Good catch.I haven't even looked if the C# Mirror is supporting this case 😢
https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-writefile
To write to the end of file, specify both the Offset and OffsetHigh members of the OVERLAPPED structure as 0xFFFFFFFF. This is functionally equivalent to previously calling the CreateFile function to open hFile using FILE_APPEND_DATA access.
FileStream.Position used will be set to -1 and the doc says nothing of what will happen. I might be better to add a check for -1 offset and seek the end of the file ourself. Would you be able to do the test ?
Hey @Liryna ,
We were able to reproduce this inside our software in a unit test. Here's the code for the curious:
public void TestWriteOverlapped() {
var fileName = GetTemporaryFileName();
var handle = Win32Api.CreateFile(fileName,
Win32Api.GENERIC_READ | Win32Api.GENERIC_WRITE,
Win32Api.FILE_SHARE_NONE,
IntPtr.Zero,
Win32Api.CREATE_ALWAYS,
Win32Api.FILE_FLAG_OVERLAPPED,
IntPtr.Zero
);
var writeBuffer = new byte[] { 65, 66, 68 };
var result = WriteFileWithOverlappedAppend(handle, writeBuffer, out var bytesWritten);
Assert.That(bytesWritten, Is.EqualTo(writeBuffer.Length));
Assert.That(result, Is.True);
}
private bool WriteFileWithOverlappedAppend(SafeFileHandle handle, byte[] writeBuffer, out uint bytesWritten)
{
var stateChangeEvent = new ManualResetEvent(false);
var nativeOverlapped = new NativeOverlapped
{
OffsetHigh = -1,
OffsetLow = -1,
EventHandle = stateChangeEvent.SafeWaitHandle.DangerousGetHandle()
};
// See http://www.pinvoke.net/default.aspx/kernel32/GetOverlappedResult.html for more information
var result = Win32Api.WriteFile(handle.DangerousGetHandle(), writeBuffer, (uint)writeBuffer.Length, out bytesWritten, ref nativeOverlapped);
var lastError = Marshal.GetLastWin32Error();
if (!result && (lastError == Win32ErrorCodes.ERROR_IO_PENDING || lastError == Win32ErrorCodes.ERROR_SUCCESS))
{
return Win32Api.GetOverlappedResult(handle.DangerousGetHandle(), ref nativeOverlapped, out bytesWritten, true);
}
bytesWritten = 0;
return false;
}
When running this test on windows, it's fine, but in dokan-dotnet it crashes. I have not had the time to try to fix it yet, just wanted to update for now.
I created a pull request: #262 with the fix. After the fix, I was able to pull git repositories.
@phobeus Thank you very much for reporting, investigating and contributing the fix ! That's very much appreciated it really deserves a 🏆 !
When I'm trying to use "git clone" to clone the repository into a mounted folder, the git command fails at certain positions. At first I thought it had something to do with our driver, but I was able to reproduce this on the master branch on dokan-dotnet, running with stock settings (I mounted the drive to V:) Here's the output of the command:
If I attach a trace logger, it looks like I'm running into a timing issue:
In the trace log, I see the following errors:
In my own application, I'm getting the following error, but I was never able to reproduce this on mirror unfortunately:
Which is weird, from what I've gathered on the dokan side, the offset of -1 should be handled as an "ammend" by fuse? I'm not 100% certain though and I'm also not certain that this is the same issue, we just had similar errors when cloning repositories.
Please let me know if I should attach better logging for this or if this is reproduceable enough. The clone runs through if I use mirror.exe though, so I thought posting this here seems like the right spot.