1 /*
2 * Check printing of character/block device numbers in -yy mode.
3 *
4 * Copyright (c) 2018-2021 The strace developers.
5 * All rights reserved.
6 *
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 */
9
10 #include "tests.h"
11
12 #include <stdio.h>
13 #include <unistd.h>
14
15 #include "scno.h"
16
17 #include <linux/fcntl.h>
18
19 #include <sys/sysmacros.h>
20
21 #ifndef PRINT_PATH
22 # define PRINT_PATH 1
23 #endif
24
25 #ifndef PRINT_DEVNUM
26 # if PRINT_PATH
27 # define PRINT_DEVNUM 1
28 # else
29 # define PRINT_DEVNUM 0
30 # endif
31 #endif
32
33 #ifndef PRINT_AT_FDCWD_PATH
34 # define PRINT_AT_FDCWD_PATH PRINT_DEVNUM
35 #endif
36
37 #if PRINT_DEVNUM
38 # define DEV_FMT "<%s<%s %u:%u>>"
39 #elif PRINT_PATH
40 # define DEV_FMT "<%s>"
41 #else
42 # define DEV_FMT ""
43 #endif
44
45 #if defined __NR_openat && defined O_PATH
46
47 int
48 main(void)
49 {
50 skip_if_unavailable("/proc/self/fd/");
51 # if PRINT_AT_FDCWD_PATH
52 char *cwd = get_fd_path(get_dir_fd("."));
53 # endif
54
55 static const struct {
56 const char *path;
57 unsigned int major;
58 unsigned int minor;
59 bool blk;
60 bool optional;
61 } checks[] = {
62 { "/dev/zero", 1, 5, false, false },
63 { "/dev/full", 1, 7, false, false },
64 { "/dev/sda", 8, 0, true, true },
65 };
66
67 for (unsigned int i = 0; i < ARRAY_SIZE(checks); i++) {
68 /*
69 * We can't have nice things here and call openat() directly as
70 * some libcs (yes, musl, I'm looking at you now) are too
71 * frivolous in passing flags to the kernel.
72 */
73 long fd = syscall(__NR_openat, AT_FDCWD, checks[i].path,
74 O_RDONLY|O_PATH);
75
76 printf("openat(AT_FDCWD"
77 # if PRINT_AT_FDCWD_PATH
78 "<%s>"
79 # endif
80 ", \"%s\", O_RDONLY|O_PATH) = %s",
81 # if PRINT_AT_FDCWD_PATH
82 cwd,
83 # endif
84 checks[i].path, sprintrc(fd));
85 # if PRINT_PATH
86 if (fd >= 0)
87 printf(DEV_FMT,
88 checks[i].path
89 # if PRINT_DEVNUM
90 , checks[i].blk ? "block" : "char",
91 checks[i].major, checks[i].minor
92 # endif
93 );
94 # endif
95 puts("");
96
97 if (fd < 0) {
98 if (checks[i].optional)
99 continue;
100 else
101 perror_msg_and_fail("openat(\"%s\")",
102 checks[i].path);
103 }
104
105 int rc = fsync(fd);
106
107 printf("fsync(%ld" DEV_FMT ") = %s\n",
108 fd,
109 # if PRINT_PATH
110 checks[i].path,
111 # if PRINT_DEVNUM
112 checks[i].blk ? "block" : "char",
113 checks[i].major, checks[i].minor,
114 # endif
115 # endif
116 sprintrc(rc));
117
118 close(fd);
119 }
120
121 puts("+++ exited with 0 +++");
122 return 0;
123 }
124
125 #else
126
127 SKIP_MAIN_UNDEFINED("__NR_openat && O_PATH")
128
129 #endif