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