Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to share file delete privilege when I opening a file by ifstream

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?

like image 412
Min Mun Avatar asked Aug 15 '16 09:08

Min Mun


2 Answers

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.

like image 147
Remy Lebeau Avatar answered Nov 15 '22 07:11

Remy Lebeau


File permissions differ by operating system:

  • Windows has:

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

  • *nix systems provide read, write, and execute permissions, but as far as delete permissions, all that is needed is:

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.

like image 21
Jonathan Mee Avatar answered Nov 15 '22 07:11

Jonathan Mee