1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-08-05 19:35:52 +03:00

Linux: Keep termios ioctl constants strictly internal

Undefine TCGETS, TCGETS2, and related ioctl constants in the installed
headers.  Extract the correct constants (using the kernel type
definitions) automatically from the UAPI headers.  The kernel
constants are available under KERNEL_* names during the glibc build,
computed using assembler constant extraction mechanism.

Alpha may have to use TCGETS instead of TCGETS2 because TCTGETS2
became available in Linux 4.20 only.  Introduce ARCH_TCGETS to make
this choice explict.

To support emulation on powerpc, glibc versions of the termios
constants are added to the emulation code in internal-ioctl.h.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
This commit is contained in:
Florian Weimer
2025-07-11 16:04:07 +02:00
parent 02e7ac5ee3
commit 3d3572f590
18 changed files with 116 additions and 260 deletions

5
NEWS
View File

@@ -42,6 +42,11 @@ Deprecated and removed features, and other changes affecting compatibility:
obsolete since the very first version of POSIX.1 in 1988, replaced obsolete since the very first version of POSIX.1 in 1988, replaced
with <termios.h>. with <termios.h>.
* On Linux, the ioctl constants TCGETS, TCSETS, TCSETSF, TCSETSW,
TCGETS2, TCSETS2, TCSETSF2, TCSETSW2 are no longer defined in
<sys/ioctl.h>. Applications must use the high-level <termios.h>
interfaces instead.
* The support for TX lock elision of pthread mutexes is deprecated on * The support for TX lock elision of pthread mutexes is deprecated on
all architectures and will be removed in the next release. all architectures and will be removed in the next release.

View File

@@ -425,6 +425,8 @@ sysdep_headers += \
bits/termios-tcflow.h \ bits/termios-tcflow.h \
# sysdep_headers # sysdep_headers
gen-as-const-headers += termios-kernel-consts.sym
tests += \ tests += \
tst-termios-linux \ tst-termios-linux \
# tests # tests

View File

@@ -1,36 +0,0 @@
/* Copyright (C) 1996-2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library. If not, see
<https://www.gnu.org/licenses/>. */
#ifndef _SYS_IOCTL_H
# error "Never use <bits/ioctls.h> directly; include <sys/ioctl.h> instead."
#endif
/* Use the definitions from the kernel header files. */
#include <asm/ioctls.h>
/* Oh well, this is necessary since the kernel data structure is
different from the user-level version. */
#undef TCGETS
#undef TCSETS
#undef TCSETSW
#undef TCSETSF
#define TCGETS _IOR ('t', 19, char[44])
#define TCSETS _IOW ('t', 20, char[44])
#define TCSETSW _IOW ('t', 21, char[44])
#define TCSETSF _IOW ('t', 22, char[44])
#include <linux/sockios.h>

View File

@@ -1,26 +0,0 @@
/* Architectural parameters for Linux termios - Alpha/PowerPC version
Copyright (C) 1997-2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#ifndef TERMIOS_INTERNALS_H
# error "<termios_arch.h> should only be included from <termios_internals.h>"
#endif
#define _TERMIOS2_NCCS 19
#define _HAVE_TERMIOS2_C_CC_BEFORE_C_LINE 1
#define _HAVE_STRUCT_OLD_TERMIOS 0

View File

@@ -22,4 +22,18 @@
/* Use the definitions from the kernel header files. */ /* Use the definitions from the kernel header files. */
#include <asm/ioctls.h> #include <asm/ioctls.h>
/* The GNU C library has a different definition of struct termios,
incompatible with what the ioctl interface expects. The existence
of the termios2 ioctls is considered an implementation detail.
Undefine all related ioctl constants. */
#undef TCGETS
#undef TCSETS
#undef TCSETSF
#undef TCSETSW
#undef TCGETS2
#undef TCSETS2
#undef TCSETSF2
#undef TCSETSW2
#include <linux/sockios.h> #include <linux/sockios.h>

View File

@@ -1,36 +0,0 @@
/* Copyright (C) 1996-2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library. If not, see
<https://www.gnu.org/licenses/>. */
#ifndef _SYS_IOCTL_H
# error "Never use <bits/ioctls.h> directly; include <sys/ioctl.h> instead."
#endif
/* Use the definitions from the kernel header files. */
#include <asm/ioctls.h>
/* Oh well, this is necessary since the kernel data structure is
different from the user-level version. */
#undef TCGETS
#undef TCSETS
#undef TCSETSW
#undef TCSETSF
#define TCGETS _IOR ('T', 16, char[36])
#define TCSETS _IOW ('T', 17, char[36])
#define TCSETSW _IOW ('T', 18, char[36])
#define TCSETSF _IOW ('T', 19, char[36])
#include <linux/sockios.h>

View File

@@ -24,6 +24,6 @@ int
__isatty (int fd) __isatty (int fd)
{ {
struct termios2 k_termios; struct termios2 k_termios;
return INLINE_SYSCALL_CALL (ioctl, fd, TCGETS2, &k_termios) == 0; return INLINE_SYSCALL_CALL (ioctl, fd, ARCH_TCGETS, &k_termios) == 0;
} }
weak_alias (__isatty, isatty) weak_alias (__isatty, isatty)

View File

@@ -22,5 +22,5 @@ int
__isatty_nostatus (int fd) __isatty_nostatus (int fd)
{ {
struct termios2 k_termios; struct termios2 k_termios;
return INTERNAL_SYSCALL_CALL (ioctl, fd, TCGETS2, &k_termios) == 0; return INTERNAL_SYSCALL_CALL (ioctl, fd, ARCH_TCGETS, &k_termios) == 0;
} }

View File

@@ -1,6 +1,6 @@
/* Architectural parameters for Linux termios - MIPS version /* old_termios.h for MIPS.
Copyright (C) 1991-2025 Free Software Foundation, Inc. Copyright (C) 2025 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or The GNU C Library is free software; you can redistribute it and/or
@@ -17,18 +17,15 @@
License along with the GNU C Library; if not, see License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */ <https://www.gnu.org/licenses/>. */
#define _TERMIOS2_NCCS 23
#define _HAVE_TERMIOS2_C_CC_BEFORE_C_LINE 0
#define _HAVE_STRUCT_OLD_TERMIOS 1 #define _HAVE_STRUCT_OLD_TERMIOS 1
#define OLD_NCCS 32 #define OLD_NCCS 32
struct old_termios typedef struct old_termios
{ {
tcflag_t c_iflag; /* input mode flags */ tcflag_t c_iflag; /* input mode flags */
tcflag_t c_oflag; /* output mode flags */ tcflag_t c_oflag; /* output mode flags */
tcflag_t c_cflag; /* control mode flags */ tcflag_t c_cflag; /* control mode flags */
tcflag_t c_lflag; /* local mode flags */ tcflag_t c_lflag; /* local mode flags */
cc_t c_line; /* line discipline */ cc_t c_line; /* line discipline */
cc_t c_cc[OLD_NCCS]; /* control characters */ cc_t c_cc[OLD_NCCS]; /* control characters */
}; } old_termios_t;

View File

@@ -1,4 +1,4 @@
/* Linux internal definitions for ioctl. /* Linux internal definitions for ioctl. powerpc version.
Copyright (C) 2021-2025 Free Software Foundation, Inc. Copyright (C) 2021-2025 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
@@ -17,27 +17,40 @@
<https://www.gnu.org/licenses/>. */ <https://www.gnu.org/licenses/>. */
#include <termios.h> #include <termios.h>
#include <termios_internals.h>
#include <assert.h>
/* PowerPC quirk: on PowerPC only, ioctl() emulates the TCGETS/TCSETS*
ioctls with tcgetattr/tcsetattr using the glibc struct termios.
As struct termios2 is the same as the kernel struct termios on PowerPC,
simply consider the kernel ones as the termios2 interface, even
though the kernel doesn't call it that. */
#define GLIBC_TCGETS _IOR ('t', 19, struct termios)
#define GLIBC_TCSETS _IOW ('t', 20, struct termios)
#define GLIBC_TCSETSW _IOW ('t', 21, struct termios)
#define GLIBC_TCSETSF _IOW ('t', 22, struct termios)
/* The user-visible size of struct termios has changed. Catch ioctl calls
using the new-style struct termios, and translate them to old-style. */
static inline bool static inline bool
__ioctl_arch (int *r, int fd, unsigned long request, void *arg) __ioctl_arch (int *r, int fd, unsigned long request, void *arg)
{ {
static_assert (GLIBC_TCGETS != KERNEL_TCGETS2,
"emulation not possible due to matching ioctl constants");
switch (request) switch (request)
{ {
case TCGETS: case GLIBC_TCGETS:
*r = __tcgetattr (fd, (struct termios *) arg); *r = __tcgetattr (fd, (struct termios *) arg);
break; break;
case TCSETS: case GLIBC_TCSETS:
*r = __tcsetattr (fd, TCSANOW, (struct termios *) arg); *r = __tcsetattr (fd, TCSANOW, (struct termios *) arg);
break; break;
case TCSETSW: case GLIBC_TCSETSW:
*r = __tcsetattr (fd, TCSADRAIN, (struct termios *) arg); *r = __tcsetattr (fd, TCSADRAIN, (struct termios *) arg);
break; break;
case TCSETSF: case GLIBC_TCSETSF:
*r = __tcsetattr (fd, TCSAFLUSH, (struct termios *) arg); *r = __tcsetattr (fd, TCSAFLUSH, (struct termios *) arg);
break; break;

View File

@@ -1,33 +0,0 @@
/* Architectural parameters for Linux termios - PowerPC version
Copyright (C) 1997-2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#define _TERMIOS2_NCCS 19
#define _HAVE_TERMIOS2_C_CC_BEFORE_C_LINE 1
#define _HAVE_STRUCT_OLD_TERMIOS 0
/* PowerPC quirk: on PowerPC only, ioctl() emulates the TCGETS/TCSETS*
ioctls with tcgetattr/tcsetattr using the glibc struct termios.
As struct termios2 is the same as the kernel struct termios on PowerPC,
simply consider the kernel ones as the termios2 interface, even
though the kernel doesn't call it that. */
#define TCGETS2 _IOR ('t', 19, struct termios2)
#define TCSETS2 _IOW ('t', 20, struct termios2)
#define TCSETSW2 _IOW ('t', 21, struct termios2)
#define TCSETSF2 _IOW ('t', 22, struct termios2)

View File

@@ -1,36 +0,0 @@
/* Copyright (C) 1996-2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#ifndef _SYS_IOCTL_H
# error "Never use <bits/ioctls.h> directly; include <sys/ioctl.h> instead."
#endif
/* Use the definitions from the kernel header files. */
#include <asm/ioctls.h>
/* Oh well, this is necessary since the kernel data structure is
different from the user-level version. */
#undef TCGETS
#undef TCSETS
#undef TCSETSW
#undef TCSETSF
#define TCGETS _IOR ('T', 8, char[36])
#define TCSETS _IOW ('T', 9, char[36])
#define TCSETSW _IOW ('T', 10, char[36])
#define TCSETSF _IOW ('T', 11, char[36])
#include <linux/sockios.h>

View File

@@ -1,6 +1,6 @@
/* Architectural parameters for Linux termios - SPARC version /* old_termios.h for SPARC.
Copyright (C) 1991-2025 Free Software Foundation, Inc. Copyright (C) 2025 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or The GNU C Library is free software; you can redistribute it and/or
@@ -17,18 +17,15 @@
License along with the GNU C Library; if not, see License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */ <https://www.gnu.org/licenses/>. */
#define _TERMIOS2_NCCS 19
#define _HAVE_TERMIOS2_C_CC_BEFORE_C_LINE 0
#define _HAVE_STRUCT_OLD_TERMIOS 1 #define _HAVE_STRUCT_OLD_TERMIOS 1
#define OLD_NCCS 17 #define OLD_NCCS 17
struct old_termios typedef struct old_termios
{ {
tcflag_t c_iflag; /* input mode flags */ tcflag_t c_iflag; /* input mode flags */
tcflag_t c_oflag; /* output mode flags */ tcflag_t c_oflag; /* output mode flags */
tcflag_t c_cflag; /* control mode flags */ tcflag_t c_cflag; /* control mode flags */
tcflag_t c_lflag; /* local mode flags */ tcflag_t c_lflag; /* local mode flags */
cc_t c_line; /* line discipline */ cc_t c_line; /* line discipline */
cc_t c_cc[OLD_NCCS]; /* control characters */ cc_t c_cc[OLD_NCCS]; /* control characters */
}; } old_termios_t;

View File

@@ -22,7 +22,7 @@ int
__tcgetattr (int fd, struct termios *termios_p) __tcgetattr (int fd, struct termios *termios_p)
{ {
struct termios2 k_termios; struct termios2 k_termios;
long int retval = INLINE_SYSCALL_CALL (ioctl, fd, TCGETS2, &k_termios); long int retval = INLINE_SYSCALL_CALL (ioctl, fd, ARCH_TCGETS, &k_termios);
if (__glibc_likely (retval != -1)) if (__glibc_likely (retval != -1))
{ {

View File

@@ -19,6 +19,12 @@
#define static_assert_equal(x,y) _Static_assert ((x) == (y), #x " != " #y) #define static_assert_equal(x,y) _Static_assert ((x) == (y), #x " != " #y)
static_assert_equal (sizeof (struct termios2), KERNEL_TERMIOS2_SIZE);
static_assert_equal (offsetof (struct termios2, c_cc),
KERNEL_TERMIOS2_CC_OFFSET);
static_assert_equal (offsetof (struct termios2, c_line),
KERNEL_TERMIOS2_LINE_OFFSET);
/* Set the state of FD to *TERMIOS_P. */ /* Set the state of FD to *TERMIOS_P. */
int int
__tcsetattr (int fd, int optional_actions, const struct termios *termios_p) __tcsetattr (int fd, int optional_actions, const struct termios *termios_p)
@@ -53,10 +59,10 @@ __tcsetattr (int fd, int optional_actions, const struct termios *termios_p)
*/ */
static_assert_equal(TCSADRAIN, TCSANOW + 1); static_assert_equal(TCSADRAIN, TCSANOW + 1);
static_assert_equal(TCSAFLUSH, TCSANOW + 2); static_assert_equal(TCSAFLUSH, TCSANOW + 2);
static_assert_equal(TCSETSW2, TCSETS2 + 1); static_assert_equal(KERNEL_TCSETSW2, KERNEL_TCSETS2 + 1);
static_assert_equal(TCSETSF2, TCSETS2 + 2); static_assert_equal(KERNEL_TCSETSF2, KERNEL_TCSETS2 + 2);
static_assert_equal(TCSETSW, TCSETS + 1); static_assert_equal(KERNEL_TCSETSW, KERNEL_TCSETS + 1);
static_assert_equal(TCSETSF, TCSETS + 2); static_assert_equal(KERNEL_TCSETSF, KERNEL_TCSETS + 2);
cmd = (long)optional_actions - TCSANOW; cmd = (long)optional_actions - TCSANOW;
if (cmd > 2) if (cmd > 2)
@@ -66,11 +72,11 @@ __tcsetattr (int fd, int optional_actions, const struct termios *termios_p)
k_termios.c_ospeed != k_termios.c_ispeed || k_termios.c_ospeed != k_termios.c_ispeed ||
cbaud (k_termios.c_cflag) == __BOTHER) cbaud (k_termios.c_cflag) == __BOTHER)
{ {
cmd += TCSETS2; cmd += KERNEL_TCSETS2;
} }
else else
{ {
cmd += TCSETS; cmd += KERNEL_TCSETS;
k_termios.c_cflag &= ~CIBAUD; k_termios.c_cflag &= ~CIBAUD;
} }

View File

@@ -0,0 +1,26 @@
#include <linux/termios.h>
#include <stddef.h>
#ifdef TCGETS2
# define STRUCT_TERMIOS struct termios2
#else
# define TCGETS2 TCGETS
# define TCSETS2 TCSETS
# define TCSETSW2 TCSETSW
# define TCSETSF2 TCSETSF
# define STRUCT_TERMIOS struct termios
#endif
--
KERNEL_TCGETS TCGETS
KERNEL_TCSETS TCSETS
KERNEL_TCSETSF TCSETSF
KERNEL_TCSETSW TCSETSW
KERNEL_TCGETS2 TCGETS2
KERNEL_TCSETS2 TCSETS2
KERNEL_TCSETSF2 TCSETSF2
KERNEL_TCSETSW2 TCSETSW2
KERNEL_TERMIOS2_SIZE sizeof (STRUCT_TERMIOS)
KERNEL_TERMIOS2_CC_OFFSET offsetof (STRUCT_TERMIOS, c_cc)
KERNEL_TERMIOS2_LINE_OFFSET offsetof (STRUCT_TERMIOS, c_line)
_TERMIOS2_NCCS sizeof ((STRUCT_TERMIOS) { 0 }.c_cc) / sizeof (cc_t)

View File

@@ -1,23 +0,0 @@
/* Architectural parameters for Linux termios - generic version
Copyright (C) 1997-2025 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#define _TERMIOS2_NCCS 19
#define _HAVE_TERMIOS2_C_CC_BEFORE_C_LINE 0
#define _HAVE_STRUCT_OLD_TERMIOS 0

View File

@@ -30,7 +30,18 @@
#include <sysdep.h> #include <sysdep.h>
#include <shlib-compat.h> #include <shlib-compat.h>
#include <termios_arch.h> #include <termios-kernel-consts.h>
/* Alpha got termios2 late, but TCGETS has exactly the same structure
format and function as TCGETS2. On all other platforms, the termios2
interface exists as far back as this version of glibc supports.
For TCSETS* it is more complicated; this is handled in tcsetattr.c. */
#ifdef __ASSUME_TERMIOS2
# define ARCH_TCGETS KERNEL_TCGETS2
#else
# define ARCH_TCGETS KERNEL_TCGETS
#endif
/* ---- Kernel interface definitions ---- */ /* ---- Kernel interface definitions ---- */
@@ -44,7 +55,7 @@ struct termios2
tcflag_t c_oflag; /* output mode flags */ tcflag_t c_oflag; /* output mode flags */
tcflag_t c_cflag; /* control mode flags */ tcflag_t c_cflag; /* control mode flags */
tcflag_t c_lflag; /* local mode flags */ tcflag_t c_lflag; /* local mode flags */
#if _HAVE_TERMIOS2_C_CC_BEFORE_C_LINE #if KERNEL_TERMIOS2_CC_OFFSET < KERNEL_TERMIOS2_LINE_OFFSET
cc_t c_cc[_TERMIOS2_NCCS]; /* control characters */ cc_t c_cc[_TERMIOS2_NCCS]; /* control characters */
cc_t c_line; /* line discipline */ cc_t c_line; /* line discipline */
#else #else
@@ -55,26 +66,6 @@ struct termios2
speed_t c_ospeed; /* output speed */ speed_t c_ospeed; /* output speed */
}; };
/* Alpha got termios2 late, but TCGETS has exactly the same structure
format and function as TCGETS2. On all other platforms, the termios2
interface exists as far back as this version of glibc supports.
For TCSETS* it is more complicated; this is handled in tcsetattr.c.
Some other architectures only have the equivalent of the termios2
interface, in which case the old ioctl names are the only ones
presented, but are equivalent to the new ones. */
#ifndef TCGETS2
# define TCGETS2 TCGETS
# define TCSETS2 TCSETS
# define TCSETSW2 TCSETSW
# define TCSETSF2 TCSETSF
#elif !__ASSUME_TERMIOS2
/* Hack for Alpha */
# undef TCGETS2
# define TCGETS2 TCGETS
#endif
/* ---- Application interface definitions ---- */ /* ---- Application interface definitions ---- */
/* /*
@@ -91,12 +82,7 @@ struct termios2
* This only applies to SPARC and MIPS; for other architectures the * This only applies to SPARC and MIPS; for other architectures the
* new and old speed_t interfaces both use the same struct termios. * new and old speed_t interfaces both use the same struct termios.
*/ */
#if _HAVE_STRUCT_OLD_TERMIOS #include <old_termios.h>
typedef struct old_termios old_termios_t;
#else
# define OLD_NCCS NCCS
typedef struct termios old_termios_t;
#endif
/* ---- Internal function definitions ---- */ /* ---- Internal function definitions ---- */