]> granicus.if.org Git - strace/blobdiff - ioctl.c
Introduce generic STRINGIFY and STRINGIFY_VAL macros
[strace] / ioctl.c
diff --git a/ioctl.c b/ioctl.c
index 9b6ea166a2552648b6bf0efa8ec9193cdd67cc55..264c7c02c71cafdd49d8b5baf189daf68d9b69ea 100644 (file)
--- a/ioctl.c
+++ b/ioctl.c
@@ -3,6 +3,7 @@
  * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
  * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
  * Copyright (c) 1996-2001 Wichert Akkerman <wichert@cistron.nl>
+ * Copyright (c) 1999-2017 The strace developers.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -42,7 +43,7 @@
 static int
 compare(const void *a, const void *b)
 {
-       const unsigned int code1 = (const unsigned long) a;
+       const unsigned int code1 = (const uintptr_t) a;
        const unsigned int code2 = ((struct_ioctlent *) b)->code;
        return (code1 > code2) ? 1 : (code1 < code2) ? -1 : 0;
 }
@@ -52,7 +53,7 @@ ioctl_lookup(const unsigned int code)
 {
        struct_ioctlent *iop;
 
-       iop = bsearch((const void *) (const unsigned long) code, ioctlent,
+       iop = bsearch((const void *) (const uintptr_t) code, ioctlent,
                        nioctlents, sizeof(ioctlent[0]), compare);
        while (iop > ioctlent) {
                iop--;
@@ -79,7 +80,7 @@ ioctl_print_code(const unsigned int code)
 {
        tprints("_IOC(");
        printflags(ioctl_dirs, _IOC_DIR(code), "_IOC_???");
-       tprintf(", 0x%02x, 0x%02x, 0x%02x)",
+       tprintf(", %#x, %#x, %#x)",
                _IOC_TYPE(code), _IOC_NR(code), _IOC_SIZE(code));
 }
 
@@ -91,7 +92,7 @@ evdev_decode_number(const unsigned int code)
        if (_IOC_DIR(code) == _IOC_WRITE) {
                if (nr >= 0xc0 && nr <= 0xc0 + 0x3f) {
                        tprints("EVIOCSABS(");
-                       printxval(evdev_abs, nr - 0xc0, "EV_???");
+                       printxval(evdev_abs, nr - 0xc0, "ABS_???");
                        tprints(")");
                        return 1;
                }
@@ -182,8 +183,10 @@ hiddev_decode_number(const unsigned int code)
 }
 
 static int
-ioctl_decode_command_number(const unsigned int code)
+ioctl_decode_command_number(struct tcb *tcp)
 {
+       const unsigned int code = tcp->u_arg[1];
+
        switch (_IOC_TYPE(code)) {
                case 'E':
                        return evdev_decode_number(code);
@@ -222,12 +225,24 @@ ioctl_decode_command_number(const unsigned int code)
 }
 
 static int
-ioctl_decode(struct tcb *tcp, unsigned int code, long arg)
+ioctl_decode(struct tcb *tcp)
 {
+       const unsigned int code = tcp->u_arg[1];
+       const kernel_ulong_t arg = tcp->u_arg[2];
+
        switch (_IOC_TYPE(code)) {
 #if defined(ALPHA) || defined(POWERPC)
-       case 'f': case 't': case 'T':
+       case 'f': {
+               int ret = file_ioctl(tcp, code, arg);
+               if (ret != RVAL_DECODED)
+                       return ret;
+       }
+       case 't':
+       case 'T':
+               return term_ioctl(tcp, code, arg);
 #else /* !ALPHA */
+       case 'f':
+               return file_ioctl(tcp, code, arg);
        case 0x54:
 #endif /* !ALPHA */
                return term_ioctl(tcp, code, arg);
@@ -236,13 +251,13 @@ ioctl_decode(struct tcb *tcp, unsigned int code, long arg)
        case 'p':
                return rtc_ioctl(tcp, code, arg);
        case 0x03:
+               return hdio_ioctl(tcp, code, arg);
        case 0x12:
-       case 'X':
                return block_ioctl(tcp, code, arg);
-#ifdef HAVE_SCSI_SG_H
+       case 'X':
+               return fs_x_ioctl(tcp, code, arg);
        case 0x22:
                return scsi_ioctl(tcp, code, arg);
-#endif
        case 'L':
                return loop_ioctl(tcp, code, arg);
        case 'M':
@@ -257,6 +272,20 @@ ioctl_decode(struct tcb *tcp, unsigned int code, long arg)
 #ifdef HAVE_LINUX_INPUT_H
        case 'E':
                return evdev_ioctl(tcp, code, arg);
+#endif
+#ifdef HAVE_LINUX_USERFAULTFD_H
+       case 0xaa:
+               return uffdio_ioctl(tcp, code, arg);
+#endif
+#ifdef HAVE_LINUX_BTRFS_H
+       case 0x94:
+               return btrfs_ioctl(tcp, code, arg);
+#endif
+       case 0xb7:
+               return nsfs_ioctl(tcp, code, arg);
+#ifdef HAVE_LINUX_DM_IOCTL_H
+       case 0xfd:
+               return dm_ioctl(tcp, code, arg);
 #endif
        default:
                break;
@@ -267,28 +296,40 @@ ioctl_decode(struct tcb *tcp, unsigned int code, long arg)
 SYS_FUNC(ioctl)
 {
        const struct_ioctlent *iop;
+       int ret;
 
        if (entering(tcp)) {
                printfd(tcp, tcp->u_arg[0]);
                tprints(", ");
-               if (!ioctl_decode_command_number(tcp->u_arg[1])) {
+               ret = ioctl_decode_command_number(tcp);
+               if (!(ret & IOCTL_NUMBER_STOP_LOOKUP)) {
                        iop = ioctl_lookup(tcp->u_arg[1]);
                        if (iop) {
+                               if (ret)
+                                       tprints(" or ");
                                tprints(iop->symbol);
                                while ((iop = ioctl_next_match(iop)))
                                        tprintf(" or %s", iop->symbol);
-                       } else {
+                       } else if (!ret) {
                                ioctl_print_code(tcp->u_arg[1]);
                        }
                }
-               ioctl_decode(tcp, tcp->u_arg[1], tcp->u_arg[2]);
+               ret = ioctl_decode(tcp);
+       } else {
+               ret = ioctl_decode(tcp) | RVAL_DECODED;
        }
-       else {
-               int ret = ioctl_decode(tcp, tcp->u_arg[1], tcp->u_arg[2]);
-               if (!ret)
-                       tprintf(", %#lx", tcp->u_arg[2]);
+
+       if (ret & RVAL_DECODED) {
+               ret &= ~RVAL_DECODED;
+               if (ret)
+                       --ret;
                else
-                       return ret - 1;
+                       tprintf(", %#" PRI_klx, tcp->u_arg[2]);
+               ret |= RVAL_DECODED;
+       } else {
+               if (ret)
+                       --ret;
        }
-       return 0;
+
+       return ret;
 }