• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  #include "defs.h"
2  #include <dirent.h>
3  
4  #define D_NAME_LEN_MAX 256
5  
6  struct kernel_dirent {
7  	unsigned long   d_ino;
8  	unsigned long   d_off;
9  	unsigned short  d_reclen;
10  	char            d_name[1];
11  };
12  
13  static void
print_old_dirent(struct tcb * tcp,long addr)14  print_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  
33  	tprintf("{d_ino=%lu, d_off=%lu, d_reclen=%u, d_name=",
34  		(unsigned long) d.d_ino, (unsigned long) d.d_off, d.d_reclen);
35  	if (d.d_reclen > D_NAME_LEN_MAX)
36  		d.d_reclen = D_NAME_LEN_MAX;
37  	printpathn(tcp, addr + offsetof(old_dirent_t, d_name), d.d_reclen);
38  	tprints("}");
39  }
40  
SYS_FUNC(readdir)41  SYS_FUNC(readdir)
42  {
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  
SYS_FUNC(getdents)60  SYS_FUNC(getdents)
61  {
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;
106  			if (d_name_len > D_NAME_LEN_MAX)
107  				d_name_len = D_NAME_LEN_MAX;
108  
109  			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=");
118  			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  
SYS_FUNC(getdents64)140  SYS_FUNC(getdents64)
141  {
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  			}
191  			if (d_name_len > D_NAME_LEN_MAX)
192  				d_name_len = D_NAME_LEN_MAX;
193  
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_???");
201  
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("}");
209  		}
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  }
225