1 /*
2 * Check decoding of ioctl TIOCM* commands.
3 *
4 * Copyright (c) 2020-2022 The strace developers.
5 * All rights reserved.
6 *
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 */
9
10 #include "tests.h"
11 #include <errno.h>
12 #include <stdio.h>
13 #include <sys/ioctl.h>
14
15 static const char *errstr;
16
17 static int
18 do_ioctl(kernel_ulong_t cmd, kernel_ulong_t arg)
19 {
20 int rc = ioctl(-1, cmd, arg);
21 errstr = sprintrc(rc);
22 return rc;
23 }
24
25 static int
26 do_ioctl_ptr(kernel_ulong_t cmd, const void *arg)
27 {
28 return do_ioctl(cmd, (uintptr_t) arg);
29 }
30
31 int
32 main(int argc, const char *argv[])
33 {
34 static const struct {
35 uint32_t cmd;
36 const char *str;
37 bool on_enter;
38 bool on_exit;
39 } cmds[] = {
40 { ARG_STR(TIOCMGET), false, true },
41 { ARG_STR(TIOCMBIS), true, false },
42 { ARG_STR(TIOCMBIC), true, false },
43 { ARG_STR(TIOCMSET), true, false },
44 };
45
46 TAIL_ALLOC_OBJECT_CONST_PTR(unsigned int, p_flags);
47 const void *const efault = p_flags + 1;
48
49 for (size_t i = 0; i < ARRAY_SIZE(cmds); ++i) {
50 do_ioctl(cmds[i].cmd, 0);
51 printf("ioctl(-1, " XLAT_FMT ", NULL) = %s\n",
52 XLAT_SEL(cmds[i].cmd, cmds[i].str), errstr);
53
54 do_ioctl_ptr(cmds[i].cmd, efault);
55 printf("ioctl(-1, " XLAT_FMT ", %p) = %s\n",
56 XLAT_SEL(cmds[i].cmd, cmds[i].str),
57 efault, errstr);
58
59 #ifdef __mips__
60 # define VALID_FLAGS 0xe777
61 # define INVALID_FLAGS 0xffff1888
62 #else
63 # define VALID_FLAGS 0xe1ff
64 # define INVALID_FLAGS 0xffff1e00
65 #endif
66 *p_flags = INVALID_FLAGS;
67
68 if (cmds[i].on_enter) {
69 do_ioctl_ptr(cmds[i].cmd, p_flags);
70 printf("ioctl(-1, " XLAT_FMT ", [%s]) = %s\n",
71 XLAT_SEL(cmds[i].cmd, cmds[i].str),
72 XLAT_UNKNOWN(INVALID_FLAGS, "TIOCM_???"),
73 errstr);
74
75 *p_flags = ~*p_flags;
76 do_ioctl_ptr(cmds[i].cmd, p_flags);
77 printf("ioctl(-1, " XLAT_FMT ", [%s]) = %s\n",
78 XLAT_SEL(cmds[i].cmd, cmds[i].str),
79 XLAT_KNOWN(VALID_FLAGS,
80 "TIOCM_LE|"
81 "TIOCM_DTR|"
82 "TIOCM_RTS|"
83 "TIOCM_ST|"
84 "TIOCM_SR|"
85 "TIOCM_CTS|"
86 "TIOCM_CAR|"
87 "TIOCM_RNG|"
88 "TIOCM_DSR|"
89 "TIOCM_OUT1|"
90 "TIOCM_OUT2|"
91 "TIOCM_LOOP"),
92 errstr);
93 } else if (cmds[i].on_exit) {
94 do_ioctl_ptr(cmds[i].cmd, p_flags);
95 printf("ioctl(-1, " XLAT_FMT ", %p) = %s\n",
96 XLAT_SEL(cmds[i].cmd, cmds[i].str),
97 p_flags, errstr);
98 }
99
100 }
101
102 puts("+++ exited with 0 +++");
103 return 0;
104 }