[PATCH] misc: Add mkostempat (BZ 19866)
Mark Wielaard
mark@klomp.org
Tue Jun 23 12:27:35 GMT 2026
Hi Adhemerval,
On Mon, 2026-06-22 at 10:57 -0300, Adhemerval Zanella Netto wrote:
> I think the changes below actually pull it back toward simplicity rather
> than away from it: the parameter count drops from 8 to 7, the size/ERANGE
> bookkeeping is gone, and the path handling is removed.
>
> The trivial "just give me a temp fd" case is now:
>
> int fd = mkostempat (dirfd, NULL, NULL, 0, 0, 0600, NULL);
>
> And the "I also want the name" case:
>
> char *name;
> int fd = mkostempat (dirfd, NULL, NULL, 0, 0, 0600, &name);
> ...
> free (name);
Yes, this is a nice cleanup. So for the first I assume it will simply
fail if O_TMPFILE doesn't work on the dirfd filesystem? Is it
guaranteed that errno will be set to EOPNOTSUPP or do you always have
to fall back to the second form?
I like the second form, that is the use case I think is most
useful/simple to adopt.
>
> > When creating an O_TMPFILE I think the user still wants a path name to
> > use either when the file system didn't support O_TMPFILE so you had to
> > fall back to a real filename, or when used to (atomically) replace
> > another file (which I believe is a common use case for mkstemp) because
> > there is no flink that just takes an fd and a new (or to be replaced)
> > name. renameat still needs a pathname (maybe /proc/self/fd/nr?).
>
> I think it is doable, but atomic-replace is still clunky for O_TMPFILE.
> With O_TMPFILE set, mkostempat can creates the unnamed file directly in
> dirfd and reports it by setting *namebuf to NULL. The descriptor is
> anonymous and returning /proc/self/fd/N has multiples issues - procfs
> might not be accessible and it goes stale after dup (so I think it should
> not be returned).
>
> However, the atomic-replace still requires either:
>
> 1. linkat (fd, "", newdirfd, newname, AT_EMPTY_PATH) — the closest thing to an
> "flink." But per the man page it requires CAP_DAC_READ_SEARCH (privileged).
>
> 2. linkat (AT_FDCWD, "/proc/self/fd/<fd>", newdirfd, newname, AT_SYMLINK_FOLLOW)
> — the unprivileged workaround, but needs procfs mounted.
>
> So the only way to atomically replace in a generic way using an O_TMPFILE fd is
> the two-step dance: linkat it to a fresh temp name (retrying on EEXIST, which is
> what mkstemp does...), then renameat(temp, target).
>
> With mkostempat would be something like:
>
> char *tmp;
> int fd = mkostempat (dirfd, ".target-", NULL, 0, 0, 0600, &tmp);
> write (fd, data, len); fsync (fd);
> renameat (dirfd, tmp, dirfd, "target"); /* atomic replace */
> free (tmp);
>
> The O_TMPFILE one less malloc/free, but it requires procfs to be mounted *and* an
> unique tmpname. I am more inclined to make O_TMPFILE return EINVAL instead.
It is a pity the O_TEMPFILE variant is a little harder to use. But it
is what it is without more kernel support. I don't understand exactly
why CAP_DAC_READ_SEARCH is needed. It is not a capability most
processes should have.
Thanks,
Mark
More information about the Libc-alpha
mailing list