ioctl: print unrecognized ioctl codes in _IOC(dir,type,nr,size) format

* defs.h (ioctl_print_code): New prototype.
* ioctl.c: Include xlat/ioctl_dirs.h.
(ioctl_print_code): New function.
* io.c (sys_ioctl): Use it.
* xlat/ioctl_dirs.in: New file.
diff --git a/defs.h b/defs.h
index a91031b..33cdef0 100644
--- a/defs.h
+++ b/defs.h
@@ -733,6 +733,7 @@
 
 extern const struct_ioctlent *ioctl_lookup(const unsigned int);
 extern const struct_ioctlent *ioctl_next_match(const struct_ioctlent *);
+extern void ioctl_print_code(const unsigned int);
 extern int ioctl_decode(struct tcb *, const unsigned int, long);
 extern int block_ioctl(struct tcb *, const unsigned int, long);
 extern int loop_ioctl(struct tcb *, const unsigned int, long);
diff --git a/io.c b/io.c
index 87bdbba..2a36c00 100644
--- a/io.c
+++ b/io.c
@@ -404,7 +404,7 @@
 			while ((iop = ioctl_next_match(iop)))
 				tprintf(" or %s", iop->symbol);
 		} else
-			tprintf("%#lx", tcp->u_arg[1]);
+			ioctl_print_code(tcp->u_arg[1]);
 		ioctl_decode(tcp, tcp->u_arg[1], tcp->u_arg[2]);
 	}
 	else {
diff --git a/ioctl.c b/ioctl.c
index 3d867f7..f9d570e 100644
--- a/ioctl.c
+++ b/ioctl.c
@@ -30,6 +30,7 @@
 
 #include "defs.h"
 #include <asm/ioctl.h>
+#include "xlat/ioctl_dirs.h"
 
 static int
 compare(const void *a, const void *b)
@@ -67,6 +68,15 @@
 	return NULL;
 }
 
+void
+ioctl_print_code(const unsigned int code)
+{
+	tprints("_IOC(");
+	printflags(ioctl_dirs, _IOC_DIR(code), "_IOC_???");
+	tprintf(", 0x%02x, 0x%02x, 0x%02x)",
+		_IOC_TYPE(code), _IOC_NR(code), _IOC_SIZE(code));
+}
+
 int
 ioctl_decode(struct tcb *tcp, unsigned int code, long arg)
 {
diff --git a/xlat/ioctl_dirs.in b/xlat/ioctl_dirs.in
new file mode 100644
index 0000000..4c97a86
--- /dev/null
+++ b/xlat/ioctl_dirs.in
@@ -0,0 +1,3 @@
+_IOC_READ
+_IOC_WRITE
+_IOC_NONE