Boost logo

Boost :

Subject: [boost] [iostreams]mapped_file bug on Win32?
From: Nelson, Erik - 2 (erik.l.nelson_at_[hidden])
Date: 2010-02-19 13:22:32


Or maybe a feature? Or maybe I'm just using it incorrectly.

I'm trying to create a new file of a certain size, regardless of whether
or not a file of the same name exists.

If I run a test program along the lines of

      boost::iostreams::mapped_file file;
      boost::iostreams::mapped_file_params p("test.txt");
      p.new_file_size = 1201;
      p.length = 1;
      p.mode = ios_base::in | ios_base::out;
      file.open(p);

It fails with the error

'failed setting file size: Cannot create a file when that file already
exists.' if file 'test.txt' already exists.

It seems to me that this error is a bug caused by incorrect error
checking in mapped_file.cpp in function mapped_file_impl::open_file.

At the call to CreateFileA, dwCreationDisposition=CREATE_ALWAYS and a
valid handle value is returned. The Win32 docs say that in this case
the call to CreateFileA has succeeded and the last-error code is set to
ERROR_ALREADY_EXISTS.

http://msdn.microsoft.com/en-us/library/aa363858%28VS.85%29.aspx

Immediately after the call to CreateFileA, the handle is checked for
validity but the last-error code is not reset.

Shortly thereafter is a call to SetFilePointer. The docs say that the
proper way to check for an error from SetFilePointer is to compare its
return value to INVALID_SET_VALUE_POINTER.

http://msdn.microsoft.com/en-us/library/aa365541%28VS.85%29.aspx

This isn't done in the code... Instead, GetLastError() is called, which
apparently returns the ERROR_ALREADY_EXISTS code generated by
CreateFileA, which wasn't an error at all.

It seems to me that a couple of things need to be changed to make this
correct-

1) after the check for valid handle creation by CreateFileA, call
SetLastError(NO_ERROR)
2) when resizing the file the code

        if (::GetLastError() != NO_ERROR || !::SetEndOfFile(handle_))

        should be something like

        if (::SetFilePointer(handle_, sizelow, &sizehigh, FILE_BEGIN) ==
INVALID_SET_VALUE_POINTER || !::SetEndOfFile(handle_))

Does that make sense? Or am I just setting the mapped_file_params
incorrectly to force creation of a new file?

Erik


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk