[PATCH] misc: Add mkostempat (BZ 19866)

Mark Wielaard mark@klomp.org
Tue Jun 23 17:01:44 GMT 2026


Hi,

On Mon, 2026-06-22 at 17:03 -0300, Adhemerval Zanella Netto wrote:
> On 22/06/26 16:55, Paul Eggert wrote:
> > On 2026-06-22 12:23, Adhemerval Zanella Netto wrote:
> > 
> > > Checking gnulib lib/tempname.h, think we can bake the dirfd argument with the
> > > cost of boilerplate:
> > 
> > Yes, the boilerplate is annoying - it's life in the callbacks big city.
> > 
> > >    struct my_ctx c = { dirfd, oflags, mode };
> > >    try_tempname (tmpl, suffixlen, &c, my_create);
> > 
> > We can shorten that a bit with a compound literal. And I suggest putting the function before its arg. Also, omit suffixlen, as the template's "X"s should tell the new function where any prefix and/or suffix lie, and how long the random part is. So something like this:
> > 
> >   try_tempname (tmpl, my_create, &(struct my_ctx){dirfd, oflags, mode});
> 
> I am trying also to avoid in-place mutation of the template, where makes string literals
> usage not possible and Florian [1] has noted that is another footgun.  It does force the
> function to create the temporary name itself, but for some usage the caller does not
> want always required it.

So we are talking about this gnulib try_tempname/try_tempname_len
function:
https://cgit.git.savannah.gnu.org/cgit/gnulib.git/tree/lib/tempname.h

Which doesn't take an dirfd, but could take one through a custom struct
(then passed as a void * to the callback) and works on a mutable char *
which we would like to avoid as a footgun? Instead we would like it to
return the (newly allocated) name of the tempfile (if it has one) which
is  then owned by the caller (which must free it)?

The callback should be free to tweak the name so that it has an
optional prefix and suffix, but not the actual "random" part, and it
should be free to choose a method that exclusively create the file with
any mode or flags it wants, as long as it includes O_EXCL and
O_CLOEXEC?

And then there is the "len" part of the random part (how many XXXes)?

I am not sure I got the full idea and constraints right, please correct
me if I misinterpreted some part of the idea(s). But it feels like the
"fixed" parts are the dirfd and name, there is an optional (?) len,
which the caller might care about, but the callback just sees the
length of the proposed tempname, and then the callback might use (be
given) a prefix/suffix/oflags/mode it can carry in the opaque void *
struct argument.

So would this be a possible prototype?

int
mkostempat (int dirfd,
           int (*tryfunc) (int, char**, void *), void *args,
           int len, char **name)

Where the tryfunc gets the dirfd, proposed name and arguments (the
proposed name would be of length len).

if tryfunc creates a new name (asprintf ("%s%s%s", prefix, name,
suffix)) then then original proposed name does need to be freed. There
is no real way to check the tryfunc used O_EXCL and O_CLOEXEC or that
the mode is reasonable. But the tryfunc callbacks will probably be
small and concise, easy to audit.

> > > there are still the issue of the safe default (forget O_EXCL (loses atomicity)
> > > or O_CLOEXEC (fd leak)). And these are still footguns that the non-callback avoids
> > We can address this by documenting a callback for use in a mkostempat-like function. People can then cut and paste out of the documentation if they like. The documentation can explain why O_EXCL and O_CLOEXEC are important.

Or maybe we can allow NULL for the callback, in which case it would be
the "standard" name/mode/len? Or maybe provide standard callbacks that
the user uses to mimic what some of the existing mkstemp family of
functions would do (when there was an at dirfd variant)?

Cheers,

Mark


More information about the Libc-alpha mailing list