[libc-commits] [libc] [libc] Add tmpnam implementation (PR #204901)

Jeff Bailey via libc-commits libc-commits at lists.llvm.org
Sat Jun 20 03:33:22 PDT 2026


================
@@ -0,0 +1,89 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Declaration of tmpnam, a POSIX function that generate a string that is a
+/// valid pathname that does not name an existing file. The function is
+/// potentially capable of generating {TMP_MAX} different strings, but any or
+/// all of them may already be in use by existing files and thus not be suitable
+/// return values.
+///
+/// The tmpnam() function generates a different string each time it is called
+/// from the same process, up to {TMP_MAX} times. If it is called more than
+/// {TMP_MAX} times, it returns nullptr. If called with a null pointer argument,
+//  the tmpnam() function need not be thread-safe;  however, such calls shall
+//  avoid data races with calls to tmpnam() with a non-null argument and with
+//  calls to all other functions.See:
+/// https://pubs.opengroup.org/onlinepubs/9799919799/functions/tmpnam.html
+///
+//===----------------------------------------------------------------------===//
+
+#include "src/stdio/tmpnam.h"
+#include "hdr/errno_macros.h"
+#include "hdr/stdio_macros.h"
+#include "hdr/unistd_macros.h"
+#include "src/__support/CPP/atomic.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/access.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/getrandom.h"
+#include "src/__support/macros/config.h"
+#include "src/stdio/snprintf.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+static char tmpbuf[L_tmpnam];
+static cpp::Atomic<size_t> tmpnam_budget = TMP_MAX;
+
+/* partially thread-safe */
+LLVM_LIBC_FUNCTION(char *, tmpnam, (char *s)) {
+  if (s == nullptr)
+    s = tmpbuf;
+
+  // here if the s is null then use tmpbuf and if sizeof
+  // POSIX portable filename character set, sorted by ASCII value.
+  // See
+  // https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap03.html#tag_03_265
+  const char charset[] = "-._0123456789"
+                         "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+                         "abcdefghijklmnopqrstuvwxyz";
+
+  int prefix_size = LIBC_NAMESPACE::snprintf(s, L_tmpnam, "%s/", P_tmpdir);
+
+  int is_unique = 0;
+  while (is_unique == 0) {
+    size_t curr_budget = tmpnam_budget.load(cpp::MemoryOrder::RELAXED);
----------------
kaladron wrote:

I'll need to walk through this, but I'm curious if this provides the thread-safety guarantees you're thinking of, given the gap between the load and cmpexch below?

(I'll want to do a second pass, but wanted to reply with other comments first)

https://github.com/llvm/llvm-project/pull/204901


More information about the libc-commits mailing list