From 2ed2cc743d1b06697f2b868eecb71df2f6a27ba8 Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Thu, 11 Sep 2014 22:40:37 +0000 Subject: [PATCH] Move dirent related parsers to a separate file * dirent.c: New file. * Makefile.am (strace_SOURCES): Add it. * file.c (print_old_dirent, sys_readdir, sys_getdents, sys_getdents64): Move to dirent.c. --- Makefile.am | 1 + dirent.c | 210 ++++++++++++++++++++++++++++++++++++++++++++++++++++ file.c | 209 --------------------------------------------------- 3 files changed, 211 insertions(+), 209 deletions(-) create mode 100644 dirent.c diff --git a/Makefile.am b/Makefile.am index a30ac1c0..7dfdf2c8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -22,6 +22,7 @@ strace_SOURCES = \ block.c \ count.c \ desc.c \ + dirent.c \ fanotify.c \ file.c \ inotify.c \ diff --git a/dirent.c b/dirent.c new file mode 100644 index 00000000..cbebdb73 --- /dev/null +++ b/dirent.c @@ -0,0 +1,210 @@ +#include "defs.h" +#include + +struct kernel_dirent { + unsigned long d_ino; + unsigned long d_off; + unsigned short d_reclen; + char d_name[1]; +}; + +static void +print_old_dirent(struct tcb *tcp, long addr) +{ +#ifdef SH64 + typedef struct kernel_dirent old_dirent_t; +#else + typedef struct { + uint32_t d_ino; + uint32_t d_off; + unsigned short d_reclen; + char d_name[1]; + } old_dirent_t; +#endif + old_dirent_t d; + + if (!verbose(tcp) || umove(tcp, addr, &d) < 0) { + tprintf("%#lx", addr); + return; + } + + tprintf("{d_ino=%lu, d_off=%lu, d_reclen=%u, d_name=\"", + (unsigned long) d.d_ino, (unsigned long) d.d_off, d.d_reclen); + if (d.d_reclen > 256) + d.d_reclen = 256; + printpathn(tcp, addr + offsetof(old_dirent_t, d_name), d.d_reclen); + tprints("\"}"); +} + +int +sys_readdir(struct tcb *tcp) +{ + if (entering(tcp)) { + printfd(tcp, tcp->u_arg[0]); + tprints(", "); + } else { + if (syserror(tcp) || tcp->u_rval == 0 || !verbose(tcp)) + tprintf("%#lx", tcp->u_arg[1]); + else + print_old_dirent(tcp, tcp->u_arg[1]); + /* Not much point in printing this out, it is always 1. */ + if (tcp->u_arg[2] != 1) + tprintf(", %lu", tcp->u_arg[2]); + } + return 0; +} + +#include "xlat/direnttypes.h" + +int +sys_getdents(struct tcb *tcp) +{ + unsigned int i, len, dents = 0; + char *buf; + + if (entering(tcp)) { + printfd(tcp, tcp->u_arg[0]); + tprints(", "); + return 0; + } + if (syserror(tcp) || !verbose(tcp)) { + tprintf("%#lx, %lu", tcp->u_arg[1], tcp->u_arg[2]); + return 0; + } + + /* Beware of insanely large or too small values in tcp->u_rval */ + if (tcp->u_rval > 1024*1024) + len = 1024*1024; + else if (tcp->u_rval < (int) sizeof(struct kernel_dirent)) + len = 0; + else + len = tcp->u_rval; + + if (len) { + buf = malloc(len); + if (!buf) + die_out_of_memory(); + if (umoven(tcp, tcp->u_arg[1], len, buf) < 0) { + tprintf("%#lx, %lu", tcp->u_arg[1], tcp->u_arg[2]); + free(buf); + return 0; + } + } else { + buf = NULL; + } + + if (!abbrev(tcp)) + tprints("{"); + for (i = 0; len && i <= len - sizeof(struct kernel_dirent); ) { + struct kernel_dirent *d = (struct kernel_dirent *) &buf[i]; + + if (!abbrev(tcp)) { + int oob = d->d_reclen < sizeof(struct kernel_dirent) || + i + d->d_reclen - 1 >= len; + int d_name_len = oob ? len - i : d->d_reclen; + d_name_len -= offsetof(struct kernel_dirent, d_name) + 1; + + tprintf("%s{d_ino=%lu, d_off=%lu, ", + i ? " " : "", d->d_ino, d->d_off); + tprintf("d_reclen=%u, d_name=\"%.*s\", d_type=", + d->d_reclen, d_name_len, d->d_name); + if (oob) + tprints("?"); + else + printxval(direnttypes, buf[i + d->d_reclen - 1], "DT_???"); + tprints("}"); + } + dents++; + if (d->d_reclen < sizeof(struct kernel_dirent)) { + tprints("/* d_reclen < sizeof(struct kernel_dirent) */"); + break; + } + i += d->d_reclen; + } + if (!abbrev(tcp)) + tprints("}"); + else + tprintf("/* %u entries */", dents); + tprintf(", %lu", tcp->u_arg[2]); + free(buf); + return 0; +} + +int +sys_getdents64(struct tcb *tcp) +{ + /* the minimum size of a valid dirent64 structure */ + const unsigned int d_name_offset = offsetof(struct dirent64, d_name); + + unsigned int i, len, dents = 0; + char *buf; + + if (entering(tcp)) { + printfd(tcp, tcp->u_arg[0]); + tprints(", "); + return 0; + } + if (syserror(tcp) || !verbose(tcp)) { + tprintf("%#lx, %lu", tcp->u_arg[1], tcp->u_arg[2]); + return 0; + } + + /* Beware of insanely large or too small tcp->u_rval */ + if (tcp->u_rval > 1024*1024) + len = 1024*1024; + else if (tcp->u_rval < (int) d_name_offset) + len = 0; + else + len = tcp->u_rval; + + if (len) { + buf = malloc(len); + if (!buf) + die_out_of_memory(); + if (umoven(tcp, tcp->u_arg[1], len, buf) < 0) { + tprintf("%#lx, %lu", tcp->u_arg[1], tcp->u_arg[2]); + free(buf); + return 0; + } + } else { + buf = NULL; + } + + if (!abbrev(tcp)) + tprints("{"); + for (i = 0; len && i <= len - d_name_offset; ) { + struct dirent64 *d = (struct dirent64 *) &buf[i]; + if (!abbrev(tcp)) { + int d_name_len; + if (d->d_reclen >= d_name_offset + && i + d->d_reclen <= len) { + d_name_len = d->d_reclen - d_name_offset; + } else { + d_name_len = len - i - d_name_offset; + } + + tprintf("%s{d_ino=%" PRIu64 ", d_off=%" PRId64 + ", d_reclen=%u, d_type=", + i ? " " : "", + d->d_ino, + d->d_off, + d->d_reclen); + printxval(direnttypes, d->d_type, "DT_???"); + tprintf(", d_name=\"%.*s\"}", + d_name_len, d->d_name); + } + if (d->d_reclen < d_name_offset) { + tprints("/* d_reclen < offsetof(struct dirent64, d_name) */"); + break; + } + i += d->d_reclen; + dents++; + } + if (!abbrev(tcp)) + tprints("}"); + else + tprintf("/* %u entries */", dents); + tprintf(", %lu", tcp->u_arg[2]); + free(buf); + return 0; +} diff --git a/file.c b/file.c index 00444299..47ca2302 100644 --- a/file.c +++ b/file.c @@ -29,7 +29,6 @@ */ #include "defs.h" -#include #include #if defined(SPARC) || defined(SPARC64) @@ -204,13 +203,6 @@ struct __old_kernel_stat { # include #endif -struct kernel_dirent { - unsigned long d_ino; - unsigned long d_off; - unsigned short d_reclen; - char d_name[1]; -}; - #ifdef O_LARGEFILE # if O_LARGEFILE == 0 /* biarch platforms in 64-bit mode */ # undef O_LARGEFILE @@ -2009,207 +2001,6 @@ sys_mknodat(struct tcb *tcp) return decode_mknod(tcp, 1); } -static void -print_old_dirent(struct tcb *tcp, long addr) -{ -#ifdef SH64 - typedef struct kernel_dirent old_dirent_t; -#else - typedef struct { - uint32_t d_ino; - uint32_t d_off; - unsigned short d_reclen; - char d_name[1]; - } old_dirent_t; -#endif - old_dirent_t d; - - if (!verbose(tcp) || umove(tcp, addr, &d) < 0) { - tprintf("%#lx", addr); - return; - } - - tprintf("{d_ino=%lu, d_off=%lu, d_reclen=%u, d_name=\"", - (unsigned long) d.d_ino, (unsigned long) d.d_off, d.d_reclen); - if (d.d_reclen > 256) - d.d_reclen = 256; - printpathn(tcp, addr + offsetof(old_dirent_t, d_name), d.d_reclen); - tprints("\"}"); -} - -int -sys_readdir(struct tcb *tcp) -{ - if (entering(tcp)) { - printfd(tcp, tcp->u_arg[0]); - tprints(", "); - } else { - if (syserror(tcp) || tcp->u_rval == 0 || !verbose(tcp)) - tprintf("%#lx", tcp->u_arg[1]); - else - print_old_dirent(tcp, tcp->u_arg[1]); - /* Not much point in printing this out, it is always 1. */ - if (tcp->u_arg[2] != 1) - tprintf(", %lu", tcp->u_arg[2]); - } - return 0; -} - -#include "xlat/direnttypes.h" - -int -sys_getdents(struct tcb *tcp) -{ - unsigned int i, len, dents = 0; - char *buf; - - if (entering(tcp)) { - printfd(tcp, tcp->u_arg[0]); - tprints(", "); - return 0; - } - if (syserror(tcp) || !verbose(tcp)) { - tprintf("%#lx, %lu", tcp->u_arg[1], tcp->u_arg[2]); - return 0; - } - - /* Beware of insanely large or too small values in tcp->u_rval */ - if (tcp->u_rval > 1024*1024) - len = 1024*1024; - else if (tcp->u_rval < (int) sizeof(struct kernel_dirent)) - len = 0; - else - len = tcp->u_rval; - - if (len) { - buf = malloc(len); - if (!buf) - die_out_of_memory(); - if (umoven(tcp, tcp->u_arg[1], len, buf) < 0) { - tprintf("%#lx, %lu", tcp->u_arg[1], tcp->u_arg[2]); - free(buf); - return 0; - } - } else { - buf = NULL; - } - - if (!abbrev(tcp)) - tprints("{"); - for (i = 0; len && i <= len - sizeof(struct kernel_dirent); ) { - struct kernel_dirent *d = (struct kernel_dirent *) &buf[i]; - - if (!abbrev(tcp)) { - int oob = d->d_reclen < sizeof(struct kernel_dirent) || - i + d->d_reclen - 1 >= len; - int d_name_len = oob ? len - i : d->d_reclen; - d_name_len -= offsetof(struct kernel_dirent, d_name) + 1; - - tprintf("%s{d_ino=%lu, d_off=%lu, ", - i ? " " : "", d->d_ino, d->d_off); - tprintf("d_reclen=%u, d_name=\"%.*s\", d_type=", - d->d_reclen, d_name_len, d->d_name); - if (oob) - tprints("?"); - else - printxval(direnttypes, buf[i + d->d_reclen - 1], "DT_???"); - tprints("}"); - } - dents++; - if (d->d_reclen < sizeof(struct kernel_dirent)) { - tprints("/* d_reclen < sizeof(struct kernel_dirent) */"); - break; - } - i += d->d_reclen; - } - if (!abbrev(tcp)) - tprints("}"); - else - tprintf("/* %u entries */", dents); - tprintf(", %lu", tcp->u_arg[2]); - free(buf); - return 0; -} - -int -sys_getdents64(struct tcb *tcp) -{ - /* the minimum size of a valid dirent64 structure */ - const unsigned int d_name_offset = offsetof(struct dirent64, d_name); - - unsigned int i, len, dents = 0; - char *buf; - - if (entering(tcp)) { - printfd(tcp, tcp->u_arg[0]); - tprints(", "); - return 0; - } - if (syserror(tcp) || !verbose(tcp)) { - tprintf("%#lx, %lu", tcp->u_arg[1], tcp->u_arg[2]); - return 0; - } - - /* Beware of insanely large or too small tcp->u_rval */ - if (tcp->u_rval > 1024*1024) - len = 1024*1024; - else if (tcp->u_rval < (int) d_name_offset) - len = 0; - else - len = tcp->u_rval; - - if (len) { - buf = malloc(len); - if (!buf) - die_out_of_memory(); - if (umoven(tcp, tcp->u_arg[1], len, buf) < 0) { - tprintf("%#lx, %lu", tcp->u_arg[1], tcp->u_arg[2]); - free(buf); - return 0; - } - } else { - buf = NULL; - } - - if (!abbrev(tcp)) - tprints("{"); - for (i = 0; len && i <= len - d_name_offset; ) { - struct dirent64 *d = (struct dirent64 *) &buf[i]; - if (!abbrev(tcp)) { - int d_name_len; - if (d->d_reclen >= d_name_offset - && i + d->d_reclen <= len) { - d_name_len = d->d_reclen - d_name_offset; - } else { - d_name_len = len - i - d_name_offset; - } - - tprintf("%s{d_ino=%" PRIu64 ", d_off=%" PRId64 - ", d_reclen=%u, d_type=", - i ? " " : "", - d->d_ino, - d->d_off, - d->d_reclen); - printxval(direnttypes, d->d_type, "DT_???"); - tprintf(", d_name=\"%.*s\"}", - d_name_len, d->d_name); - } - if (d->d_reclen < d_name_offset) { - tprints("/* d_reclen < offsetof(struct dirent64, d_name) */"); - break; - } - i += d->d_reclen; - dents++; - } - if (!abbrev(tcp)) - tprints("}"); - else - tprintf("/* %u entries */", dents); - tprintf(", %lu", tcp->u_arg[2]); - free(buf); - return 0; -} - int sys_getcwd(struct tcb *tcp) { -- 2.40.0