1 | // SPDX-License-Identifier: GPL-2.0 |
2 | |
3 | #include <errno.h> |
4 | #include <stdbool.h> |
5 | #include <stdio.h> |
6 | #include <stdlib.h> |
7 | #include <string.h> |
8 | #include <sys/stat.h> |
9 | #include <unistd.h> |
10 | #include <linux/limits.h> |
11 | |
12 | #include "../kselftest.h" |
13 | |
14 | #define MIN_TTY_PATH_LEN 8 |
15 | |
16 | static bool tty_valid(char *tty) |
17 | { |
18 | if (strlen(tty) < MIN_TTY_PATH_LEN) |
19 | return false; |
20 | |
21 | if (strncmp(tty, "/dev/tty" , MIN_TTY_PATH_LEN) == 0 || |
22 | strncmp(tty, "/dev/pts" , MIN_TTY_PATH_LEN) == 0) |
23 | return true; |
24 | |
25 | return false; |
26 | } |
27 | |
28 | static int write_dev_tty(void) |
29 | { |
30 | FILE *f; |
31 | int r = 0; |
32 | |
33 | f = fopen("/dev/tty" , "r+" ); |
34 | if (!f) |
35 | return -errno; |
36 | |
37 | r = fprintf(f, "hello, world!\n" ); |
38 | if (r != strlen("hello, world!\n" )) |
39 | r = -EIO; |
40 | |
41 | fclose(f); |
42 | return r; |
43 | } |
44 | |
45 | int main(int argc, char **argv) |
46 | { |
47 | int r; |
48 | char tty[PATH_MAX] = {}; |
49 | struct stat st1, st2; |
50 | |
51 | ksft_print_header(); |
52 | ksft_set_plan(plan: 1); |
53 | |
54 | r = readlink("/proc/self/fd/0" , tty, PATH_MAX); |
55 | if (r < 0) |
56 | ksft_exit_fail_msg(msg: "readlink on /proc/self/fd/0 failed: %m\n" ); |
57 | |
58 | if (!tty_valid(tty)) |
59 | ksft_exit_skip(msg: "invalid tty path '%s'\n" , tty); |
60 | |
61 | r = stat(tty, &st1); |
62 | if (r < 0) |
63 | ksft_exit_fail_msg(msg: "stat failed on tty path '%s': %m\n" , tty); |
64 | |
65 | /* We need to wait at least 8 seconds in order to observe timestamp change */ |
66 | /* https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=fbf47635315ab308c9b58a1ea0906e711a9228de */ |
67 | sleep(10); |
68 | |
69 | r = write_dev_tty(); |
70 | if (r < 0) |
71 | ksft_exit_fail_msg(msg: "failed to write to /dev/tty: %s\n" , |
72 | strerror(-r)); |
73 | |
74 | r = stat(tty, &st2); |
75 | if (r < 0) |
76 | ksft_exit_fail_msg(msg: "stat failed on tty path '%s': %m\n" , tty); |
77 | |
78 | /* We wrote to the terminal so timestamps should have been updated */ |
79 | if (st1.st_atim.tv_sec == st2.st_atim.tv_sec && |
80 | st1.st_mtim.tv_sec == st2.st_mtim.tv_sec) { |
81 | ksft_test_result_fail(msg: "tty timestamps not updated\n" ); |
82 | ksft_exit_fail(); |
83 | } |
84 | |
85 | ksft_test_result_pass( |
86 | msg: "timestamps of terminal '%s' updated after write to /dev/tty\n" , tty); |
87 | return EXIT_SUCCESS; |
88 | } |
89 | |