5

I want to make the file that can be delete when it was opened by ifstream.

I know it is easy when using Windows API: CreateFile

CreateFile(...,FILE_SHARE_DELETE,...)

But when I test with opening a file by ifstream.

It can't be deleted when I opening it.

I didn't find any document about setting attribute such like FILE_SHARE_DELETE on ifstream.

How should I do to solve this problem?

Exaeta
  • 87
  • 8
Min Mun
  • 81
  • 6
  • 5
    You cannot in a portable way. – πάντα ῥεῖ Aug 15 '16 at 09:03
  • 1
    If I needed that I guess I'd look at ways to open an `ifstream` with an existing C `FILE` handle or file number, which in turn would correspond to an API level handle. Maybe – Cheers and hth. - Alf Aug 15 '16 at 09:06
  • 2
    Some compilers (eg. `GCC`) offer the soon-to-be standard *filesystem* library as a `Technical Specification`. You can use: [std::experimental::filesystem::remove](http://en.cppreference.com/w/cpp/experimental/fs/remove). Otherwise there is the same (or similar) library in `boost`. – Galik Aug 15 '16 at 09:13
  • 2
    @Galik That is unrelated to `FILE_SHARE_DELETE` – David Heffernan Aug 15 '16 at 09:46
  • 1
    For Alf's suggestion, see also http://stackoverflow.com/questions/475853/can-i-use-createfile-but-force-the-handle-into-a-stdofstream – andlabs Aug 15 '16 at 12:21
  • 1
    Finally, I try to use Alf's suggestion and it works fine. Thanks for helping. – Min Mun Aug 15 '16 at 15:32

2 Answers2

5

Visual Studio's version of std::ifstream has a non-standard constructor and a non-standard open() overload that both have an extra optional _Prot parameter for specifying "file protection/sharing flags" (see _fsopen() for the list of available flags). However, delete sharing is not one of supported flags.

There is an alternative, though. Visual Studio's version of both std::ifstream and std::ofstream have non-standard constructors that accept a FILE* for the file access. You can wrap a HANDLE from CreateFile() into a FILE* using Microsoft's _open_osfhandle() and _fdopen() functions, for example (error handling removed for brevity):

Can I use CreateFile, but force the handle into a std::ofstream?

HANDLE file_handle = CreateFile(...,FILE_SHARE_DELETE,...);
int file_descriptor = _open_osfhandle((intptr_t)file_handle, _O_RDONLY);
FILE* file = _fdopen(file_descriptor, "r");
std::ifstream stream(file);
...
// Closes stream, file, file_descriptor, and file_handle.
stream.close();

If you need something more portable to non-Microsoft compilers, you will likely have to resort to writing a custom std::basic_streambuf class (or maybe derived from std::filebuf) to wrap your HANDLE, and then pass an object of that class to the std::basic_istream constructor directly.

Community
  • 1
  • 1
Remy Lebeau
  • 454,445
  • 28
  • 366
  • 620
2

File permissions differ by operating system:

Whole-file access-sharing for read, write, or delete

write+execute permission on the parent directory. The permissions of the file itself are irrelevant

Since Windows is really the only system with delete access, and it already provides it's own accessor in the form of CreateFile with FILE_SHARE_DELETE, there really isn't a motivation to standardize this functionality.

If this functionality is pivotal to your program you could implement this cross-platform function (note that depending upon file size this could be very expensive):

  1. Open file for read and write with an fstream; if this fails something else has a lock on the file and it would not be possible to open it for delete
  2. Slurp the file
  3. close the file
  4. remove the file; if this fails you do not have delete permissions on the file
  5. Reopen the file for writing with an ofstream
  6. "Unslurp" the file into the ofstream
  7. Return the ofstream

As long as the returned ofstream is open the operating system is responsible for preventing changes to the permissions on the file or it's containing directories. So by virtue of the fact that you have already deleted the file you know that you can still delete the file upon closing the ofstream.

Community
  • 1
  • 1
Jonathan Mee
  • 35,107
  • 16
  • 95
  • 241