blob: 32f04b9e965ac748583ee0b4090f0f888e996ab4 [file] [log] [blame]
Dmitry V. Levin2ed2cc72014-09-11 22:40:37 +00001#include "defs.h"
2#include <dirent.h>
3
Dmitry V. Levinc9297712015-01-25 00:04:20 +00004#define D_NAME_LEN_MAX 256
5
Dmitry V. Levin2ed2cc72014-09-11 22:40:37 +00006struct kernel_dirent {
7 unsigned long d_ino;
8 unsigned long d_off;
9 unsigned short d_reclen;
10 char d_name[1];
11};
12
13static void
14print_old_dirent(struct tcb *tcp, long addr)
15{
16#ifdef SH64
17 typedef struct kernel_dirent old_dirent_t;
18#else
19 typedef struct {
20 uint32_t d_ino;
21 uint32_t d_off;
22 unsigned short d_reclen;
23 char d_name[1];
24 } old_dirent_t;
25#endif
26 old_dirent_t d;
27
28 if (!verbose(tcp) || umove(tcp, addr, &d) < 0) {
29 tprintf("%#lx", addr);
30 return;
31 }
32
Dmitry V. Levinc9297712015-01-25 00:04:20 +000033 tprintf("{d_ino=%lu, d_off=%lu, d_reclen=%u, d_name=",
Dmitry V. Levin2ed2cc72014-09-11 22:40:37 +000034 (unsigned long) d.d_ino, (unsigned long) d.d_off, d.d_reclen);
Dmitry V. Levinc9297712015-01-25 00:04:20 +000035 if (d.d_reclen > D_NAME_LEN_MAX)
36 d.d_reclen = D_NAME_LEN_MAX;
Dmitry V. Levin2ed2cc72014-09-11 22:40:37 +000037 printpathn(tcp, addr + offsetof(old_dirent_t, d_name), d.d_reclen);
Dmitry V. Levinc9297712015-01-25 00:04:20 +000038 tprints("}");
Dmitry V. Levin2ed2cc72014-09-11 22:40:37 +000039}
40
Dmitry V. Levina0bd3742015-04-07 01:36:50 +000041SYS_FUNC(readdir)
Dmitry V. Levin2ed2cc72014-09-11 22:40:37 +000042{
43 if (entering(tcp)) {
44 printfd(tcp, tcp->u_arg[0]);
45 tprints(", ");
46 } else {
47 if (syserror(tcp) || tcp->u_rval == 0 || !verbose(tcp))
48 tprintf("%#lx", tcp->u_arg[1]);
49 else
50 print_old_dirent(tcp, tcp->u_arg[1]);
51 /* Not much point in printing this out, it is always 1. */
52 if (tcp->u_arg[2] != 1)
53 tprintf(", %lu", tcp->u_arg[2]);
54 }
55 return 0;
56}
57
58#include "xlat/direnttypes.h"
59
Dmitry V. Levina0bd3742015-04-07 01:36:50 +000060SYS_FUNC(getdents)
Dmitry V. Levin2ed2cc72014-09-11 22:40:37 +000061{
62 unsigned int i, len, dents = 0;
63 char *buf;
64
65 if (entering(tcp)) {
66 printfd(tcp, tcp->u_arg[0]);
67 tprints(", ");
68 return 0;
69 }
70 if (syserror(tcp) || !verbose(tcp)) {
71 tprintf("%#lx, %lu", tcp->u_arg[1], tcp->u_arg[2]);
72 return 0;
73 }
74
75 /* Beware of insanely large or too small values in tcp->u_rval */
76 if (tcp->u_rval > 1024*1024)
77 len = 1024*1024;
78 else if (tcp->u_rval < (int) sizeof(struct kernel_dirent))
79 len = 0;
80 else
81 len = tcp->u_rval;
82
83 if (len) {
84 buf = malloc(len);
85 if (!buf)
86 die_out_of_memory();
87 if (umoven(tcp, tcp->u_arg[1], len, buf) < 0) {
88 tprintf("%#lx, %lu", tcp->u_arg[1], tcp->u_arg[2]);
89 free(buf);
90 return 0;
91 }
92 } else {
93 buf = NULL;
94 }
95
96 if (!abbrev(tcp))
97 tprints("{");
98 for (i = 0; len && i <= len - sizeof(struct kernel_dirent); ) {
99 struct kernel_dirent *d = (struct kernel_dirent *) &buf[i];
100
101 if (!abbrev(tcp)) {
102 int oob = d->d_reclen < sizeof(struct 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(struct kernel_dirent, d_name) + 1;
Dmitry V. Levinc9297712015-01-25 00:04:20 +0000106 if (d_name_len > D_NAME_LEN_MAX)
107 d_name_len = D_NAME_LEN_MAX;
Dmitry V. Levin2ed2cc72014-09-11 22:40:37 +0000108
Dmitry V. Levinc9297712015-01-25 00:04:20 +0000109 tprintf("%s{d_ino=%lu, d_off=%lu, d_reclen=%u, d_name=",
110 i ? " " : "", d->d_ino, d->d_off, d->d_reclen);
111
112 if (print_quoted_string(d->d_name, d_name_len,
113 QUOTE_0_TERMINATED) > 0) {
114 tprints("...");
115 }
116
117 tprints(", d_type=");
Dmitry V. Levin2ed2cc72014-09-11 22:40:37 +0000118 if (oob)
119 tprints("?");
120 else
121 printxval(direnttypes, buf[i + d->d_reclen - 1], "DT_???");
122 tprints("}");
123 }
124 dents++;
125 if (d->d_reclen < sizeof(struct kernel_dirent)) {
126 tprints("/* d_reclen < sizeof(struct kernel_dirent) */");
127 break;
128 }
129 i += d->d_reclen;
130 }
131 if (!abbrev(tcp))
132 tprints("}");
133 else
134 tprintf("/* %u entries */", dents);
135 tprintf(", %lu", tcp->u_arg[2]);
136 free(buf);
137 return 0;
138}
139
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000140SYS_FUNC(getdents64)
Dmitry V. Levin2ed2cc72014-09-11 22:40:37 +0000141{
142 /* the minimum size of a valid dirent64 structure */
143 const unsigned int d_name_offset = offsetof(struct dirent64, d_name);
144
145 unsigned int i, len, dents = 0;
146 char *buf;
147
148 if (entering(tcp)) {
149 printfd(tcp, tcp->u_arg[0]);
150 tprints(", ");
151 return 0;
152 }
153 if (syserror(tcp) || !verbose(tcp)) {
154 tprintf("%#lx, %lu", tcp->u_arg[1], tcp->u_arg[2]);
155 return 0;
156 }
157
158 /* Beware of insanely large or too small tcp->u_rval */
159 if (tcp->u_rval > 1024*1024)
160 len = 1024*1024;
161 else if (tcp->u_rval < (int) d_name_offset)
162 len = 0;
163 else
164 len = tcp->u_rval;
165
166 if (len) {
167 buf = malloc(len);
168 if (!buf)
169 die_out_of_memory();
170 if (umoven(tcp, tcp->u_arg[1], len, buf) < 0) {
171 tprintf("%#lx, %lu", tcp->u_arg[1], tcp->u_arg[2]);
172 free(buf);
173 return 0;
174 }
175 } else {
176 buf = NULL;
177 }
178
179 if (!abbrev(tcp))
180 tprints("{");
181 for (i = 0; len && i <= len - d_name_offset; ) {
182 struct dirent64 *d = (struct dirent64 *) &buf[i];
183 if (!abbrev(tcp)) {
184 int d_name_len;
185 if (d->d_reclen >= d_name_offset
186 && i + d->d_reclen <= len) {
187 d_name_len = d->d_reclen - d_name_offset;
188 } else {
189 d_name_len = len - i - d_name_offset;
190 }
Dmitry V. Levinc9297712015-01-25 00:04:20 +0000191 if (d_name_len > D_NAME_LEN_MAX)
192 d_name_len = D_NAME_LEN_MAX;
Dmitry V. Levin2ed2cc72014-09-11 22:40:37 +0000193
194 tprintf("%s{d_ino=%" PRIu64 ", d_off=%" PRId64
195 ", d_reclen=%u, d_type=",
196 i ? " " : "",
197 d->d_ino,
198 d->d_off,
199 d->d_reclen);
200 printxval(direnttypes, d->d_type, "DT_???");
Dmitry V. Levinc9297712015-01-25 00:04:20 +0000201
202 tprints(", d_name=");
203 if (print_quoted_string(d->d_name, d_name_len,
204 QUOTE_0_TERMINATED) > 0) {
205 tprints("...");
206 }
207
208 tprints("}");
Dmitry V. Levin2ed2cc72014-09-11 22:40:37 +0000209 }
210 if (d->d_reclen < d_name_offset) {
211 tprints("/* d_reclen < offsetof(struct dirent64, d_name) */");
212 break;
213 }
214 i += d->d_reclen;
215 dents++;
216 }
217 if (!abbrev(tcp))
218 tprints("}");
219 else
220 tprintf("/* %u entries */", dents);
221 tprintf(", %lu", tcp->u_arg[2]);
222 free(buf);
223 return 0;
224}