--- /dev/null
+/*
+ * Check decoding of WDIOC* commands of ioctl syscall.
+ *
+ * Copyright (c) 2019 The strace developers.
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "tests.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <linux/watchdog.h>
+
+#define XLAT_MACROS_ONLY
+#include "xlat/watchdog_ioctl_cmds.h"
+#undef XLAT_MACROS_ONLY
+
+#define RVAL_EBADF " = -1 EBADF (%m)\n"
+
+int
+main(void)
+{
+ int val = 123;
+
+ ioctl(-1, WDIOC_GETSTATUS, &val);
+ printf("ioctl(-1, WDIOC_GETSTATUS, %p)" RVAL_EBADF, &val);
+
+ ioctl(-1, WDIOC_GETBOOTSTATUS, &val);
+ printf("ioctl(-1, WDIOC_GETBOOTSTATUS, %p)" RVAL_EBADF, &val);
+
+ ioctl(-1, WDIOC_GETTEMP, &val);
+ printf("ioctl(-1, WDIOC_GETTEMP, %p)" RVAL_EBADF, &val);
+
+ ioctl(-1, WDIOC_GETTIMEOUT, &val);
+ printf("ioctl(-1, WDIOC_GETTIMEOUT, %p)" RVAL_EBADF, &val);
+
+ ioctl(-1, WDIOC_GETPRETIMEOUT, &val);
+ printf("ioctl(-1, WDIOC_GETPRETIMEOUT, %p)" RVAL_EBADF, &val);
+
+ ioctl(-1, WDIOC_GETTIMELEFT, &val);
+ printf("ioctl(-1, WDIOC_GETTIMELEFT, %p)" RVAL_EBADF, &val);
+
+ ioctl(-1, WDIOC_SETTIMEOUT, &val);
+ printf("ioctl(-1, WDIOC_SETTIMEOUT, [123])" RVAL_EBADF);
+
+ ioctl(-1, WDIOC_SETPRETIMEOUT, &val);
+ printf("ioctl(-1, WDIOC_SETPRETIMEOUT, [123])" RVAL_EBADF);
+
+ ioctl(-1, WDIOC_KEEPALIVE);
+ printf("ioctl(-1, WDIOC_KEEPALIVE)" RVAL_EBADF);
+
+ ioctl(-1, _IOC(_IOC_NONE, 'W', 0xff, 0), &val);
+ printf("ioctl(-1, _IOC(_IOC_NONE, %#x, 0xff, 0), %p)" RVAL_EBADF,
+ 'W', &val);
+
+ puts("+++ exited with 0 +++");
+ return 0;
+}
--- /dev/null
+/*
+ * Copyright (c) 2019 The strace developers.
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "defs.h"
+#include "print_fields.h"
+
+#include <linux/watchdog.h>
+
+#define XLAT_MACROS_ONLY
+#include "xlat/watchdog_ioctl_cmds.h"
+#undef XLAT_MACROS_ONLY
+
+int
+watchdog_ioctl(struct tcb *const tcp, const unsigned int code,
+ const kernel_ulong_t arg)
+{
+ switch (code) {
+ case WDIOC_GETSTATUS:
+ case WDIOC_GETBOOTSTATUS:
+ case WDIOC_GETTEMP:
+ case WDIOC_GETTIMEOUT:
+ case WDIOC_GETPRETIMEOUT:
+ case WDIOC_GETTIMELEFT:
+ if (entering(tcp))
+ return 0;
+ ATTRIBUTE_FALLTHROUGH;
+ case WDIOC_SETTIMEOUT:
+ case WDIOC_SETPRETIMEOUT:
+ tprints(", ");
+ printnum_int(tcp, arg, "%d");
+ break;
+
+ /*
+ * linux/watchdog.h says that this takes an int, but in
+ * practice the argument is ignored.
+ */
+ case WDIOC_KEEPALIVE:
+ break;
+ default:
+ return RVAL_DECODED;
+ }
+ return RVAL_IOCTL_DECODED;
+}
--- /dev/null
+WDIOC_GETSTATUS _IOR('W', 1, int)
+WDIOC_GETBOOTSTATUS _IOR('W', 2, int)
+WDIOC_GETTEMP _IOR('W', 3, int)
+WDIOC_GETTIMEOUT _IOR('W', 7, int)
+WDIOC_GETPRETIMEOUT _IOR('W', 9, int)
+WDIOC_GETTIMELEFT _IOR('W', 10, int)
+WDIOC_SETOPTIONS _IOR('W', 4, int)
+WDIOC_KEEPALIVE _IOR('W', 5, int)
+WDIOC_SETTIMEOUT _IOWR('W', 6, int)
+WDIOC_SETPRETIMEOUT _IOWR('W', 8, int)