Menu

#2363 std::experimental::filesystem::rename does not overwrite existing file

OTHER
closed
nobody
None
Bug
invalid
Unknown
False
2018-02-23
2018-02-06
Jukka Aro
No

I am using MinGW g++ (7.2.0) for compiling an application for Windows on Linux.

Excerpt from http://en.cppreference.com/w/cpp/experimental/fs/rename :

void rename(const path& old_p, const path& new_p);

  • If old_p is a non-directory file, then new_p must be one of:
    • ...
    • existing non-directory file: new_p is first deleted, then, without allowing other processes to observe new_p as deleted, the pathname new_p is linked to the file and old_p is unlinked from the file. Write permissions are required to both the directory that contains old_p and the directory that contains newp.

When using native g++ (7.2.0) for Linux (ubuntu), std::experimental::filesystem::rename does what is described above. When using mingw-g++ (7.2.0), it does not overwrite (= delete + link) existing file but throws 'filesystem error: cannot rename: File exists'. This seems to conflict with what is stated above in the description of rename.

I have attached a minimal test program and a simple Makefile using both native g++ and mingw-g++ with wine for demonstrating the issue:

 #include <experimental/filesystem>
#include <iostream>

namespace fs = std::experimental::filesystem;

int main(int, char **argv) {
    fs::rename(fs::path(argv[1]), fs::path(argv[2]));
    return 0;
}

This is what I get when running the test program on my 4.10.0-42-generic #46-Ubuntu:

 ja@XXX $ make
 uname -a
Linux XXX 4.10.0-42-generic #46-Ubuntu SMP Mon Dec 4 14:38:01 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
g++ --version
g++ (Ubuntu 7.2.0-18ubuntu2) 7.2.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

ld -v
GNU ld (GNU Binutils for Ubuntu) 2.29.1
touch testfile1 testfile2
g++ -static -static-libgcc -static-libstdc++ fstest.cc -o fstest -lstdc++fs
./fstest testfile1 testfile2
rm -f testfile1 testfile2


uname -a
Linux XXX 4.10.0-42-generic #46-Ubuntu SMP Mon Dec 4 14:38:01 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
i686-w64-mingw32-g++-posix --version
i686-w64-mingw32-g++-posix (GCC) 7.2-posix 20180107
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

ld -v
GNU ld (GNU Binutils for Ubuntu) 2.29.1
touch testfile1 testfile2
i686-w64-mingw32-g++-posix -static -static-libgcc -static-libstdc++ fstest.cc -o fstest_mingw -lstdc++fs
wine ./fstest_mingw testfile1 testfile2
terminate called after throwing an instance of 'std::experimental::filesystem::v1::__cxx11::filesystem_error'
  what():  filesystem error: cannot rename: File exists [testfile1] [testfile2]

abnormal program termination
Makefile:36: recipe for target 'mingw' failed
make: *** [mingw] Error 3
2 Attachments

Discussion

  • Keith Marshall

    Keith Marshall - 2018-02-10

    Thank you for this report.

    First, may I point out that this project (MinGW.org) does not distribute any version of g++ later than g++-6.3.0, so you clearly aren't using a product which have provided, and thus, we should hardly be expected to support it. That said, our own g++-6.3.0 distribution may well be similarly affected, so we may still benefit from follow-up.

    Without detailed investigation, I'm inclined to suggest referring this upstream, to the GCC libstdc++ developers/maintainers. On the (native) MS-Windows platform, the std::experimental::filesystem::rename() method would be expected (ultimately) to map to either a MoveFile() or MoveFileEx() Windows-API call. The former simply cannot support the behaviour you expect; it will always fail, if the new_p file pre-exists. OTOH, the latter API can support the required behaviour, but if, and only if, the MOVEFILE_REPLACE_EXISTING option is specified in the flags argument for the call, (and then only if your process has delete permission for the existing file). Perhaps the upstream g++ implementation doesn't satisfy these requirements; otherwise, the distributor of your g++-7.2.0 may have neglected some essential supporting infrastructure.

     
  • Jukka Aro

    Jukka Aro - 2018-02-12

    Now I realise what I am using is MinGW-w64, not MinGW. I got confused about the two projects with almost similar names and posted my report to the wrong one. Sorry, my bad. Please feel free to close this one in case it is not relevant for you. I will recreate a similar report for the MinGW-w64 project.

     
  • Keith Marshall

    Keith Marshall - 2018-02-23
    • status: unread --> closed
    • Resolution: none --> invalid
     
  • Keith Marshall

    Keith Marshall - 2018-02-23

    GCC's own (upstream) documentation indicates that C++ filesystem support is a) experimental, and b) "rudimentary" (translation: "unlikely to work") on non-POSIX platforms (specifically Windows). Our GCC-6.3.0 distribution doesn't even attempt to support it, so I see no point in pursuing this any further.

     
MongoDB Logo MongoDB