[3/3] msvcrt: Implement 4k block flushing behavior.

Grazvydas Ignotas notasas at gmail.com
Mon Jun 2 18:16:58 CDT 2014


On Sun, Jun 1, 2014 at 12:38 PM, Piotr Caban <piotr.caban at gmail.com> wrote:
> On 05/31/14 01:00, Grazvydas Ignotas wrote:
>>
>> +        } else if(wrcnt >= MSVCRT_WRITE_BLOCK_SIZE) {
>> +            if(msvcrt_set_write_direction(file) != 0)
>> +                break;
>> +
>> +            if(file->_bufsiz && file->_ptr != file->_base)
>> +                if(msvcrt_flush_buffer(file) == MSVCRT_EOF)
>> +                    break;
>> +
>> +            if(MSVCRT__write(file->_file, ptr, MSVCRT_WRITE_BLOCK_SIZE)
>> <= 0) {
>> +                file->_flag |= MSVCRT__IOERR;
>> +                break;
>> +            }
>> +            written += MSVCRT_WRITE_BLOCK_SIZE;
>> +            wrcnt -= MSVCRT_WRITE_BLOCK_SIZE;
>> +            ptr = (const char*)ptr + MSVCRT_WRITE_BLOCK_SIZE;
>
> This doesn't look right for me. It doesn't make sense to have some special
> size blocks written in different way.
>
> I think this is caused by 2 differences in native and wine's implementation
> of fwrite:
>  - if you check file->_bufsiz value on windows it's set to 4096 (on wine
> it's 512), this is probably causing the flash to be done when 4096 bytes are
> written

I don't think so, as doing 2K fwrites 2 times (for example) doesn't
trigger the flush, only a single write >= 4K does.

>  - probably there's some kind of optimization that writes integral number of
> buffers directly to file

Yes and this is what I'm trying to implement/simulate here..

>  - I was not checking it but maybe native flushes the output when buffer is
> full, wine will exit fwrite with full buffer in this case

As mentioned above, no it does not. Doing it this way would fix IDA,
but I fear it may break something else. IDA does 8K writes at random
offsets of it's database file, then does fileno() and some lseeks,
after that it goes back to using stdio (does fseek() first), but at
that point the flush will go to last lseek it did and corrupt it's
database.

I guess defaulting to 4K buffer and flushing it if it's full on
fwrite() exit would be closer to how msvcrt operates, even though not
entirely correct. Do you prefer this solution, or perhaps something
entirely different?


-- 
Gražvydas



More information about the wine-devel mailing list