diff options
author | Dmitry V. Levin <ldv@altlinux.org> | 2015-07-07 21:38:07 +0300 |
---|---|---|
committer | Dmitry V. Levin <ldv@altlinux.org> | 2015-07-10 22:58:48 +0000 |
commit | 3d0e1f331f25834bc8d32b46ed9402b8b64ce99d (patch) | |
tree | 3231d0e54eee72322afeedeb8292cb12b4dca194 | |
parent | 317d19e8e99d16173b900f98c81e9a95a465b5bb (diff) | |
download | strace-3d0e1f331f25834bc8d32b46ed9402b8b64ce99d.tar.gz |
scsi.c: enhance SG_IO ioctl parser
Fix SG_IO ioctl output in case of failed umove
* scsi.c: Include <linux/ioctl.h> instead of <sys/ioctl.h>.
Update for RVAL_DECODED.
(print_sg_io_v3_req, print_sg_io_v3_res, print_sg_io_v4_req,
print_sg_io_v4_res): Do not print address in case of failed umove.
(scsi_ioctl): Use printaddr.
-rw-r--r-- | scsi.c | 106 |
1 files changed, 52 insertions, 54 deletions
@@ -30,7 +30,7 @@ #ifdef HAVE_SCSI_SG_H -# include <sys/ioctl.h> +# include <linux/ioctl.h> # include <scsi/sg.h> # include "xlat/sg_io_dxfer_direction.h" @@ -67,17 +67,16 @@ out: tprints("]"); } -static void -print_sg_io_v3_req(struct tcb *tcp, long arg) +static int +print_sg_io_v3_req(struct tcb *tcp, const long arg) { struct sg_io_hdr sg_io; if (umove(tcp, arg, &sg_io) < 0) { - tprintf(", %#lx", arg); - return; + tprints("???}"); + return RVAL_DECODED | 1; } - tprints(", "); printxval(sg_io_dxfer_direction, sg_io.dxfer_direction, "SG_DXFER_???"); tprintf(", cmd[%u]=", sg_io.cmd_len); @@ -99,15 +98,16 @@ print_sg_io_v3_req(struct tcb *tcp, long arg) print_sg_io_buffer(tcp, (unsigned long) sg_io.dxferp, sg_io.dxfer_len); } + return 1; } static void -print_sg_io_v3_res(struct tcb *tcp, long arg) +print_sg_io_v3_res(struct tcb *tcp, const long arg) { struct sg_io_hdr sg_io; if (umove(tcp, arg, &sg_io) < 0) { - tprintf(", %#lx", arg); + tprints(", ???"); return; } @@ -139,17 +139,16 @@ print_sg_io_v3_res(struct tcb *tcp, long arg) #ifdef HAVE_LINUX_BSG_H -static void -print_sg_io_v4_req(struct tcb *tcp, long arg) +static int +print_sg_io_v4_req(struct tcb *tcp, const long arg) { struct sg_io_v4 sg_io; if (umove(tcp, arg, &sg_io) < 0) { - tprintf(", %#lx", arg); - return; + tprints("???}"); + return RVAL_DECODED | 1; } - tprints(", "); printxval(bsg_protocol, sg_io.protocol, "BSG_PROTOCOL_???"); tprints(", "); printxval(bsg_subprotocol, sg_io.subprotocol, "BSG_SUB_PROTOCOL_???"); @@ -175,16 +174,17 @@ print_sg_io_v4_req(struct tcb *tcp, long arg) 1, sg_io.dout_xfer_len); else print_sg_io_buffer(tcp, sg_io.dout_xferp, sg_io.dout_xfer_len); + return 1; } static void -print_sg_io_v4_res(struct tcb *tcp, long arg) +print_sg_io_v4_res(struct tcb *tcp, const long arg) { struct sg_io_v4 sg_io; uint32_t din_len; if (umove(tcp, arg, &sg_io) < 0) { - tprintf(", %#lx", arg); + tprints(", ???"); return; } @@ -214,78 +214,76 @@ print_sg_io_v4_res(struct tcb *tcp, long arg) #else /* !HAVE_LINUX_BSG_H */ -static void -print_sg_io_v4_req(struct tcb *tcp, long arg) +static int +print_sg_io_v4_req(struct tcb *tcp, const long arg) { - tprintf(", %#lx", arg); + tprints("...}"); + return RVAL_DECODED | 1; } static void -print_sg_io_v4_res(struct tcb *tcp, long arg) +print_sg_io_v4_res(struct tcb *tcp, const long arg) { } #endif -static void -print_sg_io_req(struct tcb *tcp, uint32_t iid, long arg) +static int +print_sg_io_req(struct tcb *tcp, uint32_t iid, const long arg) { - tprintf("{'%c'", iid); + tprintf("{'%c', ", iid); switch (iid) { case 'S': - print_sg_io_v3_req(tcp, arg); - break; + return print_sg_io_v3_req(tcp, arg); case 'Q': - print_sg_io_v4_req(tcp, arg); - break; + return print_sg_io_v4_req(tcp, arg); default: - tprints(", ..."); + tprints("...}"); + return RVAL_DECODED | 1; } } static void -print_sg_io_res(struct tcb *tcp, uint32_t iid, long arg) +print_sg_io_res(struct tcb *tcp, uint32_t iid, const long arg) { - if (!syserror(tcp)) { - switch (iid) { - case 'S': - print_sg_io_v3_res(tcp, arg); - break; - case 'Q': - print_sg_io_v4_res(tcp, arg); - break; - } + switch (iid) { + case 'S': + print_sg_io_v3_res(tcp, arg); + break; + case 'Q': + print_sg_io_v4_res(tcp, arg); + break; } - - tprintf("}"); } int -scsi_ioctl(struct tcb *tcp, const unsigned int code, long arg) +scsi_ioctl(struct tcb *tcp, const unsigned int code, const long arg) { uint32_t iid; - switch (code) { - case SG_IO: - if (entering(tcp)) { - tprints(", "); + if (SG_IO != code) + return RVAL_DECODED; + + if (entering(tcp)) { + tprints(", "); + if (!arg || umove(tcp, arg, &iid) < 0) { + printaddr(arg); + return RVAL_DECODED | 1; + } else { + return print_sg_io_req(tcp, iid, arg); + } + } else { + if (!syserror(tcp)) { if (umove(tcp, arg, &iid) < 0) - tprintf("%#lx", arg); + tprints(", ???"); else - print_sg_io_req(tcp, iid, arg); - } else { - if (umove(tcp, arg, &iid) >= 0) print_sg_io_res(tcp, iid, arg); } - break; - default: - if (entering(tcp)) - tprintf(", %#lx", arg); - break; + tprintf("}"); + return RVAL_DECODED | 1; } - return 1; } #endif /* HAVE_SCSI_SG_H */ |