diff options
author | Dmitry V. Levin <ldv@altlinux.org> | 2011-10-11 17:07:05 +0000 |
---|---|---|
committer | Dmitry V. Levin <ldv@altlinux.org> | 2011-10-11 17:07:05 +0000 |
commit | d99e48c0f33f5230a743cd91a986edba176db2f8 (patch) | |
tree | 3721bbc9a677276967e93763d1298d4cf09e74c7 /io.c | |
parent | c327d71258edb75a8120dfbbdd0b1828a3f43a9a (diff) | |
download | strace-d99e48c0f33f5230a743cd91a986edba176db2f8.tar.gz strace-d99e48c0f33f5230a743cd91a986edba176db2f8.tar.bz2 strace-d99e48c0f33f5230a743cd91a986edba176db2f8.tar.xz |
Implement decoding of splice, tee and vmsplice(2) syscalls
* io.c (print_loff_t): New function.
(sys_sendfile64): Use it.
(splice_flags): New xlat structure.
(sys_tee, sys_splice, sys_vmsplice): New functions.
* linux/syscall.h (sys_tee, sys_splice, sys_vmsplice): Declare them.
* linux/*/syscallent.h: Use them.
Diffstat (limited to 'io.c')
-rw-r--r-- | io.c | 95 |
1 files changed, 87 insertions, 8 deletions
@@ -361,27 +361,106 @@ sys_sendfile(struct tcb *tcp) return 0; } +static void +print_loff_t(struct tcb *tcp, long addr) +{ + loff_t offset; + + if (!addr) + tprints("NULL"); + else if (umove(tcp, addr, &offset) < 0) + tprintf("%#lx", addr); + else + tprintf("[%llu]", (unsigned long long int) offset); +} + int sys_sendfile64(struct tcb *tcp) { if (entering(tcp)) { - loff_t offset; - printfd(tcp, tcp->u_arg[0]); tprints(", "); printfd(tcp, tcp->u_arg[1]); tprints(", "); - if (!tcp->u_arg[2]) - tprints("NULL"); - else if (umove(tcp, tcp->u_arg[2], &offset) < 0) - tprintf("%#lx", tcp->u_arg[2]); - else - tprintf("[%llu]", (unsigned long long int) offset); + print_loff_t(tcp, tcp->u_arg[2]); tprintf(", %lu", tcp->u_arg[3]); } return 0; } +static const struct xlat splice_flags[] = { +#ifdef SPLICE_F_MOVE + { SPLICE_F_MOVE, "SPLICE_F_MOVE" }, +#endif +#ifdef SPLICE_F_NONBLOCK + { SPLICE_F_NONBLOCK, "SPLICE_F_NONBLOCK" }, +#endif +#ifdef SPLICE_F_MORE + { SPLICE_F_MORE, "SPLICE_F_MORE" }, +#endif +#ifdef SPLICE_F_GIFT + { SPLICE_F_GIFT, "SPLICE_F_GIFT" }, +#endif + { 0, NULL }, +}; + +int +sys_tee(struct tcb *tcp) +{ + if (entering(tcp)) { + /* int fd_in */ + printfd(tcp, tcp->u_arg[0]); + tprints(", "); + /* int fd_out */ + printfd(tcp, tcp->u_arg[1]); + tprints(", "); + /* size_t len */ + tprintf("%lu, ", tcp->u_arg[2]); + /* unsigned int flags */ + printflags(splice_flags, tcp->u_arg[3], "SPLICE_F_???"); + } + return 0; +} + +int +sys_splice(struct tcb *tcp) +{ + if (entering(tcp)) { + /* int fd_in */ + printfd(tcp, tcp->u_arg[0]); + tprints(", "); + /* loff_t *off_in */ + print_loff_t(tcp, tcp->u_arg[1]); + tprints(", "); + /* int fd_out */ + printfd(tcp, tcp->u_arg[2]); + tprints(", "); + /* loff_t *off_out */ + print_loff_t(tcp, tcp->u_arg[3]); + tprints(", "); + /* size_t len */ + tprintf("%lu, ", tcp->u_arg[4]); + /* unsigned int flags */ + printflags(splice_flags, tcp->u_arg[5], "SPLICE_F_???"); + } + return 0; +} + +int +sys_vmsplice(struct tcb *tcp) +{ + if (entering(tcp)) { + /* int fd */ + printfd(tcp, tcp->u_arg[0]); + tprints(", "); + /* const struct iovec *iov, unsigned long nr_segs */ + tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1], 1); + tprints(", "); + /* unsigned int flags */ + printflags(splice_flags, tcp->u_arg[3], "SPLICE_F_???"); + } + return 0; +} #endif /* LINUX */ #if _LFS64_LARGEFILE || HAVE_LONG_LONG_OFF_T |