[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