blob: dec436b5f43892729f9da050d322691bbcbb8f82 [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
Dmitry V. Levin3ef50212015-07-20 15:42:22 +000028 if (umove_or_printaddr(tcp, addr, &d))
Dmitry V. Levin2ed2cc72014-09-11 22:40:37 +000029 return;
Dmitry V. Levin2ed2cc72014-09-11 22:40:37 +000030
Dmitry V. Levinc9297712015-01-25 00:04:20 +000031 tprintf("{d_ino=%lu, d_off=%lu, d_reclen=%u, d_name=",
Dmitry V. Levin2ed2cc72014-09-11 22:40:37 +000032 (unsigned long) d.d_ino, (unsigned long) d.d_off, d.d_reclen);
Dmitry V. Levinc9297712015-01-25 00:04:20 +000033 if (d.d_reclen > D_NAME_LEN_MAX)
34 d.d_reclen = D_NAME_LEN_MAX;
Dmitry V. Levin2ed2cc72014-09-11 22:40:37 +000035 printpathn(tcp, addr + offsetof(old_dirent_t, d_name), d.d_reclen);
Dmitry V. Levinc9297712015-01-25 00:04:20 +000036 tprints("}");
Dmitry V. Levin2ed2cc72014-09-11 22:40:37 +000037}
38
Dmitry V. Levina0bd3742015-04-07 01:36:50 +000039SYS_FUNC(readdir)
Dmitry V. Levin2ed2cc72014-09-11 22:40:37 +000040{
41 if (entering(tcp)) {
42 printfd(tcp, tcp->u_arg[0]);
43 tprints(", ");
44 } else {
Dmitry V. Levin3ef50212015-07-20 15:42:22 +000045 if (tcp->u_rval == 0)
46 printaddr(tcp->u_arg[1]);
Dmitry V. Levin2ed2cc72014-09-11 22:40:37 +000047 else
48 print_old_dirent(tcp, tcp->u_arg[1]);
49 /* Not much point in printing this out, it is always 1. */
50 if (tcp->u_arg[2] != 1)
51 tprintf(", %lu", tcp->u_arg[2]);
52 }
53 return 0;
54}
55
56#include "xlat/direnttypes.h"
57
Dmitry V. Levina0bd3742015-04-07 01:36:50 +000058SYS_FUNC(getdents)
Dmitry V. Levin2ed2cc72014-09-11 22:40:37 +000059{
60 unsigned int i, len, dents = 0;
61 char *buf;
62
63 if (entering(tcp)) {
64 printfd(tcp, tcp->u_arg[0]);
65 tprints(", ");
66 return 0;
67 }
68 if (syserror(tcp) || !verbose(tcp)) {
Dmitry V. Levin3ef50212015-07-20 15:42:22 +000069 printaddr(tcp->u_arg[1]);
70 tprintf(", %lu", tcp->u_arg[2]);
Dmitry V. Levin2ed2cc72014-09-11 22:40:37 +000071 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(struct kernel_dirent))
78 len = 0;
79 else
80 len = tcp->u_rval;
81
82 if (len) {
Dmitry V. Levin3ef50212015-07-20 15:42:22 +000083 buf = malloc(len);
84 if (!buf || umoven(tcp, tcp->u_arg[1], len, buf) < 0) {
85 printaddr(tcp->u_arg[1]);
86 tprintf(", %lu", tcp->u_arg[2]);
Dmitry V. Levin2ed2cc72014-09-11 22:40:37 +000087 free(buf);
88 return 0;
89 }
90 } else {
91 buf = NULL;
92 }
93
94 if (!abbrev(tcp))
Gabriel Laskara2df1c12015-11-19 11:44:30 +010095 tprints("[");
Dmitry V. Levin2ed2cc72014-09-11 22:40:37 +000096 for (i = 0; len && i <= len - sizeof(struct kernel_dirent); ) {
97 struct kernel_dirent *d = (struct kernel_dirent *) &buf[i];
98
99 if (!abbrev(tcp)) {
100 int oob = d->d_reclen < sizeof(struct kernel_dirent) ||
101 i + d->d_reclen - 1 >= len;
102 int d_name_len = oob ? len - i : d->d_reclen;
103 d_name_len -= offsetof(struct kernel_dirent, d_name) + 1;
Dmitry V. Levinc9297712015-01-25 00:04:20 +0000104 if (d_name_len > D_NAME_LEN_MAX)
105 d_name_len = D_NAME_LEN_MAX;
Dmitry V. Levin2ed2cc72014-09-11 22:40:37 +0000106
Dmitry V. Levinc9297712015-01-25 00:04:20 +0000107 tprintf("%s{d_ino=%lu, d_off=%lu, d_reclen=%u, d_name=",
Gabriel Laskara2df1c12015-11-19 11:44:30 +0100108 i ? ", " : "", d->d_ino, d->d_off, d->d_reclen);
Dmitry V. Levinc9297712015-01-25 00:04:20 +0000109
110 if (print_quoted_string(d->d_name, d_name_len,
111 QUOTE_0_TERMINATED) > 0) {
112 tprints("...");
113 }
114
115 tprints(", d_type=");
Dmitry V. Levin2ed2cc72014-09-11 22:40:37 +0000116 if (oob)
117 tprints("?");
118 else
119 printxval(direnttypes, buf[i + d->d_reclen - 1], "DT_???");
120 tprints("}");
121 }
122 dents++;
123 if (d->d_reclen < sizeof(struct kernel_dirent)) {
124 tprints("/* d_reclen < sizeof(struct kernel_dirent) */");
125 break;
126 }
127 i += d->d_reclen;
128 }
129 if (!abbrev(tcp))
Gabriel Laskara2df1c12015-11-19 11:44:30 +0100130 tprints("]");
Dmitry V. Levin2ed2cc72014-09-11 22:40:37 +0000131 else
132 tprintf("/* %u entries */", dents);
133 tprintf(", %lu", tcp->u_arg[2]);
134 free(buf);
135 return 0;
136}
137
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000138SYS_FUNC(getdents64)
Dmitry V. Levin2ed2cc72014-09-11 22:40:37 +0000139{
140 /* the minimum size of a valid dirent64 structure */
141 const unsigned int d_name_offset = offsetof(struct dirent64, d_name);
142
143 unsigned int i, len, dents = 0;
144 char *buf;
145
146 if (entering(tcp)) {
147 printfd(tcp, tcp->u_arg[0]);
148 tprints(", ");
149 return 0;
150 }
151 if (syserror(tcp) || !verbose(tcp)) {
Dmitry V. Levin3ef50212015-07-20 15:42:22 +0000152 printaddr(tcp->u_arg[1]);
153 tprintf(", %lu", tcp->u_arg[2]);
Dmitry V. Levin2ed2cc72014-09-11 22:40:37 +0000154 return 0;
155 }
156
157 /* Beware of insanely large or too small tcp->u_rval */
158 if (tcp->u_rval > 1024*1024)
159 len = 1024*1024;
160 else if (tcp->u_rval < (int) d_name_offset)
161 len = 0;
162 else
163 len = tcp->u_rval;
164
165 if (len) {
Dmitry V. Levin3ef50212015-07-20 15:42:22 +0000166 buf = malloc(len);
167 if (!buf || umoven(tcp, tcp->u_arg[1], len, buf) < 0) {
168 printaddr(tcp->u_arg[1]);
169 tprintf(", %lu", tcp->u_arg[2]);
Dmitry V. Levin2ed2cc72014-09-11 22:40:37 +0000170 free(buf);
171 return 0;
172 }
173 } else {
174 buf = NULL;
175 }
176
177 if (!abbrev(tcp))
Gabriel Laskara2df1c12015-11-19 11:44:30 +0100178 tprints("[");
Dmitry V. Levin2ed2cc72014-09-11 22:40:37 +0000179 for (i = 0; len && i <= len - d_name_offset; ) {
180 struct dirent64 *d = (struct dirent64 *) &buf[i];
181 if (!abbrev(tcp)) {
182 int d_name_len;
183 if (d->d_reclen >= d_name_offset
184 && i + d->d_reclen <= len) {
185 d_name_len = d->d_reclen - d_name_offset;
186 } else {
187 d_name_len = len - i - d_name_offset;
188 }
Dmitry V. Levinc9297712015-01-25 00:04:20 +0000189 if (d_name_len > D_NAME_LEN_MAX)
190 d_name_len = D_NAME_LEN_MAX;
Dmitry V. Levin2ed2cc72014-09-11 22:40:37 +0000191
192 tprintf("%s{d_ino=%" PRIu64 ", d_off=%" PRId64
193 ", d_reclen=%u, d_type=",
Gabriel Laskara2df1c12015-11-19 11:44:30 +0100194 i ? ", " : "",
Dmitry V. Levin2ed2cc72014-09-11 22:40:37 +0000195 d->d_ino,
196 d->d_off,
197 d->d_reclen);
198 printxval(direnttypes, d->d_type, "DT_???");
Dmitry V. Levinc9297712015-01-25 00:04:20 +0000199
200 tprints(", d_name=");
201 if (print_quoted_string(d->d_name, d_name_len,
202 QUOTE_0_TERMINATED) > 0) {
203 tprints("...");
204 }
205
206 tprints("}");
Dmitry V. Levin2ed2cc72014-09-11 22:40:37 +0000207 }
208 if (d->d_reclen < d_name_offset) {
209 tprints("/* d_reclen < offsetof(struct dirent64, d_name) */");
210 break;
211 }
212 i += d->d_reclen;
213 dents++;
214 }
215 if (!abbrev(tcp))
Gabriel Laskara2df1c12015-11-19 11:44:30 +0100216 tprints("]");
Dmitry V. Levin2ed2cc72014-09-11 22:40:37 +0000217 else
218 tprintf("/* %u entries */", dents);
219 tprintf(", %lu", tcp->u_arg[2]);
220 free(buf);
221 return 0;
222}