[libc-commits] [libc] [libc][termios] Fix termios compatibility with glibc 2.42 or after. (PR #211039)
via libc-commits
libc-commits at lists.llvm.org
Thu Jul 23 14:46:45 PDT 2026
https://github.com/lntue updated https://github.com/llvm/llvm-project/pull/211039
>From f75918f7a9251d7a8dd3d307f0c2a2ec7141bf40 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Tue, 21 Jul 2026 16:21:46 +0000
Subject: [PATCH 1/6] [libc][termios] Fix termios compatibility with glibc 2.42
or after.
---
libc/hdr/CMakeLists.txt | 9 ++
libc/hdr/termios_macros.h | 27 ++++
libc/hdr/types/CMakeLists.txt | 33 +++++
libc/hdr/types/cc_t.h | 27 ++++
libc/hdr/types/speed_t.h | 27 ++++
libc/hdr/types/struct_termios.h | 27 ++++
libc/hdr/types/tcflag_t.h | 27 ++++
libc/src/termios/linux/CMakeLists.txt | 32 ++++-
libc/src/termios/linux/cfgetispeed.cpp | 12 +-
libc/src/termios/linux/cfgetospeed.cpp | 12 +-
libc/src/termios/linux/cfsetispeed.cpp | 15 +-
libc/src/termios/linux/cfsetospeed.cpp | 15 +-
libc/src/termios/linux/kernel_termios.h | 10 +-
libc/src/termios/linux/speed_utils.h | 184 ++++++++++++++++++++++++
libc/src/termios/linux/tcdrain.cpp | 9 +-
libc/src/termios/linux/tcflow.cpp | 9 +-
libc/src/termios/linux/tcflush.cpp | 9 +-
libc/src/termios/linux/tcgetattr.cpp | 14 +-
libc/src/termios/linux/tcgetsid.cpp | 9 +-
libc/src/termios/linux/tcsendbreak.cpp | 9 +-
libc/src/termios/linux/tcsetattr.cpp | 10 +-
libc/test/src/termios/CMakeLists.txt | 2 +
libc/test/src/termios/termios_test.cpp | 11 +-
23 files changed, 503 insertions(+), 36 deletions(-)
create mode 100644 libc/hdr/termios_macros.h
create mode 100644 libc/hdr/types/cc_t.h
create mode 100644 libc/hdr/types/speed_t.h
create mode 100644 libc/hdr/types/struct_termios.h
create mode 100644 libc/hdr/types/tcflag_t.h
create mode 100644 libc/src/termios/linux/speed_utils.h
diff --git a/libc/hdr/CMakeLists.txt b/libc/hdr/CMakeLists.txt
index 9df87558046fa..b511fd673eb40 100644
--- a/libc/hdr/CMakeLists.txt
+++ b/libc/hdr/CMakeLists.txt
@@ -234,6 +234,15 @@ add_proxy_header_library(
libc.include.llvm-libc-macros.sys_wait_macros
)
+add_proxy_header_library(
+ termios_macros
+ HDRS
+ termios_macros.h
+ FULL_BUILD_DEPENDS
+ libc.include.llvm-libc-macros.termios_macros
+)
+
+
add_header_library(unistd_overlay HDRS unistd_overlay.h)
add_proxy_header_library(
unistd_macros
diff --git a/libc/hdr/termios_macros.h b/libc/hdr/termios_macros.h
new file mode 100644
index 0000000000000..9ccf917a293e3
--- /dev/null
+++ b/libc/hdr/termios_macros.h
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// Proxy header for macros from termios.h.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_HDR_TERMIOS_MACROS_H
+#define LLVM_LIBC_HDR_TERMIOS_MACROS_H
+
+#ifdef LIBC_FULL_BUILD
+
+#include "include/llvm-libc-macros/termios-macros.h"
+
+#else // Overlay mode
+
+#include <termios.h>
+
+#endif // LIBC_FULL_BUILD
+
+#endif // LLVM_LIBC_HDR_TERMIOS_MACROS_H
diff --git a/libc/hdr/types/CMakeLists.txt b/libc/hdr/types/CMakeLists.txt
index 0f2590aed2deb..0e957813e8383 100644
--- a/libc/hdr/types/CMakeLists.txt
+++ b/libc/hdr/types/CMakeLists.txt
@@ -1218,3 +1218,36 @@ add_proxy_header_library(
FULL_BUILD_DEPENDS
libc.include.llvm-libc-types.regmatch_t
)
+
+add_proxy_header_library(
+ speed_t
+ HDRS
+ speed_t.h
+ FULL_BUILD_DEPENDS
+ libc.include.llvm-libc-types.speed_t
+)
+
+add_proxy_header_library(
+ struct_termios
+ HDRS
+ struct_termios.h
+ FULL_BUILD_DEPENDS
+ libc.include.llvm-libc-types.struct_termios
+)
+
+add_proxy_header_library(
+ cc_t
+ HDRS
+ cc_t.h
+ FULL_BUILD_DEPENDS
+ libc.include.llvm-libc-types.cc_t
+)
+
+add_proxy_header_library(
+ tcflag_t
+ HDRS
+ tcflag_t.h
+ FULL_BUILD_DEPENDS
+ libc.include.llvm-libc-types.tcflag_t
+)
+
diff --git a/libc/hdr/types/cc_t.h b/libc/hdr/types/cc_t.h
new file mode 100644
index 0000000000000..b830fcd7baa01
--- /dev/null
+++ b/libc/hdr/types/cc_t.h
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// Proxy header for cc_t.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_HDR_TYPES_CC_T_H
+#define LLVM_LIBC_HDR_TYPES_CC_T_H
+
+#ifdef LIBC_FULL_BUILD
+
+#include "include/llvm-libc-types/cc_t.h"
+
+#else
+
+#include <termios.h>
+
+#endif // LIBC_FULL_BUILD
+
+#endif // LLVM_LIBC_HDR_TYPES_CC_T_H
diff --git a/libc/hdr/types/speed_t.h b/libc/hdr/types/speed_t.h
new file mode 100644
index 0000000000000..93b4c239c02a4
--- /dev/null
+++ b/libc/hdr/types/speed_t.h
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// Proxy header for speed_t.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_HDR_TYPES_SPEED_T_H
+#define LLVM_LIBC_HDR_TYPES_SPEED_T_H
+
+#ifdef LIBC_FULL_BUILD
+
+#include "include/llvm-libc-types/speed_t.h"
+
+#else
+
+#include <termios.h>
+
+#endif // LIBC_FULL_BUILD
+
+#endif // LLVM_LIBC_HDR_TYPES_SPEED_T_H
diff --git a/libc/hdr/types/struct_termios.h b/libc/hdr/types/struct_termios.h
new file mode 100644
index 0000000000000..88305a8809f45
--- /dev/null
+++ b/libc/hdr/types/struct_termios.h
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// Proxy header for struct termios.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_HDR_TYPES_STRUCT_TERMIOS_H
+#define LLVM_LIBC_HDR_TYPES_STRUCT_TERMIOS_H
+
+#ifdef LIBC_FULL_BUILD
+
+#include "include/llvm-libc-types/struct_termios.h"
+
+#else
+
+#include <termios.h>
+
+#endif // LIBC_FULL_BUILD
+
+#endif // LLVM_LIBC_HDR_TYPES_STRUCT_TERMIOS_H
diff --git a/libc/hdr/types/tcflag_t.h b/libc/hdr/types/tcflag_t.h
new file mode 100644
index 0000000000000..4616889462274
--- /dev/null
+++ b/libc/hdr/types/tcflag_t.h
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// Proxy header for tcflag_t.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_HDR_TYPES_TCFLAG_T_H
+#define LLVM_LIBC_HDR_TYPES_TCFLAG_T_H
+
+#ifdef LIBC_FULL_BUILD
+
+#include "include/llvm-libc-types/tcflag_t.h"
+
+#else
+
+#include <termios.h>
+
+#endif // LIBC_FULL_BUILD
+
+#endif // LLVM_LIBC_HDR_TYPES_TCFLAG_T_H
diff --git a/libc/src/termios/linux/CMakeLists.txt b/libc/src/termios/linux/CMakeLists.txt
index 5d5440ae69266..e89041b641bf9 100644
--- a/libc/src/termios/linux/CMakeLists.txt
+++ b/libc/src/termios/linux/CMakeLists.txt
@@ -1,7 +1,17 @@
# There is no difference between input and output speeds on Linux.
# However, since POSIX requires separate functions for setting and getting
-# of the input and output speeds, we use different entrypoints wiht the
+# of the input and output speeds, we use different entrypoints with the
# same getter/setter logic.
+
+add_header_library(
+ speed_utils
+ HDRS
+ speed_utils.h
+ DEPENDS
+ libc.hdr.termios_macros
+ libc.hdr.types.speed_t
+)
+
add_entrypoint_object(
cfgetispeed
SRCS
@@ -10,6 +20,8 @@ add_entrypoint_object(
../cfgetispeed.h
DEPENDS
libc.include.termios
+ libc.hdr.types.speed_t
+ libc.hdr.types.struct_termios
)
add_entrypoint_object(
@@ -19,7 +31,9 @@ add_entrypoint_object(
HDRS
../cfsetispeed.h
DEPENDS
+ .speed_utils
libc.include.termios
+ libc.hdr.types.struct_termios
libc.src.errno.errno
)
@@ -31,6 +45,8 @@ add_entrypoint_object(
../cfgetospeed.h
DEPENDS
libc.include.termios
+ libc.hdr.types.speed_t
+ libc.hdr.types.struct_termios
)
add_entrypoint_object(
@@ -40,7 +56,9 @@ add_entrypoint_object(
HDRS
../cfsetospeed.h
DEPENDS
+ .speed_utils
libc.include.termios
+ libc.hdr.types.struct_termios
libc.src.errno.errno
)
@@ -52,6 +70,7 @@ add_entrypoint_object(
../tcgetsid.h
DEPENDS
libc.include.termios
+ libc.hdr.types.struct_termios
libc.src.__support.OSUtil.linux.syscall_wrappers.ioctl
libc.src.errno.errno
)
@@ -64,6 +83,7 @@ add_entrypoint_object(
../tcdrain.h
DEPENDS
libc.include.termios
+ libc.hdr.types.struct_termios
libc.src.__support.OSUtil.linux.syscall_wrappers.ioctl
libc.src.errno.errno
)
@@ -76,6 +96,7 @@ add_entrypoint_object(
../tcflush.h
DEPENDS
libc.include.termios
+ libc.hdr.termios_macros
libc.src.__support.OSUtil.linux.syscall_wrappers.ioctl
libc.src.errno.errno
)
@@ -88,6 +109,7 @@ add_entrypoint_object(
../tcflow.h
DEPENDS
libc.include.termios
+ libc.hdr.termios_macros
libc.src.__support.OSUtil.linux.syscall_wrappers.ioctl
libc.src.errno.errno
)
@@ -100,6 +122,7 @@ add_entrypoint_object(
../tcsendbreak.h
DEPENDS
libc.include.termios
+ libc.hdr.types.struct_termios
libc.src.__support.OSUtil.linux.syscall_wrappers.ioctl
libc.src.errno.errno
)
@@ -108,6 +131,9 @@ add_header_library(
kernel_termios
HDRS
kernel_termios.h
+ DEPENDS
+ libc.hdr.types.cc_t
+ libc.hdr.types.tcflag_t
)
add_entrypoint_object(
@@ -118,7 +144,9 @@ add_entrypoint_object(
../tcgetattr.h
DEPENDS
.kernel_termios
+ .speed_utils
libc.include.termios
+ libc.hdr.types.struct_termios
libc.src.__support.OSUtil.linux.syscall_wrappers.ioctl
libc.src.errno.errno
)
@@ -132,6 +160,8 @@ add_entrypoint_object(
DEPENDS
.kernel_termios
libc.include.termios
+ libc.hdr.termios_macros
+ libc.hdr.types.struct_termios
libc.src.__support.OSUtil.linux.syscall_wrappers.ioctl
libc.src.errno.errno
)
diff --git a/libc/src/termios/linux/cfgetispeed.cpp b/libc/src/termios/linux/cfgetispeed.cpp
index 19e9b9140aa2b..9d9c912b4f672 100644
--- a/libc/src/termios/linux/cfgetispeed.cpp
+++ b/libc/src/termios/linux/cfgetispeed.cpp
@@ -1,22 +1,28 @@
-//===-- Linux implementation of cfgetispeed -------------------------------===//
+//===----------------------------------------------------------------------===//
//
// 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
+/// Linux implementation of cfgetispeed.
+///
+//===----------------------------------------------------------------------===//
#include "src/termios/cfgetispeed.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
-#include <termios.h>
+#include "hdr/types/speed_t.h"
+#include "hdr/types/struct_termios.h"
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(speed_t, cfgetispeed, (const struct termios *t)) {
- return t->c_cflag & CBAUD;
+ return t->c_ispeed;
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/termios/linux/cfgetospeed.cpp b/libc/src/termios/linux/cfgetospeed.cpp
index d633beb8061f8..7c069de269b9d 100644
--- a/libc/src/termios/linux/cfgetospeed.cpp
+++ b/libc/src/termios/linux/cfgetospeed.cpp
@@ -1,22 +1,28 @@
-//===-- Linux implementation of cfgetospeed -------------------------------===//
+//===----------------------------------------------------------------------===//
//
// 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
+/// Linux implementation of cfgetospeed.
+///
+//===----------------------------------------------------------------------===//
#include "src/termios/cfgetospeed.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
-#include <termios.h>
+#include "hdr/types/speed_t.h"
+#include "hdr/types/struct_termios.h"
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(speed_t, cfgetospeed, (const struct termios *t)) {
- return t->c_cflag & CBAUD;
+ return t->c_ospeed;
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/termios/linux/cfsetispeed.cpp b/libc/src/termios/linux/cfsetispeed.cpp
index 47b19974d21be..9fd31f86a1254 100644
--- a/libc/src/termios/linux/cfsetispeed.cpp
+++ b/libc/src/termios/linux/cfsetispeed.cpp
@@ -1,30 +1,37 @@
-//===-- Linux implementation of cfsetispeed -------------------------------===//
+//===----------------------------------------------------------------------===//
//
// 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
+/// Linux implementation of cfsetispeed.
+///
+//===----------------------------------------------------------------------===//
#include "src/termios/cfsetispeed.h"
#include "src/__support/common.h"
#include "src/__support/libc_errno.h"
#include "src/__support/macros/config.h"
+#include "src/termios/linux/speed_utils.h"
-#include <termios.h>
+#include "hdr/types/struct_termios.h"
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(int, cfsetispeed, (struct termios * t, speed_t speed)) {
constexpr speed_t NOT_SPEED_MASK = ~speed_t(CBAUD);
+ speed_t encoded = encode_speed(speed);
// A speed value is valid only if it is equal to one of the B<NN+> values.
- if (t == nullptr || ((speed & NOT_SPEED_MASK) != 0)) {
+ if (t == nullptr || ((encoded & NOT_SPEED_MASK) != 0)) {
libc_errno = EINVAL;
return -1;
}
- t->c_cflag = (t->c_cflag & NOT_SPEED_MASK) | speed;
+ t->c_cflag = (t->c_cflag & NOT_SPEED_MASK) | encoded;
t->c_ispeed = speed;
return 0;
}
diff --git a/libc/src/termios/linux/cfsetospeed.cpp b/libc/src/termios/linux/cfsetospeed.cpp
index d2f138257a47a..c5c2e2cf8512b 100644
--- a/libc/src/termios/linux/cfsetospeed.cpp
+++ b/libc/src/termios/linux/cfsetospeed.cpp
@@ -1,30 +1,37 @@
-//===-- Linux implementation of cfsetospeed -------------------------------===//
+//===----------------------------------------------------------------------===//
//
// 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
+/// Linux implementation of cfsetospeed.
+///
+//===----------------------------------------------------------------------===//
#include "src/termios/cfsetospeed.h"
#include "src/__support/libc_errno.h"
#include "src/__support/macros/config.h"
#include "src/__support/common.h"
+#include "src/termios/linux/speed_utils.h"
-#include <termios.h>
+#include "hdr/types/struct_termios.h"
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(int, cfsetospeed, (struct termios * t, speed_t speed)) {
constexpr speed_t NOT_SPEED_MASK = ~speed_t(CBAUD);
+ speed_t encoded = encode_speed(speed);
// A speed value is valid only if it is equal to one of the B<NN+> values.
- if (t == nullptr || ((speed & NOT_SPEED_MASK) != 0)) {
+ if (t == nullptr || ((encoded & NOT_SPEED_MASK) != 0)) {
libc_errno = EINVAL;
return -1;
}
- t->c_cflag = (t->c_cflag & NOT_SPEED_MASK) | speed;
+ t->c_cflag = (t->c_cflag & NOT_SPEED_MASK) | encoded;
t->c_ospeed = speed;
return 0;
}
diff --git a/libc/src/termios/linux/kernel_termios.h b/libc/src/termios/linux/kernel_termios.h
index 5a3a9722789eb..cc499e7ab42a5 100644
--- a/libc/src/termios/linux/kernel_termios.h
+++ b/libc/src/termios/linux/kernel_termios.h
@@ -1,17 +1,23 @@
-//===-- Definition of kernel's version of struct termios --------*- C++ -*-===//
+//===----------------------------------------------------------------------===//
//
// 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
+/// Definition of the kernel's version of struct termios.
+///
+//===----------------------------------------------------------------------===//
#ifndef LLVM_LIBC_SRC_TERMIOS_LINUX_KERNEL_TERMIOS_H
#define LLVM_LIBC_SRC_TERMIOS_LINUX_KERNEL_TERMIOS_H
+#include "hdr/types/cc_t.h"
+#include "hdr/types/tcflag_t.h"
#include "src/__support/macros/config.h"
#include <stddef.h>
-#include <termios.h>
namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/src/termios/linux/speed_utils.h b/libc/src/termios/linux/speed_utils.h
new file mode 100644
index 0000000000000..4dcbef630238b
--- /dev/null
+++ b/libc/src/termios/linux/speed_utils.h
@@ -0,0 +1,184 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// Speed translation utilities for termios.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_TERMIOS_LINUX_SPEED_UTILS_H
+#define LLVM_LIBC_SRC_TERMIOS_LINUX_SPEED_UTILS_H
+
+#include "hdr/termios_macros.h"
+#include "hdr/types/speed_t.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+// glibc 2.42 changed the behavior of the termios Bxxx constants:
+// - Before glibc 2.42, the Bxxx constants correspond to the kernel speed
+// bitmasks
+// directly (e.g. B50 = 1).
+// - Starting from glibc 2.42, to support arbitrary baud rates numerically, the
+// Bxxx constants are defined as their actual integer values (e.g. B50 = 50).
+// In this case, we need to translate between the host's numerical speeds and
+// the kernel's speed bitmasks.
+// - If B50 == 1, then the host uses the kernel's bitmasks directly (no
+// translation).
+// - If B50 is not 1 (e.g. B50 == 50 in glibc >= 2.42), we apply
+// translation.
+#if (B50 == 1)
+
+LIBC_INLINE constexpr speed_t encode_speed(speed_t speed) { return speed; }
+LIBC_INLINE constexpr speed_t decode_speed(speed_t speed) { return speed; }
+
+#else // Overlay mode with numerical speeds (e.g. glibc)
+
+LIBC_INLINE constexpr speed_t encode_speed(speed_t speed) {
+ switch (speed) {
+ case 0:
+ return 0;
+ case 50:
+ return 0000001;
+ case 75:
+ return 0000002;
+ case 110:
+ return 0000003;
+ case 134:
+ return 0000004;
+ case 150:
+ return 0000005;
+ case 200:
+ return 0000006;
+ case 300:
+ return 0000007;
+ case 600:
+ return 0000010;
+ case 1200:
+ return 0000011;
+ case 1800:
+ return 0000012;
+ case 2400:
+ return 0000013;
+ case 4800:
+ return 0000014;
+ case 9600:
+ return 0000015;
+ case 19200:
+ return 0000016;
+ case 38400:
+ return 0000017;
+ case 57600:
+ return 0010001;
+ case 115200:
+ return 0010002;
+ case 230400:
+ return 0010003;
+ case 460800:
+ return 0010004;
+ case 500000:
+ return 0010005;
+ case 576000:
+ return 0010006;
+ case 921600:
+ return 0010007;
+ case 1000000:
+ return 0010010;
+ case 1152000:
+ return 0010011;
+ case 1500000:
+ return 0010012;
+ case 2000000:
+ return 0010013;
+ case 2500000:
+ return 0010014;
+ case 3000000:
+ return 0010015;
+ case 3500000:
+ return 0010016;
+ case 4000000:
+ return 0010017;
+ default:
+ return speed;
+ }
+}
+
+LIBC_INLINE constexpr speed_t decode_speed(speed_t kernel_speed) {
+ switch (kernel_speed) {
+ case 0:
+ return 0;
+ case 0000001:
+ return 50;
+ case 0000002:
+ return 75;
+ case 0000003:
+ return 110;
+ case 0000004:
+ return 134;
+ case 0000005:
+ return 150;
+ case 0000006:
+ return 200;
+ case 0000007:
+ return 300;
+ case 0000010:
+ return 600;
+ case 0000011:
+ return 1200;
+ case 0000012:
+ return 1800;
+ case 0000013:
+ return 2400;
+ case 0000014:
+ return 4800;
+ case 0000015:
+ return 9600;
+ case 0000016:
+ return 19200;
+ case 0000017:
+ return 38400;
+ case 0010001:
+ return 57600;
+ case 0010002:
+ return 115200;
+ case 0010003:
+ return 230400;
+ case 0010004:
+ return 460800;
+ case 0010005:
+ return 500000;
+ case 0010006:
+ return 576000;
+ case 0010007:
+ return 921600;
+ case 0010010:
+ return 1000000;
+ case 0010011:
+ return 1152000;
+ case 0010012:
+ return 1500000;
+ case 0010013:
+ return 2000000;
+ case 0010014:
+ return 2500000;
+ case 0010015:
+ return 3000000;
+ case 0010016:
+ return 3500000;
+ case 0010017:
+ return 4000000;
+ default:
+ return kernel_speed;
+ }
+}
+
+#endif // LIBC_FULL_BUILD
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_TERMIOS_LINUX_SPEED_UTILS_H
diff --git a/libc/src/termios/linux/tcdrain.cpp b/libc/src/termios/linux/tcdrain.cpp
index 4fce89d65a76f..fa2f5a1ed91ca 100644
--- a/libc/src/termios/linux/tcdrain.cpp
+++ b/libc/src/termios/linux/tcdrain.cpp
@@ -1,20 +1,25 @@
-//===-- Linux implementation of tcdrain -----------------------------------===//
+//===----------------------------------------------------------------------===//
//
// 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
+/// Linux implementation of tcdrain.
+///
+//===----------------------------------------------------------------------===//
#include "src/termios/tcdrain.h"
+#include "hdr/types/struct_termios.h"
#include "src/__support/OSUtil/linux/syscall_wrappers/ioctl.h"
#include "src/__support/common.h"
#include "src/__support/libc_errno.h"
#include "src/__support/macros/config.h"
#include <asm/ioctls.h> // Safe to include without the risk of name pollution.
-#include <termios.h>
namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/src/termios/linux/tcflow.cpp b/libc/src/termios/linux/tcflow.cpp
index 4ffd294997ad4..7efc9dd4a4cb6 100644
--- a/libc/src/termios/linux/tcflow.cpp
+++ b/libc/src/termios/linux/tcflow.cpp
@@ -1,20 +1,25 @@
-//===-- Linux implementation of tcflow -----------------------------------===//
+//===----------------------------------------------------------------------===//
//
// 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
+/// Linux implementation of tcflow.
+///
+//===----------------------------------------------------------------------===//
#include "src/termios/tcflow.h"
+#include "hdr/termios_macros.h"
#include "src/__support/OSUtil/linux/syscall_wrappers/ioctl.h"
#include "src/__support/common.h"
#include "src/__support/libc_errno.h"
#include "src/__support/macros/config.h"
#include <asm/ioctls.h> // Safe to include without the risk of name pollution.
-#include <termios.h>
namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/src/termios/linux/tcflush.cpp b/libc/src/termios/linux/tcflush.cpp
index 8a4676d97454a..684445a3d2732 100644
--- a/libc/src/termios/linux/tcflush.cpp
+++ b/libc/src/termios/linux/tcflush.cpp
@@ -1,20 +1,25 @@
-//===-- Linux implementation of tcflush -----------------------------------===//
+//===----------------------------------------------------------------------===//
//
// 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
+/// Linux implementation of tcflush.
+///
+//===----------------------------------------------------------------------===//
#include "src/termios/tcflush.h"
+#include "hdr/termios_macros.h"
#include "src/__support/OSUtil/linux/syscall_wrappers/ioctl.h"
#include "src/__support/common.h"
#include "src/__support/libc_errno.h"
#include "src/__support/macros/config.h"
#include <asm/ioctls.h> // Safe to include without the risk of name pollution.
-#include <termios.h>
namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/src/termios/linux/tcgetattr.cpp b/libc/src/termios/linux/tcgetattr.cpp
index 0569be4ae588f..588a1de61fb9c 100644
--- a/libc/src/termios/linux/tcgetattr.cpp
+++ b/libc/src/termios/linux/tcgetattr.cpp
@@ -1,20 +1,26 @@
-//===-- Linux implementation of tcgetattr ---------------------------------===//
+//===----------------------------------------------------------------------===//
//
// 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
+/// Linux implementation of tcgetattr.
+///
+//===----------------------------------------------------------------------===//
#include "src/termios/tcgetattr.h"
+#include "hdr/types/struct_termios.h"
#include "src/__support/OSUtil/linux/syscall_wrappers/ioctl.h"
#include "src/__support/common.h"
#include "src/__support/libc_errno.h"
#include "src/__support/macros/config.h"
#include "src/termios/linux/kernel_termios.h"
+#include "src/termios/linux/speed_utils.h"
#include <asm/ioctls.h> // Safe to include without the risk of name pollution.
-#include <termios.h>
namespace LIBC_NAMESPACE_DECL {
@@ -29,8 +35,8 @@ LLVM_LIBC_FUNCTION(int, tcgetattr, (int fd, struct termios *t)) {
t->c_oflag = kt.c_oflag;
t->c_cflag = kt.c_cflag;
t->c_lflag = kt.c_lflag;
- t->c_ispeed = kt.c_cflag & CBAUD;
- t->c_ospeed = kt.c_cflag & CBAUD;
+ t->c_ispeed = decode_speed(kt.c_cflag & CBAUD);
+ t->c_ospeed = decode_speed(kt.c_cflag & CBAUD);
size_t nccs = KERNEL_NCCS <= NCCS ? KERNEL_NCCS : NCCS;
for (size_t i = 0; i < nccs; ++i)
diff --git a/libc/src/termios/linux/tcgetsid.cpp b/libc/src/termios/linux/tcgetsid.cpp
index f80fd31b65865..2cafb44b9a55f 100644
--- a/libc/src/termios/linux/tcgetsid.cpp
+++ b/libc/src/termios/linux/tcgetsid.cpp
@@ -1,20 +1,25 @@
-//===-- Linux implementation of tcgetsid ----------------------------------===//
+//===----------------------------------------------------------------------===//
//
// 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
+/// Linux implementation of tcgetsid.
+///
+//===----------------------------------------------------------------------===//
#include "src/termios/tcgetsid.h"
+#include "hdr/types/struct_termios.h"
#include "src/__support/OSUtil/linux/syscall_wrappers/ioctl.h"
#include "src/__support/common.h"
#include "src/__support/libc_errno.h"
#include "src/__support/macros/config.h"
#include <asm/ioctls.h> // Safe to include without the risk of name pollution.
-#include <termios.h>
namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/src/termios/linux/tcsendbreak.cpp b/libc/src/termios/linux/tcsendbreak.cpp
index e91ec7b748582..0157d6098b218 100644
--- a/libc/src/termios/linux/tcsendbreak.cpp
+++ b/libc/src/termios/linux/tcsendbreak.cpp
@@ -1,20 +1,25 @@
-//===-- Linux implementation of tcsendbreak -------------------------------===//
+//===----------------------------------------------------------------------===//
//
// 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
+/// Linux implementation of tcsendbreak.
+///
+//===----------------------------------------------------------------------===//
#include "src/termios/tcsendbreak.h"
+#include "hdr/types/struct_termios.h"
#include "src/__support/OSUtil/linux/syscall_wrappers/ioctl.h"
#include "src/__support/common.h"
#include "src/__support/libc_errno.h"
#include "src/__support/macros/config.h"
#include <asm/ioctls.h> // Safe to include without the risk of name pollution.
-#include <termios.h>
namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/src/termios/linux/tcsetattr.cpp b/libc/src/termios/linux/tcsetattr.cpp
index b2f08d078ee83..25e36813ca283 100644
--- a/libc/src/termios/linux/tcsetattr.cpp
+++ b/libc/src/termios/linux/tcsetattr.cpp
@@ -1,12 +1,19 @@
-//===-- Linux implementation of tcsetattr ---------------------------------===//
+//===----------------------------------------------------------------------===//
//
// 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
+/// Linux implementation of tcsetattr.
+///
+//===----------------------------------------------------------------------===//
#include "src/termios/tcsetattr.h"
+#include "hdr/termios_macros.h"
+#include "hdr/types/struct_termios.h"
#include "src/__support/OSUtil/linux/syscall_wrappers/ioctl.h"
#include "src/__support/common.h"
#include "src/__support/libc_errno.h"
@@ -14,7 +21,6 @@
#include "src/termios/linux/kernel_termios.h"
#include <asm/ioctls.h> // Safe to include without the risk of name pollution.
-#include <termios.h>
namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/test/src/termios/CMakeLists.txt b/libc/test/src/termios/CMakeLists.txt
index 059c272c105c4..2ff137e89ebc1 100644
--- a/libc/test/src/termios/CMakeLists.txt
+++ b/libc/test/src/termios/CMakeLists.txt
@@ -8,6 +8,8 @@ add_libc_unittest(
termios_test.cpp
DEPENDS
libc.include.termios
+ libc.hdr.termios_macros
+ libc.hdr.types.struct_termios
libc.src.errno.errno
libc.src.fcntl.open
libc.src.termios.cfgetispeed
diff --git a/libc/test/src/termios/termios_test.cpp b/libc/test/src/termios/termios_test.cpp
index 7a8075997a4a8..91ec1294be3ad 100644
--- a/libc/test/src/termios/termios_test.cpp
+++ b/libc/test/src/termios/termios_test.cpp
@@ -1,11 +1,18 @@
-//===-- Unittests for a bunch of functions in termios.h -------------------===//
+//===----------------------------------------------------------------------===//
//
// 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
+/// Unittests for functions in termios.h.
+///
+//===----------------------------------------------------------------------===//
+#include "hdr/termios_macros.h"
+#include "hdr/types/struct_termios.h"
#include "src/__support/libc_errno.h"
#include "src/fcntl/open.h"
#include "src/termios/cfgetispeed.h"
@@ -20,8 +27,6 @@
#include "test/UnitTest/ErrnoSetterMatcher.h"
#include "test/UnitTest/Test.h"
-#include <termios.h>
-
using LlvmLibcTermiosTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest;
using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher;
>From 00df12cd7e2bdb8f49a3c65c31078f0b20c17560 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Tue, 21 Jul 2026 17:53:46 +0000
Subject: [PATCH 2/6] Address comments.
---
libc/src/termios/cfgetispeed.h | 5 ++--
libc/src/termios/cfgetospeed.h | 5 ++--
libc/src/termios/cfsetispeed.h | 5 ++--
libc/src/termios/cfsetospeed.h | 5 ++--
libc/src/termios/linux/CMakeLists.txt | 13 +++++++--
libc/src/termios/linux/cfgetispeed.cpp | 9 +++---
libc/src/termios/linux/cfgetospeed.cpp | 9 +++---
libc/src/termios/linux/cfsetispeed.cpp | 13 ++++-----
libc/src/termios/linux/cfsetospeed.cpp | 15 +++++-----
libc/src/termios/linux/speed_utils.h | 2 +-
libc/src/termios/linux/tcgetattr.cpp | 20 +++++++++----
libc/src/termios/linux/tcgetsid.cpp | 2 +-
libc/src/termios/linux/tcsendbreak.cpp | 3 +-
libc/src/termios/linux/tcsetattr.cpp | 20 +++++++++----
libc/src/termios/tcgetattr.h | 4 +--
libc/src/termios/tcsetattr.h | 4 +--
libc/test/src/termios/termios_test.cpp | 40 ++++++++++++++++++++++++--
17 files changed, 119 insertions(+), 55 deletions(-)
diff --git a/libc/src/termios/cfgetispeed.h b/libc/src/termios/cfgetispeed.h
index 56b0ab852cdb8..fb058b197fca4 100644
--- a/libc/src/termios/cfgetispeed.h
+++ b/libc/src/termios/cfgetispeed.h
@@ -9,12 +9,13 @@
#ifndef LLVM_LIBC_SRC_TERMIOS_CFGETISPEED_H
#define LLVM_LIBC_SRC_TERMIOS_CFGETISPEED_H
+#include "hdr/types/speed_t.h"
+#include "hdr/types/struct_termios.h"
#include "src/__support/macros/config.h"
-#include <termios.h>
namespace LIBC_NAMESPACE_DECL {
-speed_t cfgetispeed(const struct termios *t);
+speed_t cfgetispeed(const termios *t);
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/termios/cfgetospeed.h b/libc/src/termios/cfgetospeed.h
index 9d8e6656b0e9b..9126d0880f88d 100644
--- a/libc/src/termios/cfgetospeed.h
+++ b/libc/src/termios/cfgetospeed.h
@@ -9,12 +9,13 @@
#ifndef LLVM_LIBC_SRC_TERMIOS_CFGETOSPEED_H
#define LLVM_LIBC_SRC_TERMIOS_CFGETOSPEED_H
+#include "hdr/types/speed_t.h"
+#include "hdr/types/struct_termios.h"
#include "src/__support/macros/config.h"
-#include <termios.h>
namespace LIBC_NAMESPACE_DECL {
-speed_t cfgetospeed(const struct termios *t);
+speed_t cfgetospeed(const termios *t);
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/termios/cfsetispeed.h b/libc/src/termios/cfsetispeed.h
index 89b683e560489..5799bf1bf2455 100644
--- a/libc/src/termios/cfsetispeed.h
+++ b/libc/src/termios/cfsetispeed.h
@@ -9,12 +9,13 @@
#ifndef LLVM_LIBC_SRC_TERMIOS_CFSETISPEED_H
#define LLVM_LIBC_SRC_TERMIOS_CFSETISPEED_H
+#include "hdr/types/speed_t.h"
+#include "hdr/types/struct_termios.h"
#include "src/__support/macros/config.h"
-#include <termios.h>
namespace LIBC_NAMESPACE_DECL {
-int cfsetispeed(struct termios *t, speed_t speed);
+int cfsetispeed(termios *t, speed_t speed);
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/termios/cfsetospeed.h b/libc/src/termios/cfsetospeed.h
index 2f2c5315fb690..940e4d70ecff7 100644
--- a/libc/src/termios/cfsetospeed.h
+++ b/libc/src/termios/cfsetospeed.h
@@ -9,12 +9,13 @@
#ifndef LLVM_LIBC_SRC_TERMIOS_CFSETOSPEED_H
#define LLVM_LIBC_SRC_TERMIOS_CFSETOSPEED_H
+#include "hdr/types/speed_t.h"
+#include "hdr/types/struct_termios.h"
#include "src/__support/macros/config.h"
-#include <termios.h>
namespace LIBC_NAMESPACE_DECL {
-int cfsetospeed(struct termios *t, speed_t speed);
+int cfsetospeed(termios *t, speed_t speed);
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/termios/linux/CMakeLists.txt b/libc/src/termios/linux/CMakeLists.txt
index e89041b641bf9..ef2c115cb8ea0 100644
--- a/libc/src/termios/linux/CMakeLists.txt
+++ b/libc/src/termios/linux/CMakeLists.txt
@@ -22,6 +22,7 @@ add_entrypoint_object(
libc.include.termios
libc.hdr.types.speed_t
libc.hdr.types.struct_termios
+ libc.src.__support.macros.null_check
)
add_entrypoint_object(
@@ -33,8 +34,10 @@ add_entrypoint_object(
DEPENDS
.speed_utils
libc.include.termios
+ libc.hdr.types.speed_t
libc.hdr.types.struct_termios
libc.src.errno.errno
+ libc.src.__support.macros.null_check
)
add_entrypoint_object(
@@ -47,6 +50,7 @@ add_entrypoint_object(
libc.include.termios
libc.hdr.types.speed_t
libc.hdr.types.struct_termios
+ libc.src.__support.macros.null_check
)
add_entrypoint_object(
@@ -58,8 +62,10 @@ add_entrypoint_object(
DEPENDS
.speed_utils
libc.include.termios
+ libc.hdr.types.speed_t
libc.hdr.types.struct_termios
libc.src.errno.errno
+ libc.src.__support.macros.null_check
)
add_entrypoint_object(
@@ -70,7 +76,7 @@ add_entrypoint_object(
../tcgetsid.h
DEPENDS
libc.include.termios
- libc.hdr.types.struct_termios
+ libc.hdr.types.pid_t
libc.src.__support.OSUtil.linux.syscall_wrappers.ioctl
libc.src.errno.errno
)
@@ -122,7 +128,6 @@ add_entrypoint_object(
../tcsendbreak.h
DEPENDS
libc.include.termios
- libc.hdr.types.struct_termios
libc.src.__support.OSUtil.linux.syscall_wrappers.ioctl
libc.src.errno.errno
)
@@ -146,9 +151,11 @@ add_entrypoint_object(
.kernel_termios
.speed_utils
libc.include.termios
+ libc.hdr.termios_macros
libc.hdr.types.struct_termios
libc.src.__support.OSUtil.linux.syscall_wrappers.ioctl
libc.src.errno.errno
+ libc.src.__support.macros.null_check
)
add_entrypoint_object(
@@ -159,9 +166,11 @@ add_entrypoint_object(
../tcsetattr.h
DEPENDS
.kernel_termios
+ .speed_utils
libc.include.termios
libc.hdr.termios_macros
libc.hdr.types.struct_termios
libc.src.__support.OSUtil.linux.syscall_wrappers.ioctl
libc.src.errno.errno
+ libc.src.__support.macros.null_check
)
diff --git a/libc/src/termios/linux/cfgetispeed.cpp b/libc/src/termios/linux/cfgetispeed.cpp
index 9d9c912b4f672..bb0f49a206f6f 100644
--- a/libc/src/termios/linux/cfgetispeed.cpp
+++ b/libc/src/termios/linux/cfgetispeed.cpp
@@ -12,16 +12,15 @@
//===----------------------------------------------------------------------===//
#include "src/termios/cfgetispeed.h"
-
-#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
-
#include "hdr/types/speed_t.h"
#include "hdr/types/struct_termios.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/null_check.h"
namespace LIBC_NAMESPACE_DECL {
-LLVM_LIBC_FUNCTION(speed_t, cfgetispeed, (const struct termios *t)) {
+LLVM_LIBC_FUNCTION(speed_t, cfgetispeed, (const termios *t)) {
+ LIBC_CRASH_ON_NULLPTR(t);
return t->c_ispeed;
}
diff --git a/libc/src/termios/linux/cfgetospeed.cpp b/libc/src/termios/linux/cfgetospeed.cpp
index 7c069de269b9d..3da0447f961a4 100644
--- a/libc/src/termios/linux/cfgetospeed.cpp
+++ b/libc/src/termios/linux/cfgetospeed.cpp
@@ -12,16 +12,15 @@
//===----------------------------------------------------------------------===//
#include "src/termios/cfgetospeed.h"
-
-#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
-
#include "hdr/types/speed_t.h"
#include "hdr/types/struct_termios.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/null_check.h"
namespace LIBC_NAMESPACE_DECL {
-LLVM_LIBC_FUNCTION(speed_t, cfgetospeed, (const struct termios *t)) {
+LLVM_LIBC_FUNCTION(speed_t, cfgetospeed, (const termios *t)) {
+ LIBC_CRASH_ON_NULLPTR(t);
return t->c_ospeed;
}
diff --git a/libc/src/termios/linux/cfsetispeed.cpp b/libc/src/termios/linux/cfsetispeed.cpp
index 9fd31f86a1254..0b9b6e440bc8c 100644
--- a/libc/src/termios/linux/cfsetispeed.cpp
+++ b/libc/src/termios/linux/cfsetispeed.cpp
@@ -12,21 +12,20 @@
//===----------------------------------------------------------------------===//
#include "src/termios/cfsetispeed.h"
-
+#include "hdr/types/struct_termios.h"
#include "src/__support/common.h"
#include "src/__support/libc_errno.h"
-#include "src/__support/macros/config.h"
+#include "src/__support/macros/null_check.h"
#include "src/termios/linux/speed_utils.h"
-#include "hdr/types/struct_termios.h"
-
namespace LIBC_NAMESPACE_DECL {
-LLVM_LIBC_FUNCTION(int, cfsetispeed, (struct termios * t, speed_t speed)) {
- constexpr speed_t NOT_SPEED_MASK = ~speed_t(CBAUD);
+LLVM_LIBC_FUNCTION(int, cfsetispeed, (termios * t, speed_t speed)) {
+ LIBC_CRASH_ON_NULLPTR(t);
+ constexpr speed_t NOT_SPEED_MASK = ~static_cast<speed_t>(CBAUD);
speed_t encoded = encode_speed(speed);
// A speed value is valid only if it is equal to one of the B<NN+> values.
- if (t == nullptr || ((encoded & NOT_SPEED_MASK) != 0)) {
+ if ((encoded & NOT_SPEED_MASK) != 0) {
libc_errno = EINVAL;
return -1;
}
diff --git a/libc/src/termios/linux/cfsetospeed.cpp b/libc/src/termios/linux/cfsetospeed.cpp
index c5c2e2cf8512b..38f4d3f310095 100644
--- a/libc/src/termios/linux/cfsetospeed.cpp
+++ b/libc/src/termios/linux/cfsetospeed.cpp
@@ -12,21 +12,20 @@
//===----------------------------------------------------------------------===//
#include "src/termios/cfsetospeed.h"
-#include "src/__support/libc_errno.h"
-#include "src/__support/macros/config.h"
-
+#include "hdr/types/struct_termios.h"
#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
+#include "src/__support/macros/null_check.h"
#include "src/termios/linux/speed_utils.h"
-#include "hdr/types/struct_termios.h"
-
namespace LIBC_NAMESPACE_DECL {
-LLVM_LIBC_FUNCTION(int, cfsetospeed, (struct termios * t, speed_t speed)) {
- constexpr speed_t NOT_SPEED_MASK = ~speed_t(CBAUD);
+LLVM_LIBC_FUNCTION(int, cfsetospeed, (termios * t, speed_t speed)) {
+ LIBC_CRASH_ON_NULLPTR(t);
+ constexpr speed_t NOT_SPEED_MASK = ~static_cast<speed_t>(CBAUD);
speed_t encoded = encode_speed(speed);
// A speed value is valid only if it is equal to one of the B<NN+> values.
- if (t == nullptr || ((encoded & NOT_SPEED_MASK) != 0)) {
+ if ((encoded & NOT_SPEED_MASK) != 0) {
libc_errno = EINVAL;
return -1;
}
diff --git a/libc/src/termios/linux/speed_utils.h b/libc/src/termios/linux/speed_utils.h
index 4dcbef630238b..cc0d76e2cc3b5 100644
--- a/libc/src/termios/linux/speed_utils.h
+++ b/libc/src/termios/linux/speed_utils.h
@@ -177,7 +177,7 @@ LIBC_INLINE constexpr speed_t decode_speed(speed_t kernel_speed) {
}
}
-#endif // LIBC_FULL_BUILD
+#endif // (B50 == 1)
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/termios/linux/tcgetattr.cpp b/libc/src/termios/linux/tcgetattr.cpp
index 588a1de61fb9c..5e7f3d2f9c794 100644
--- a/libc/src/termios/linux/tcgetattr.cpp
+++ b/libc/src/termios/linux/tcgetattr.cpp
@@ -12,11 +12,13 @@
//===----------------------------------------------------------------------===//
#include "src/termios/tcgetattr.h"
+#include "hdr/termios_macros.h"
#include "hdr/types/struct_termios.h"
+#include "src/__support/CPP/algorithm.h"
#include "src/__support/OSUtil/linux/syscall_wrappers/ioctl.h"
#include "src/__support/common.h"
#include "src/__support/libc_errno.h"
-#include "src/__support/macros/config.h"
+#include "src/__support/macros/null_check.h"
#include "src/termios/linux/kernel_termios.h"
#include "src/termios/linux/speed_utils.h"
@@ -24,7 +26,8 @@
namespace LIBC_NAMESPACE_DECL {
-LLVM_LIBC_FUNCTION(int, tcgetattr, (int fd, struct termios *t)) {
+LLVM_LIBC_FUNCTION(int, tcgetattr, (int fd, termios *t)) {
+ LIBC_CRASH_ON_NULLPTR(t);
LIBC_NAMESPACE::kernel_termios kt;
auto ret = linux_syscalls::ioctl(fd, TCGETS, &kt);
if (!ret.has_value()) {
@@ -35,10 +38,17 @@ LLVM_LIBC_FUNCTION(int, tcgetattr, (int fd, struct termios *t)) {
t->c_oflag = kt.c_oflag;
t->c_cflag = kt.c_cflag;
t->c_lflag = kt.c_lflag;
- t->c_ispeed = decode_speed(kt.c_cflag & CBAUD);
- t->c_ospeed = decode_speed(kt.c_cflag & CBAUD);
+ t->c_line = kt.c_line;
- size_t nccs = KERNEL_NCCS <= NCCS ? KERNEL_NCCS : NCCS;
+ speed_t ospeed_mask = kt.c_cflag & CBAUD;
+ speed_t ispeed_mask = (kt.c_cflag & CIBAUD) >> 16;
+ if (ispeed_mask == 0)
+ ispeed_mask = ospeed_mask;
+
+ t->c_ospeed = decode_speed(ospeed_mask);
+ t->c_ispeed = decode_speed(ispeed_mask);
+
+ size_t nccs = cpp::min(KERNEL_NCCS, static_cast<size_t>(NCCS));
for (size_t i = 0; i < nccs; ++i)
t->c_cc[i] = kt.c_cc[i];
if (NCCS > nccs) {
diff --git a/libc/src/termios/linux/tcgetsid.cpp b/libc/src/termios/linux/tcgetsid.cpp
index 2cafb44b9a55f..087f7ba4f8c64 100644
--- a/libc/src/termios/linux/tcgetsid.cpp
+++ b/libc/src/termios/linux/tcgetsid.cpp
@@ -13,7 +13,7 @@
#include "src/termios/tcgetsid.h"
-#include "hdr/types/struct_termios.h"
+#include "hdr/types/pid_t.h"
#include "src/__support/OSUtil/linux/syscall_wrappers/ioctl.h"
#include "src/__support/common.h"
#include "src/__support/libc_errno.h"
diff --git a/libc/src/termios/linux/tcsendbreak.cpp b/libc/src/termios/linux/tcsendbreak.cpp
index 0157d6098b218..90866c4f54d82 100644
--- a/libc/src/termios/linux/tcsendbreak.cpp
+++ b/libc/src/termios/linux/tcsendbreak.cpp
@@ -13,7 +13,6 @@
#include "src/termios/tcsendbreak.h"
-#include "hdr/types/struct_termios.h"
#include "src/__support/OSUtil/linux/syscall_wrappers/ioctl.h"
#include "src/__support/common.h"
#include "src/__support/libc_errno.h"
@@ -23,7 +22,7 @@
namespace LIBC_NAMESPACE_DECL {
-LLVM_LIBC_FUNCTION(pid_t, tcsendbreak, (int fd, int /* unused duration */)) {
+LLVM_LIBC_FUNCTION(int, tcsendbreak, (int fd, int /* unused duration */)) {
// POSIX leaves the behavior for non-zero duration implementation dependent.
// Which means that the behavior can be the same as it is when duration is
// zero. So, we just pass zero to the syscall.
diff --git a/libc/src/termios/linux/tcsetattr.cpp b/libc/src/termios/linux/tcsetattr.cpp
index 25e36813ca283..e22810bbc5a62 100644
--- a/libc/src/termios/linux/tcsetattr.cpp
+++ b/libc/src/termios/linux/tcsetattr.cpp
@@ -14,18 +14,20 @@
#include "src/termios/tcsetattr.h"
#include "hdr/termios_macros.h"
#include "hdr/types/struct_termios.h"
+#include "src/__support/CPP/algorithm.h"
#include "src/__support/OSUtil/linux/syscall_wrappers/ioctl.h"
#include "src/__support/common.h"
#include "src/__support/libc_errno.h"
-#include "src/__support/macros/config.h"
+#include "src/__support/macros/null_check.h"
#include "src/termios/linux/kernel_termios.h"
+#include "src/termios/linux/speed_utils.h"
#include <asm/ioctls.h> // Safe to include without the risk of name pollution.
namespace LIBC_NAMESPACE_DECL {
-LLVM_LIBC_FUNCTION(int, tcsetattr,
- (int fd, int actions, const struct termios *t)) {
+LLVM_LIBC_FUNCTION(int, tcsetattr, (int fd, int actions, const termios *t)) {
+ LIBC_CRASH_ON_NULLPTR(t);
struct kernel_termios kt;
long cmd;
@@ -46,9 +48,17 @@ LLVM_LIBC_FUNCTION(int, tcsetattr,
kt.c_iflag = t->c_iflag;
kt.c_oflag = t->c_oflag;
- kt.c_cflag = t->c_cflag;
+
+ speed_t ospeed = encode_speed(t->c_ospeed);
+ speed_t ispeed = t->c_ispeed == 0 ? ospeed : encode_speed(t->c_ispeed);
+
+ constexpr speed_t NOT_SPEED_MASK = ~static_cast<speed_t>(CBAUD | CIBAUD);
+ kt.c_cflag = (t->c_cflag & NOT_SPEED_MASK) | ospeed | (ispeed << 16);
+
kt.c_lflag = t->c_lflag;
- size_t nccs = KERNEL_NCCS <= NCCS ? KERNEL_NCCS : NCCS;
+ kt.c_line = t->c_line;
+
+ size_t nccs = cpp::min(KERNEL_NCCS, static_cast<size_t>(NCCS));
for (size_t i = 0; i < nccs; ++i)
kt.c_cc[i] = t->c_cc[i];
if (nccs < KERNEL_NCCS) {
diff --git a/libc/src/termios/tcgetattr.h b/libc/src/termios/tcgetattr.h
index 54b169aedad88..fee34ad859832 100644
--- a/libc/src/termios/tcgetattr.h
+++ b/libc/src/termios/tcgetattr.h
@@ -9,12 +9,12 @@
#ifndef LLVM_LIBC_SRC_TERMIOS_TCGETATTR_H
#define LLVM_LIBC_SRC_TERMIOS_TCGETATTR_H
+#include "hdr/types/struct_termios.h"
#include "src/__support/macros/config.h"
-#include <termios.h>
namespace LIBC_NAMESPACE_DECL {
-int tcgetattr(int fd, struct termios *t);
+int tcgetattr(int fd, termios *t);
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/termios/tcsetattr.h b/libc/src/termios/tcsetattr.h
index 05c88f104836f..28a75b883e0f3 100644
--- a/libc/src/termios/tcsetattr.h
+++ b/libc/src/termios/tcsetattr.h
@@ -9,12 +9,12 @@
#ifndef LLVM_LIBC_SRC_TERMIOS_TCSETATTR_H
#define LLVM_LIBC_SRC_TERMIOS_TCSETATTR_H
+#include "hdr/types/struct_termios.h"
#include "src/__support/macros/config.h"
-#include <termios.h>
namespace LIBC_NAMESPACE_DECL {
-int tcsetattr(int fd, int actions, const struct termios *t);
+int tcsetattr(int fd, int actions, const termios *t);
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/test/src/termios/termios_test.cpp b/libc/test/src/termios/termios_test.cpp
index 91ec1294be3ad..ac484e6874b0f 100644
--- a/libc/test/src/termios/termios_test.cpp
+++ b/libc/test/src/termios/termios_test.cpp
@@ -35,7 +35,7 @@ using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher;
// from ninja/make which change the terminal behavior.
TEST_F(LlvmLibcTermiosTest, SpeedSmokeTest) {
- struct termios t;
+ termios t;
ASSERT_THAT(LIBC_NAMESPACE::cfsetispeed(&t, B50), Succeeds(0));
ASSERT_EQ(LIBC_NAMESPACE::cfgetispeed(&t), speed_t(B50));
ASSERT_THAT(LIBC_NAMESPACE::cfsetospeed(&t, B75), Succeeds(0));
@@ -46,7 +46,7 @@ TEST_F(LlvmLibcTermiosTest, SpeedSmokeTest) {
}
TEST_F(LlvmLibcTermiosTest, GetAttrSmokeTest) {
- struct termios t;
+ termios t;
int fd = LIBC_NAMESPACE::open("/dev/tty", O_RDONLY);
if (fd < 0) {
// When /dev/tty is not available, no point continuing
@@ -70,3 +70,39 @@ TEST_F(LlvmLibcTermiosTest, TcGetSidSmokeTest) {
returns(GT(pid_t(0))).with_errno(EQ(0)));
ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));
}
+
+TEST_F(LlvmLibcTermiosTest, SplitSpeedTest) {
+ int fd = LIBC_NAMESPACE::open("/dev/ptmx", O_RDWR);
+ if (fd < 0) {
+ // Gracefully skip if /dev/ptmx is not available
+ libc_errno = 0;
+ return;
+ }
+ ASSERT_ERRNO_SUCCESS();
+
+ termios t;
+ ASSERT_THAT(LIBC_NAMESPACE::tcgetattr(fd, &t), Succeeds(0));
+
+ // 1. Test setting split speeds.
+ ASSERT_THAT(LIBC_NAMESPACE::cfsetispeed(&t, B50), Succeeds(0));
+ ASSERT_THAT(LIBC_NAMESPACE::cfsetospeed(&t, B75), Succeeds(0));
+ ASSERT_THAT(LIBC_NAMESPACE::tcsetattr(fd, TCSANOW, &t), Succeeds(0));
+
+ termios t2;
+ ASSERT_THAT(LIBC_NAMESPACE::tcgetattr(fd, &t2), Succeeds(0));
+ ASSERT_EQ(LIBC_NAMESPACE::cfgetispeed(&t2), speed_t(B50));
+ ASSERT_EQ(LIBC_NAMESPACE::cfgetospeed(&t2), speed_t(B75));
+
+ // 2. Test input speed 0 fallback.
+ ASSERT_THAT(LIBC_NAMESPACE::cfsetispeed(&t2, 0), Succeeds(0));
+ ASSERT_THAT(LIBC_NAMESPACE::tcsetattr(fd, TCSANOW, &t2), Succeeds(0));
+
+ termios t3;
+ ASSERT_THAT(LIBC_NAMESPACE::tcgetattr(fd, &t3), Succeeds(0));
+ ASSERT_EQ(LIBC_NAMESPACE::cfgetospeed(&t3), speed_t(B75));
+ // Under POSIX, if input speed was set to 0, it must be the same as output
+ // speed.
+ ASSERT_EQ(LIBC_NAMESPACE::cfgetispeed(&t3), speed_t(B75));
+
+ ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));
+}
>From a36684f0b929e90b99db30a1f614338081deda03 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Tue, 21 Jul 2026 18:02:06 +0000
Subject: [PATCH 3/6] Remove unused <termios.h> include and dependency.
---
libc/src/termios/linux/CMakeLists.txt | 12 ------------
libc/src/termios/linux/tcdrain.cpp | 1 -
libc/src/termios/tcdrain.h | 1 -
libc/src/termios/tcflow.h | 1 -
libc/src/termios/tcflush.h | 1 -
libc/src/termios/tcgetsid.h | 2 +-
libc/src/termios/tcsendbreak.h | 1 -
7 files changed, 1 insertion(+), 18 deletions(-)
diff --git a/libc/src/termios/linux/CMakeLists.txt b/libc/src/termios/linux/CMakeLists.txt
index ef2c115cb8ea0..86565cf1294c7 100644
--- a/libc/src/termios/linux/CMakeLists.txt
+++ b/libc/src/termios/linux/CMakeLists.txt
@@ -19,7 +19,6 @@ add_entrypoint_object(
HDRS
../cfgetispeed.h
DEPENDS
- libc.include.termios
libc.hdr.types.speed_t
libc.hdr.types.struct_termios
libc.src.__support.macros.null_check
@@ -33,7 +32,6 @@ add_entrypoint_object(
../cfsetispeed.h
DEPENDS
.speed_utils
- libc.include.termios
libc.hdr.types.speed_t
libc.hdr.types.struct_termios
libc.src.errno.errno
@@ -47,7 +45,6 @@ add_entrypoint_object(
HDRS
../cfgetospeed.h
DEPENDS
- libc.include.termios
libc.hdr.types.speed_t
libc.hdr.types.struct_termios
libc.src.__support.macros.null_check
@@ -61,7 +58,6 @@ add_entrypoint_object(
../cfsetospeed.h
DEPENDS
.speed_utils
- libc.include.termios
libc.hdr.types.speed_t
libc.hdr.types.struct_termios
libc.src.errno.errno
@@ -75,7 +71,6 @@ add_entrypoint_object(
HDRS
../tcgetsid.h
DEPENDS
- libc.include.termios
libc.hdr.types.pid_t
libc.src.__support.OSUtil.linux.syscall_wrappers.ioctl
libc.src.errno.errno
@@ -88,8 +83,6 @@ add_entrypoint_object(
HDRS
../tcdrain.h
DEPENDS
- libc.include.termios
- libc.hdr.types.struct_termios
libc.src.__support.OSUtil.linux.syscall_wrappers.ioctl
libc.src.errno.errno
)
@@ -101,7 +94,6 @@ add_entrypoint_object(
HDRS
../tcflush.h
DEPENDS
- libc.include.termios
libc.hdr.termios_macros
libc.src.__support.OSUtil.linux.syscall_wrappers.ioctl
libc.src.errno.errno
@@ -114,7 +106,6 @@ add_entrypoint_object(
HDRS
../tcflow.h
DEPENDS
- libc.include.termios
libc.hdr.termios_macros
libc.src.__support.OSUtil.linux.syscall_wrappers.ioctl
libc.src.errno.errno
@@ -127,7 +118,6 @@ add_entrypoint_object(
HDRS
../tcsendbreak.h
DEPENDS
- libc.include.termios
libc.src.__support.OSUtil.linux.syscall_wrappers.ioctl
libc.src.errno.errno
)
@@ -150,7 +140,6 @@ add_entrypoint_object(
DEPENDS
.kernel_termios
.speed_utils
- libc.include.termios
libc.hdr.termios_macros
libc.hdr.types.struct_termios
libc.src.__support.OSUtil.linux.syscall_wrappers.ioctl
@@ -167,7 +156,6 @@ add_entrypoint_object(
DEPENDS
.kernel_termios
.speed_utils
- libc.include.termios
libc.hdr.termios_macros
libc.hdr.types.struct_termios
libc.src.__support.OSUtil.linux.syscall_wrappers.ioctl
diff --git a/libc/src/termios/linux/tcdrain.cpp b/libc/src/termios/linux/tcdrain.cpp
index fa2f5a1ed91ca..ee4abd0f2d8a2 100644
--- a/libc/src/termios/linux/tcdrain.cpp
+++ b/libc/src/termios/linux/tcdrain.cpp
@@ -13,7 +13,6 @@
#include "src/termios/tcdrain.h"
-#include "hdr/types/struct_termios.h"
#include "src/__support/OSUtil/linux/syscall_wrappers/ioctl.h"
#include "src/__support/common.h"
#include "src/__support/libc_errno.h"
diff --git a/libc/src/termios/tcdrain.h b/libc/src/termios/tcdrain.h
index f7fcd8c734bfa..73a45b3f01076 100644
--- a/libc/src/termios/tcdrain.h
+++ b/libc/src/termios/tcdrain.h
@@ -10,7 +10,6 @@
#define LLVM_LIBC_SRC_TERMIOS_TCDRAIN_H
#include "src/__support/macros/config.h"
-#include <termios.h>
namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/src/termios/tcflow.h b/libc/src/termios/tcflow.h
index dbe63adea1ceb..4b101b1ed1696 100644
--- a/libc/src/termios/tcflow.h
+++ b/libc/src/termios/tcflow.h
@@ -10,7 +10,6 @@
#define LLVM_LIBC_SRC_TERMIOS_TCFLOW_H
#include "src/__support/macros/config.h"
-#include <termios.h>
namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/src/termios/tcflush.h b/libc/src/termios/tcflush.h
index 5c283a0203c89..7f92b9ab1a6d1 100644
--- a/libc/src/termios/tcflush.h
+++ b/libc/src/termios/tcflush.h
@@ -10,7 +10,6 @@
#define LLVM_LIBC_SRC_TERMIOS_TCFLUSH_H
#include "src/__support/macros/config.h"
-#include <termios.h>
namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/src/termios/tcgetsid.h b/libc/src/termios/tcgetsid.h
index a69db00a5dab0..0d8de57668ae4 100644
--- a/libc/src/termios/tcgetsid.h
+++ b/libc/src/termios/tcgetsid.h
@@ -9,8 +9,8 @@
#ifndef LLVM_LIBC_SRC_TERMIOS_TCGETSID_H
#define LLVM_LIBC_SRC_TERMIOS_TCGETSID_H
+#include "hdr/types/pid_t.h"
#include "src/__support/macros/config.h"
-#include <termios.h>
namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/src/termios/tcsendbreak.h b/libc/src/termios/tcsendbreak.h
index 9edc602cff6c5..bbf540e89e9ab 100644
--- a/libc/src/termios/tcsendbreak.h
+++ b/libc/src/termios/tcsendbreak.h
@@ -10,7 +10,6 @@
#define LLVM_LIBC_SRC_TERMIOS_TCSENDBREAK_H
#include "src/__support/macros/config.h"
-#include <termios.h>
namespace LIBC_NAMESPACE_DECL {
>From 068213980a48f33498658edab75aefd595a3f560 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Tue, 21 Jul 2026 21:15:48 +0000
Subject: [PATCH 4/6] Fix missing include paths and termios macro header.
---
libc/CMakeLists.txt | 3 +++
libc/cmake/modules/LLVMLibCCompileOptionRules.cmake | 12 +++++++-----
libc/include/llvm-libc-types/CMakeLists.txt | 2 +-
libc/include/llvm-libc-types/struct_termios.h | 1 +
4 files changed, 12 insertions(+), 6 deletions(-)
diff --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt
index af820ba6ab6c0..e7d012ecdeeb3 100644
--- a/libc/CMakeLists.txt
+++ b/libc/CMakeLists.txt
@@ -162,6 +162,9 @@ option(LIBC_CONFIG_PATH "The path to user provided folder that configures the bu
if(LIBC_TARGET_OS_IS_LINUX)
set(kernel_headers "/usr/include")
+ if(CMAKE_LIBRARY_ARCHITECTURE AND EXISTS "/usr/include/${CMAKE_LIBRARY_ARCHITECTURE}")
+ list(APPEND kernel_headers "/usr/include/${CMAKE_LIBRARY_ARCHITECTURE}")
+ endif()
endif()
set(LIBC_KERNEL_HEADERS "${kernel_headers}" CACHE STRING "Path to Linux kernel headers")
diff --git a/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake b/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake
index c97f906cb663b..600df74f552b0 100644
--- a/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake
+++ b/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake
@@ -243,11 +243,13 @@ function(_get_common_compile_options output_var flags)
(LIBC_CC_SUPPORTS_NOSTDLIBINC OR COMPILER_RESOURCE_DIR))
# We use -idirafter to avoid preempting libc's own headers in case the
# directory (e.g. /usr/include) contains other headers.
- if(CMAKE_CROSSCOMPILING)
- list(APPEND compile_options "-idirafter=${LIBC_KERNEL_HEADERS}")
- else()
- list(APPEND compile_options "-idirafter${LIBC_KERNEL_HEADERS}")
- endif()
+ foreach(path IN LISTS LIBC_KERNEL_HEADERS)
+ if(CMAKE_CROSSCOMPILING)
+ list(APPEND compile_options "-idirafter=${path}")
+ else()
+ list(APPEND compile_options "-idirafter${path}")
+ endif()
+ endforeach()
endif()
endif()
diff --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt
index 3cb64260aaa6c..1d5db0be56099 100644
--- a/libc/include/llvm-libc-types/CMakeLists.txt
+++ b/libc/include/llvm-libc-types/CMakeLists.txt
@@ -189,7 +189,7 @@ add_header(tss_dtor_t HDR tss_dtor_t.h)
add_header(__atexithandler_t HDR __atexithandler_t.h)
add_header(speed_t HDR speed_t.h)
add_header(tcflag_t HDR tcflag_t.h)
-add_header(struct_termios HDR struct_termios.h DEPENDS .cc_t .speed_t .tcflag_t)
+add_header(struct_termios HDR struct_termios.h DEPENDS .cc_t .speed_t .tcflag_t libc.include.llvm-libc-macros.termios_macros)
add_header(struct_winsize HDR struct_winsize.h)
add_header(__getoptargv_t HDR __getoptargv_t.h)
add_header(wchar_t HDR wchar_t.h)
diff --git a/libc/include/llvm-libc-types/struct_termios.h b/libc/include/llvm-libc-types/struct_termios.h
index e3c5f2809e439..800232069fcea 100644
--- a/libc/include/llvm-libc-types/struct_termios.h
+++ b/libc/include/llvm-libc-types/struct_termios.h
@@ -12,6 +12,7 @@
#include "cc_t.h"
#include "speed_t.h"
#include "tcflag_t.h"
+#include "../llvm-libc-macros/termios-macros.h"
struct termios {
tcflag_t c_iflag; // Input mode flags
>From 78ba517b962af4728991c9a3becfb6aacdb10e02 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Tue, 21 Jul 2026 21:23:55 +0000
Subject: [PATCH 5/6] Run clang-format.
---
libc/include/llvm-libc-types/struct_termios.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libc/include/llvm-libc-types/struct_termios.h b/libc/include/llvm-libc-types/struct_termios.h
index 800232069fcea..9fc820d0b1ccb 100644
--- a/libc/include/llvm-libc-types/struct_termios.h
+++ b/libc/include/llvm-libc-types/struct_termios.h
@@ -9,10 +9,10 @@
#ifndef __LLVM_LIBC_TYPES_STRUCT_TERMIOS_H__
#define __LLVM_LIBC_TYPES_STRUCT_TERMIOS_H__
+#include "../llvm-libc-macros/termios-macros.h"
#include "cc_t.h"
#include "speed_t.h"
#include "tcflag_t.h"
-#include "../llvm-libc-macros/termios-macros.h"
struct termios {
tcflag_t c_iflag; // Input mode flags
>From 167022ca1c5b9ca67da4f6860d722b5631e7241f Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Thu, 23 Jul 2026 21:46:17 +0000
Subject: [PATCH 6/6] Address comments.
---
libc/src/termios/linux/cfsetispeed.cpp | 1 -
libc/src/termios/linux/speed_utils.h | 4 +++-
libc/test/src/termios/termios_test.cpp | 6 ++++++
3 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/libc/src/termios/linux/cfsetispeed.cpp b/libc/src/termios/linux/cfsetispeed.cpp
index 0b9b6e440bc8c..d953e25427d98 100644
--- a/libc/src/termios/linux/cfsetispeed.cpp
+++ b/libc/src/termios/linux/cfsetispeed.cpp
@@ -30,7 +30,6 @@ LLVM_LIBC_FUNCTION(int, cfsetispeed, (termios * t, speed_t speed)) {
return -1;
}
- t->c_cflag = (t->c_cflag & NOT_SPEED_MASK) | encoded;
t->c_ispeed = speed;
return 0;
}
diff --git a/libc/src/termios/linux/speed_utils.h b/libc/src/termios/linux/speed_utils.h
index cc0d76e2cc3b5..5b731a00825ef 100644
--- a/libc/src/termios/linux/speed_utils.h
+++ b/libc/src/termios/linux/speed_utils.h
@@ -20,6 +20,8 @@
namespace LIBC_NAMESPACE_DECL {
+constexpr speed_t INVALID_SPEED = ~static_cast<speed_t>(0);
+
// glibc 2.42 changed the behavior of the termios Bxxx constants:
// - Before glibc 2.42, the Bxxx constants correspond to the kernel speed
// bitmasks
@@ -104,7 +106,7 @@ LIBC_INLINE constexpr speed_t encode_speed(speed_t speed) {
case 4000000:
return 0010017;
default:
- return speed;
+ return INVALID_SPEED;
}
}
diff --git a/libc/test/src/termios/termios_test.cpp b/libc/test/src/termios/termios_test.cpp
index ac484e6874b0f..1af2953b1a8ef 100644
--- a/libc/test/src/termios/termios_test.cpp
+++ b/libc/test/src/termios/termios_test.cpp
@@ -43,6 +43,12 @@ TEST_F(LlvmLibcTermiosTest, SpeedSmokeTest) {
ASSERT_THAT(LIBC_NAMESPACE::cfsetispeed(&t, ~CBAUD), Fails(EINVAL));
ASSERT_THAT(LIBC_NAMESPACE::cfsetospeed(&t, ~CBAUD), Fails(EINVAL));
+ ASSERT_THAT(LIBC_NAMESPACE::cfsetispeed(&t, 4096), Fails(EINVAL));
+ ASSERT_THAT(LIBC_NAMESPACE::cfsetospeed(&t, 4096), Fails(EINVAL));
+#if B50 != 1
+ ASSERT_THAT(LIBC_NAMESPACE::cfsetispeed(&t, 1), Fails(EINVAL));
+ ASSERT_THAT(LIBC_NAMESPACE::cfsetospeed(&t, 1), Fails(EINVAL));
+#endif
}
TEST_F(LlvmLibcTermiosTest, GetAttrSmokeTest) {
More information about the libc-commits
mailing list