[libc-commits] [libc] [libc] Implement freopen (PR #207837)

Jeff Bailey via libc-commits libc-commits at lists.llvm.org
Wed Jul 8 07:50:49 PDT 2026


================
@@ -176,4 +183,103 @@ int get_fileno(File *f) {
   return lf->get_fd();
 }
 
+int reopenfile(File *f, const char *path, const char *mode) {
+  auto modeflags = File::mode_flags(mode);
+  if (modeflags == 0)
+    return EINVAL;
+
+  auto *lf = reinterpret_cast<LinuxFile *>(f);
+
+  if (path != nullptr) {
+    int open_flags = mode_flags_to_open_flags(modeflags);
+
+    constexpr mode_t OPEN_MODE =
+        S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+
+    ErrorOr<int> new_fd = linux_syscalls::open(path, open_flags, OPEN_MODE);
+    int old_fd = lf->get_fd();
+
+    // If the new file fails to open, POSIX says we still have to close the old
+    // file.
+    if (!new_fd) {
+      if (old_fd >= 0) {
+        auto close_result = linux_syscalls::close(old_fd);
+        if (!close_result) {
+          f->reset_stream_state(modeflags);
+          return close_result.error();
+        }
+        lf->set_fd(-1);
+      }
+      f->reset_stream_state(modeflags);
+      return new_fd.error();
+    }
+
+    // Else the new file successfully opened, so we move it into the fd the old
+    // file was using if the old fd exists.
+    if (old_fd >= 0) {
+      auto dup_result = linux_syscalls::dup2(new_fd.value(), old_fd);
+      if (!dup_result) {
+        f->reset_stream_state(modeflags);
+        return dup_result.error();
+      }
+      auto close_result = linux_syscalls::close(new_fd.value());
+      if (!close_result) {
+        f->reset_stream_state(modeflags);
+        return close_result.error();
+      }
+    } else {
+      lf->set_fd(new_fd.value());
+    }
+
+    f->reset_stream_state(modeflags);
+    return 0;
+  }
+
+  int fd = lf->get_fd();
----------------
kaladron wrote:

Another place where an ErrorOr is potentially useful, but would be scope creep for this.

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


More information about the libc-commits mailing list