]> granicus.if.org Git - strace/blob - dirent.c
tests: implement ioctl_evdev-success-v.test via ioctl_evdev-success.test
[strace] / dirent.c
1 /*
2  * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3  * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4  * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
5  * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
6  * Copyright (c) 2005-2015 Dmitry V. Levin <ldv@altlinux.org>
7  * Copyright (c) 2014-2018 The strace developers.
8  * All rights reserved.
9  *
10  * SPDX-License-Identifier: LGPL-2.1-or-later
11  */
12
13 #include "defs.h"
14
15 #include DEF_MPERS_TYPE(kernel_dirent)
16
17 #include MPERS_DEFS
18
19 #define D_NAME_LEN_MAX 256
20
21 static void
22 print_old_dirent(struct tcb *const tcp, const kernel_ulong_t addr)
23 {
24         kernel_dirent d;
25
26         if (umove_or_printaddr(tcp, addr, &d))
27                 return;
28
29         tprintf("{d_ino=%llu, d_off=%llu, d_reclen=%u, d_name=",
30                 zero_extend_signed_to_ull(d.d_ino),
31                 zero_extend_signed_to_ull(d.d_off), d.d_reclen);
32         if (d.d_reclen > D_NAME_LEN_MAX)
33                 d.d_reclen = D_NAME_LEN_MAX;
34         printpathn(tcp, addr + offsetof(kernel_dirent, d_name), d.d_reclen);
35         tprints("}");
36 }
37
38 SYS_FUNC(readdir)
39 {
40         if (entering(tcp)) {
41                 printfd(tcp, tcp->u_arg[0]);
42                 tprints(", ");
43         } else {
44                 if (tcp->u_rval == 0)
45                         printaddr(tcp->u_arg[1]);
46                 else
47                         print_old_dirent(tcp, tcp->u_arg[1]);
48                 /* Not much point in printing this out, it is always 1. */
49                 if (tcp->u_arg[2] != 1)
50                         tprintf(", %" PRI_klu, tcp->u_arg[2]);
51         }
52         return 0;
53 }
54
55 SYS_FUNC(getdents)
56 {
57         unsigned int i, len, dents = 0;
58         unsigned char *buf;
59
60         if (entering(tcp)) {
61                 printfd(tcp, tcp->u_arg[0]);
62                 return 0;
63         }
64
65         const unsigned int count = tcp->u_arg[2];
66
67         if (syserror(tcp) || !verbose(tcp)) {
68                 tprints(", ");
69                 printaddr(tcp->u_arg[1]);
70                 tprintf(", %u", count);
71                 return 0;
72         }
73
74         /* Beware of insanely large or too small values in tcp->u_rval */
75         if (tcp->u_rval > 1024*1024)
76                 len = 1024*1024;
77         else if (tcp->u_rval < (int) sizeof(kernel_dirent))
78                 len = 0;
79         else
80                 len = tcp->u_rval;
81
82         if (len) {
83                 buf = malloc(len);
84                 if (!buf || umoven(tcp, tcp->u_arg[1], len, buf) < 0) {
85                         tprints(", ");
86                         printaddr(tcp->u_arg[1]);
87                         tprintf(", %u", count);
88                         free(buf);
89                         return 0;
90                 }
91         } else {
92                 buf = NULL;
93         }
94
95         tprints(",");
96         if (!abbrev(tcp))
97                 tprints(" [");
98         for (i = 0; len && i <= len - sizeof(kernel_dirent); ) {
99                 kernel_dirent *d = (kernel_dirent *) &buf[i];
100
101                 if (!abbrev(tcp)) {
102                         int oob = d->d_reclen < sizeof(kernel_dirent) ||
103                                   i + d->d_reclen - 1 >= len;
104                         int d_name_len = oob ? len - i : d->d_reclen;
105                         d_name_len -= offsetof(kernel_dirent, d_name) + 1;
106                         if (d_name_len > D_NAME_LEN_MAX)
107                                 d_name_len = D_NAME_LEN_MAX;
108
109                         tprintf("%s{d_ino=%llu, d_off=%llu, d_reclen=%u"
110                                 ", d_name=", i ? ", " : "",
111                                 zero_extend_signed_to_ull(d->d_ino),
112                                 zero_extend_signed_to_ull(d->d_off),
113                                 d->d_reclen);
114
115                         print_quoted_cstring(d->d_name, d_name_len);
116
117                         tprints(", d_type=");
118                         if (oob)
119                                 tprints("?");
120                         else
121                                 printxval(dirent_types, buf[i + d->d_reclen - 1], "DT_???");
122                         tprints("}");
123                 }
124                 dents++;
125                 if (d->d_reclen < sizeof(kernel_dirent)) {
126                         tprints_comment("d_reclen < sizeof(struct dirent)");
127                         break;
128                 }
129                 i += d->d_reclen;
130         }
131         if (!abbrev(tcp))
132                 tprints("]");
133         else
134                 tprintf_comment("%u entries", dents);
135         tprintf(", %u", count);
136         free(buf);
137         return 0;
138 }