fengye110 / dokan

Automatically exported from code.google.com/p/dokan
0 stars 0 forks source link

file pointer is reset when reading from eof #145

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
Hello,

We encountered this problem when switching from v0.5.1 to v0.5.2
One of our third party library is trying to read its config file on our
file system. I don't know why but this lib seems to read the file until the
number of bytes read is 0 twice in a row.
You can reproduce this by calling ReadFile(f, buf, 4096, &count) at least 3
times on a small text file.

With Dokan 0.5.1 everything is fine (see attached file dokan_051.png). The
global behavior is the same on a NTFS file system.

With Dokan 0.5.2 the file pointer/offset is set to 0 when reading from the
end of file (see attached file dokan_052.png), or after eof. In our case,
this causes an infinite loop as a side effect.

This is also breaking some of our unit tests, which compare behavior of
Windows API functions on NTFS and our Dokan-based file system.
Here is a simplified (silly) example :
f = CreateFile("M:\\foo", CREATE_ALWAYS);
SetFilePointer(f, 10);
IF_CHECK( ReadFile(f, buf, 4, &count) )  // silly part
{
    CHECK_EQUAL(count, 0);
    IF_CHECK( WriteFile(f, data, 2, &count) )
    {
        CHECK_EQUAL(count, 2);
        CHECK_EQUAL(GetFileSize(f), 10 + 2);
    }
}
This code fails with 0.5.2 because ReadFile reset the file pointer so the
write offset is 0 instead of 10 (and final file size is 2 instead of 12)

This bug was reproduced on WinXP x86 and Win7 x64.
I guess it may have been introduced by revision 105.

Thanks for your hard work.

Original issue reported on code.google.com by Romain.C...@gmail.com on 16 Apr 2010 at 12:07

Attachments:

GoogleCodeExporter commented 9 years ago
About the weird read method, it's in fact due to libc fread(...) behavior, which
calls ReadFile twice Oo. Although the stop condition is not the best (count == 0
instead of count < 4096), it must work.
I made a sample to reproduce the bug (see "TestRead.cpp").

I also wrote a hotfix in "dokan\read.c" (see attachements) to avoid loosing the
current offset. I don't know if it's the best solution, but I didn't want to 
change
"sys\read.c" as we can't sign a driver, which is mandatory for win7 x64.

Regards.

Original comment by Romain.C...@gmail.com on 21 Apr 2010 at 9:37

Attachments:

GoogleCodeExporter commented 9 years ago
I can confirm this.
Reading when the EOF is reached resets the file pointer, while it should just 
stay at 
the EOF.
Will it be fixed soon or should I get back to using v0.5.1?

Original comment by ivail...@gmail.com on 21 Apr 2010 at 9:50

GoogleCodeExporter commented 9 years ago
Thank you for your report. Your fix is right, however let me fix in sys/dokan.c.
Dokan 0.5.2 with your fix is much better than 0.5.1 since there ware BSOD in 
0.5.1.

http://code.google.com/p/dokan/source/detail?r=149

Original comment by asa...@gmail.com on 22 Apr 2010 at 8:41

GoogleCodeExporter commented 9 years ago
I've run into this problem with 0.5.2 also.  In my case, I've installed Firefox 
onto a virtual disk and the installed file structure is binary identical to 
Firefox installed on a normal C: drive.  Firefox starts up from the virtual 
disk but spins and eventually crashes after consuming all available virtual 
memory.  The cause is that Firefox reads a html.css file on startup in a series 
of 4KB chunks and the last partial chunk (less than 4KB but not zero) causes 
the file pointer to reset to zero.  Firefox keeps reading and so re-reads the 
html.css file indefinitely.  I've been able to reproduce the problem using the 
MS Visual Studio stdio fread() with a small program:

int __cdecl _tmain(int argc, _TCHAR* argv[]) {
    char bufr[4096], *path = "e:\\blah.txt"; /* File size is 14,021 bytes. */
    FILE *fp;
    if ( fp = fopen(path, "r") ) {
        int cycle, bytes, position;
        for ( cycle = 1;  cycle < 10;  cycle++ ) {
            position = ftell(fp);
            bytes = fread(bufr, 1, sizeof(bufr), fp);
            printf("Cycle %d read %d bytes from position %d\n",
                    cycle, bytes, position);
        }
    }
}

When run against a virtual disk, this produces output:
Cycle 1 read 4096 bytes from position 0
Cycle 2 read 4096 bytes from position 4174
Cycle 3 read 4096 bytes from position 8343
Cycle 4 read 1479 bytes from position 12515
Cycle 5 read 4096 bytes from position 0
Cycle 6 read 4096 bytes from position 4174
Cycle 7 read 4096 bytes from position 8343
Cycle 8 read 1479 bytes from position 12515
Cycle 9 read 4096 bytes from position 0

When run against a normal C: drive with the same .txt file it produces:
Cycle 1 read 4096 bytes from position 0
Cycle 2 read 4096 bytes from position 4174
Cycle 3 read 4096 bytes from position 8343
Cycle 4 read 1479 bytes from position 12515
Cycle 5 read 0 bytes from position 14021
Cycle 6 read 0 bytes from position 14021
Cycle 7 read 0 bytes from position 14021
Cycle 8 read 0 bytes from position 14021
Cycle 9 read 0 bytes from position 14021

Firefox code is probably looking for a returned read count of zero rather than 
one that's less than the requested number of bytes.

I've been unable to find any way to compensate for this in my virtual file 
system.  Can you recommend anything short of dropping back to 0.5.1?  Is there 
a 0.5.3 on the near-term horizon?

Original comment by k...@kace.com on 22 Jun 2010 at 12:18

GoogleCodeExporter commented 9 years ago
A follow-up on my note above...
I backed down to the Dokan 0.5.1 distribution and the Firefox startup problem 
was cleared.  This is a final confirmation of the cause of that startup from 
virtual disk problem.  Also confirmed that it is the cause of a similar 
infinite read loop problem using svn to checkout project files onto a virtual 
disk.

Original comment by k...@kace.com on 2 Jul 2010 at 4:14

GoogleCodeExporter commented 9 years ago
This is considered as ShowStopper since most application are using the same 
technique to read a stream and stop only when the return read bytes is 0,
do you mean that current official 0.5.2 version of Dokan release contains this 
problem ?
even after the message of asakaw on this thread in date of April 22nd?

Original comment by jyv...@gmail.com on 3 Jul 2010 at 12:45

GoogleCodeExporter commented 9 years ago
Yes, I stops many applications from working. I have reverted to 0.5.1 for now, 
and a new version doesn't seem to be coming any soon, but this is all we can do 
for now (0.5.1 doesn't contain this bug, SVN checks out correctly).

Original comment by ivail...@gmail.com on 4 Jul 2010 at 6:02

GoogleCodeExporter commented 9 years ago
Dokan 0.5.2 has this issue. I will release Dokan 0.5.3 soon.

Original comment by asa...@gmail.com on 5 Jul 2010 at 3:42

GoogleCodeExporter commented 9 years ago
Issue 152 has been merged into this issue.

Original comment by asa...@gmail.com on 5 Jul 2010 at 3:43

GoogleCodeExporter commented 9 years ago
Thank you for posting the 0.5.3 release.  It has clear up my problem with 
running Firefox from a virtual disk.

Original comment by k...@kace.com on 6 Jul 2010 at 8:43

GoogleCodeExporter commented 9 years ago
Thank you k...@kace.com for your comment,
this is always great feedback for all other developers.

Original comment by jyv...@gmail.com on 7 Jul 2010 at 7:44