[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();
+ if (fd < 0)
+ return EBADF;
+
+ auto result = internal::fcntl(fd, F_GETFL);
+ if (!result.has_value())
+ return EBADF;
+ int fd_flags = result.value();
+
+ using OpenMode = File::OpenMode;
+ using ModeFlags = File::ModeFlags;
+ if (((fd_flags & O_ACCMODE) == O_RDONLY &&
+ (modeflags & static_cast<ModeFlags>(OpenMode::WRITE))) ||
+ ((fd_flags & O_ACCMODE) == O_WRONLY &&
+ (modeflags & static_cast<ModeFlags>(OpenMode::READ)))) {
+ return EINVAL;
----------------
kaladron wrote:
I think this applies here:
[EBADF] The mode with which the file descriptor underlying the stream was opened does not support the requested mode when pathname is a null pointer.
https://github.com/llvm/llvm-project/pull/207837
More information about the libc-commits
mailing list