[libc-commits] [libc] [libc] Add 'x' and 'e' mode support to fopen() (PR #224207)

Michael Jones via libc-commits libc-commits at lists.llvm.org
Thu Sep 17 09:53:30 PDT 2026


================
@@ -42,3 +57,78 @@ TEST(LlvmLibcFOpenTest, PrintToFile) {
     ASSERT_STREQ(data, STRING);
   }
 }
+
+#ifdef LIBC_TARGET_OS_IS_LINUX
+class LlvmLibcFOpenModeTest
+    : public LIBC_NAMESPACE::testing::ErrnoCheckingTest {
+protected:
+  void check_exclusive_create(const char *mode) {
+    const auto FILENAME = libc_make_test_file_path("fopen_exclusive.test");
+    constexpr char CONTENT[] = "Preserve this content";
+
+    // Remove a file left by an interrupted test run.
+    LIBC_NAMESPACE::remove(FILENAME);
+    libc_errno = 0;
+    FILE *file = LIBC_NAMESPACE::fopen(FILENAME, mode);
+    ASSERT_NE(file, nullptr);
+    scope_exit remove_file(
+        [&] { EXPECT_THAT(LIBC_NAMESPACE::remove(FILENAME), Succeeds(0)); });
+    {
+      scope_exit close_file(
+          [&] { EXPECT_THAT(LIBC_NAMESPACE::fclose(file), Succeeds(0)); });
+      ASSERT_EQ(LIBC_NAMESPACE::fwrite(CONTENT, 1, sizeof(CONTENT) - 1, file),
+                sizeof(CONTENT) - 1);
+    }
+
+    FILE *existing = LIBC_NAMESPACE::fopen(FILENAME, mode);
+    EXPECT_THAT(existing, Fails(EEXIST, static_cast<void *>(nullptr)));
+    if (existing != nullptr)
+      EXPECT_THAT(LIBC_NAMESPACE::fclose(existing), Succeeds(0));
+
+    file = LIBC_NAMESPACE::fopen(FILENAME, "r");
+    ASSERT_NE(file, nullptr);
+    scope_exit close_file(
+        [&] { EXPECT_THAT(LIBC_NAMESPACE::fclose(file), Succeeds(0)); });
+    char buffer[sizeof(CONTENT)] = {};
+    ASSERT_EQ(LIBC_NAMESPACE::fread(buffer, 1, sizeof(buffer) - 1, file),
+              sizeof(CONTENT) - 1);
+    EXPECT_STREQ(buffer, CONTENT);
+  }
+};
+
+TEST_F(LlvmLibcFOpenModeTest, ExclusiveWrite) { check_exclusive_create("wx"); }
+
+TEST_F(LlvmLibcFOpenModeTest, ExclusiveAppend) { check_exclusive_create("ax"); }
+
+TEST_F(LlvmLibcFOpenModeTest, CloseOnExec) {
+  {
+    FILE *file = LIBC_NAMESPACE::fopen("/dev/null", "w");
+    ASSERT_NE(file, nullptr);
+    scope_exit close_file(
+        [&] { EXPECT_THAT(LIBC_NAMESPACE::fclose(file), Succeeds(0)); });
----------------
michaelrj-google wrote:

this `scope_exit` is unnecessary. Just put the `fclose` after the `fcntl`. Same below.

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


More information about the libc-commits mailing list