C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Add an interface to std::fstream::open to open unnamed file wb+

From: Louis Langholtz <lou_langholtz_at_[hidden]>
Date: Tue, 25 Apr 2023 14:40:47 -0600
On Apr 25, 2023, at 12:35 PM, Thiago Macieira via Std-Proposals <std-proposals_at_[hidden]> wrote:
>
> On Tuesday, 25 April 2023 11:03:48 PDT Louis Langholtz via Std-Proposals
> wrote:
>> For me, opening an fstream with no filename means opening an unnamed file.
>
> An unnamed file is not the same as a randomly-generated name. Linux does
> support creating unnamed files, using the O_TMPFILE option, but they can't be
> created in all filesystems and this also runs afoul of users needing a name in
> their code. So we need to have both functionalities: unnamed files and files
> with randomly-generated names.

My primary goal is providing an fstream opened for an exclusively created file not completely named by the user and that as much as possible goes away automatically - which is like what std::tmpfile provides. https://en.cppreference.com/w/cpp/io/c/tmpfile notes how the implementation of std::tmpfile has the liberty to vary as per the concerns you are raising. This seems like a reasonable lee-way to carry-over to an fstream interface to opening a temporary file like I’m wanting and seems to speak partly to this concern. But std::tmpfile doesn’t have to be used/required.

I realize C++23 std::ios_base::noreplace gives us exclusively opened writable files which provides part of my goal. That by itself doesn’t provide an interface to underlying facilities for creating those exclusively opened writable file that only exists temporarily however.

It occurs to me now that a new open mode - that effectively plumbed O_TMPFILE like support back to the user - could be added as an alternative strategy for supporting what I want. This avoids the “horrible”-ness of adding an open function overload that took no arguments. ;) And it even works in conjunction with noreplace (that does O_EXCL like support).

>
> QTemporaryFile supports both. It will try to create an unnamed file in the
> directory you asked of it and fall back to randomly-generated names otherwise.
> And if you ask it for the name, it'll materialise the file by using the
> linkat() trick.

Thank you for recognizing this prior art. It seems reasonable to consider it as such in regards to this proposal. I’m looking at its documentation <https://doc.qt.io/qt-6/qtemporaryfile.html> for an eye on how it differs functionality wise from std::tmpfile.

Seems a difference is the ability to pick the directory in which to attempt to create the file by way of its templateName parameter. That parameter looks suggestive that it uses mkstemp <https://pubs.opengroup.org/onlinepubs/9699919799/functions/mkdtemp.html> or was patterned from similar functions taking a filename template with six X characters. Having an optional parameter to specify the directory path in which the temporary should be made seems like a useful option in any case. Relatedly, we have std::filesystem::temp_directory_path. It establishes precedence to me for my proposed new interface to make use of it internally certainly (at least a requirement for internal implementation for this proposal) and suggests providing an optional directory path parameter to allow the user to override the temp_directory_path(). I don’t like the idea of a filename template for which having X’s in it is possibly replaced. I do however like that this parameter allows control over the temporary file’s prefix and suffix characters (allowing configurability of before and after components for a file path).

I see there are additional differences like you mention. Having the ability to rename a temporary file to a specified name is very useful IMO. That could be achieved orthogonally however to a std::fstream::open function opening a file exclusively or as a temporary. For instance, std::fstream could support an interface for renaming the underlying handle (like “rename_to”) using calls like linkat(2) with AT_EMPTY_PATH on supporting OS’s or falling back to using rename(2) or the equivalent on systems that don’t have better. I don’t want to encumber a proposal to support opening temporary files though with additional interfaces like this however.

>
> In any case, Jason's concern was about naming this function simply open(). I
> agree with him: that's a horrible API. It sounds like it should open a file
> whose name was previously specified, such as reopening a previously opened file.
> QFile has an open() with no parameters, but that's because it also supports
> passing the file name in the constructor or via setFileName.

Fair enough. Thank you for helping recognize this and providing QFile as context.

I’m liking the additional openmode constant strategy more now anyway. It’s closer to how O_TMPFILE gets plumbed at the Linux open system call level where in that case the filename parameter specifies the directory in which to create the temporary file. That’s appealing to me.

> Instead, this
> should have a better name or that it be added to a class derived from fstream
> specifically for temporary files (like QTemporaryFile is to QFile), or both.

Maybe we name this capability "std::ios_base::tmpfile” instead and as a new openmode constant then. Seems something like that would be preferable to you as well. Or is that worse somehow?

Other opinions? What would be next steps for such a proposal?

Lou

Received on 2023-04-25 20:40:58