]> granicus.if.org Git - strace/blobdiff - loop.c
travis: add build environment information to the travis log
[strace] / loop.c
diff --git a/loop.c b/loop.c
index 6ce6545a0508f3f8255462503b26785484af999f..e30b7ce59b4a6a36b867f56f41dacd62a8d4d3f3 100644 (file)
--- a/loop.c
+++ b/loop.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2012 The Chromium OS Authors.
+ * Copyright (c) 2012-2017 The strace developers.
  * Written by Mike Frysinger <vapier@gentoo.org>.
  *
  * Redistribution and use in source and binary forms, with or without
  */
 
 #include "defs.h"
+#include <linux/ioctl.h>
+#include <linux/loop.h>
 
-#include <sys/ioctl.h>
+typedef struct loop_info struct_loop_info;
 
-#include <linux/loop.h>
+#include DEF_MPERS_TYPE(struct_loop_info)
+
+#include MPERS_DEFS
 
+#include "print_fields.h"
+#include "xlat/loop_cmds.h"
 #include "xlat/loop_flags_options.h"
 #include "xlat/loop_crypt_type_options.h"
 
-int
-loop_ioctl(struct tcb *tcp, const unsigned int code, long arg)
+static void
+decode_loop_info(struct tcb *const tcp, const kernel_ulong_t addr)
 {
-       struct loop_info info;
-       struct loop_info64 info64;
-       char *s = alloca((LO_NAME_SIZE + LO_KEY_SIZE) * 4);
+       struct_loop_info info;
 
-       if (entering(tcp))
-               return 0;
+       tprints(", ");
+       if (umove_or_printaddr(tcp, addr, &info))
+               return;
 
-       switch (code) {
+       tprintf("{lo_number=%d", info.lo_number);
 
-       case LOOP_SET_STATUS:
-       case LOOP_GET_STATUS:
-               if (!verbose(tcp) || umove(tcp, arg, &info) < 0)
-                       return 0;
+       if (!abbrev(tcp)) {
+               PRINT_FIELD_DEV(", ", info, lo_device);
+               tprintf(", lo_inode=%" PRI_klu, (kernel_ulong_t) info.lo_inode);
+               PRINT_FIELD_DEV(", ", info, lo_rdevice);
+       }
 
-               tprintf(", {number=%d", info.lo_number);
+       tprintf(", lo_offset=%#x", info.lo_offset);
+
+       if (!abbrev(tcp) || info.lo_encrypt_type != LO_CRYPT_NONE) {
+               tprints(", lo_encrypt_type=");
+               printxval(loop_crypt_type_options, info.lo_encrypt_type,
+                       "LO_CRYPT_???");
+               /*
+                * It is converted to unsigned before use in kernel, see
+                * loop_info64_from_old in drivers/block/loop.c
+                */
+               tprintf(", lo_encrypt_key_size=%" PRIu32,
+                       (uint32_t) info.lo_encrypt_key_size);
+       }
 
-               if (!abbrev(tcp)) {
-                       tprintf(", device=%#lx, inode=%lu, rdevice=%#lx",
-                               (unsigned long) info.lo_device,
-                               info.lo_inode,
-                               (unsigned long) info.lo_rdevice);
-               }
+       tprints(", lo_flags=");
+       printflags(loop_flags_options, info.lo_flags, "LO_FLAGS_???");
 
-               tprintf(", offset=%#x", info.lo_offset);
+       PRINT_FIELD_CSTRING(", ", info, lo_name);
 
-               if (!abbrev(tcp) || info.lo_encrypt_type != LO_CRYPT_NONE) {
-                       tprints(", encrypt_type=");
-                       printxval(loop_crypt_type_options, info.lo_encrypt_type,
-                               "LO_CRYPT_???");
-                       tprintf(", encrypt_key_size=%d", info.lo_encrypt_key_size);
-               }
+       if (!abbrev(tcp) || info.lo_encrypt_type != LO_CRYPT_NONE) {
+               const unsigned int lo_encrypt_key_size =
+                       MIN((unsigned) info.lo_encrypt_key_size, LO_KEY_SIZE);
+               PRINT_FIELD_STRING(", ", info, lo_encrypt_key,
+                                         lo_encrypt_key_size, 0);
+       }
 
-               tprints(", flags=");
-               printflags(loop_flags_options, info.lo_flags, "LO_FLAGS_???");
+       if (!abbrev(tcp))
+               tprintf(", lo_init=[%#" PRI_klx ", %#" PRI_klx "]"
+                       ", reserved=[%#hhx, %#hhx, %#hhx, %#hhx]}",
+                       (kernel_ulong_t) info.lo_init[0],
+                       (kernel_ulong_t) info.lo_init[1],
+                       info.reserved[0], info.reserved[1],
+                       info.reserved[2], info.reserved[3]);
+       else
+               tprints(", ...}");
+}
 
-               string_quote(info.lo_name, s, -1, LO_NAME_SIZE);
-               tprintf(", name=%s", s);
+static void
+decode_loop_info64(struct tcb *const tcp, const kernel_ulong_t addr)
+{
+       struct loop_info64 info64;
 
-               if (!abbrev(tcp) || info.lo_encrypt_type != LO_CRYPT_NONE) {
-                       string_quote((void *) info.lo_encrypt_key, s, 0, LO_KEY_SIZE);
-                       tprintf(", encrypt_key=%s", s);
-               }
+       tprints(", ");
+       if (umove_or_printaddr(tcp, addr, &info64))
+               return;
+
+       if (!abbrev(tcp)) {
+               PRINT_FIELD_DEV("{", info64, lo_device);
+               tprintf(", lo_inode=%" PRIu64, (uint64_t) info64.lo_inode);
+               PRINT_FIELD_DEV(", ", info64, lo_rdevice);
+               tprintf(", lo_offset=%#" PRIx64 ", lo_sizelimit=%" PRIu64
+                       ", lo_number=%" PRIu32,
+                       (uint64_t) info64.lo_offset,
+                       (uint64_t) info64.lo_sizelimit,
+                       (uint32_t) info64.lo_number);
+       } else {
+               tprintf("{lo_offset=%#" PRIx64 ", lo_number=%" PRIu32,
+                       (uint64_t) info64.lo_offset,
+                       (uint32_t) info64.lo_number);
+       }
 
-               if (!abbrev(tcp))
-                       tprintf(", init={%#lx, %#lx}"
-                               ", reserved={%#x, %#x, %#x, %#x}}",
-                               info.lo_init[0], info.lo_init[1],
-                               info.reserved[0], info.reserved[1],
-                               info.reserved[2], info.reserved[3]);
-               else
-                       tprints(", ...}");
+       if (!abbrev(tcp) || info64.lo_encrypt_type != LO_CRYPT_NONE) {
+               tprints(", lo_encrypt_type=");
+               printxval(loop_crypt_type_options, info64.lo_encrypt_type,
+                       "LO_CRYPT_???");
+               tprintf(", lo_encrypt_key_size=%" PRIu32,
+                       info64.lo_encrypt_key_size);
+       }
 
-               return 1;
+       tprints(", lo_flags=");
+       printflags(loop_flags_options, info64.lo_flags, "LO_FLAGS_???");
 
-       case LOOP_SET_STATUS64:
-       case LOOP_GET_STATUS64:
-               if (!verbose(tcp) || umove(tcp, arg, &info64) < 0)
+       PRINT_FIELD_CSTRING(", ", info64, lo_file_name);
+
+       if (!abbrev(tcp) || info64.lo_encrypt_type != LO_CRYPT_NONE) {
+               PRINT_FIELD_CSTRING(", ", info64, lo_crypt_name);
+               const unsigned int lo_encrypt_key_size =
+                       MIN((unsigned) info64.lo_encrypt_key_size, LO_KEY_SIZE);
+               PRINT_FIELD_STRING(", ", info64, lo_encrypt_key,
+                                         lo_encrypt_key_size, 0);
+       }
+
+       if (!abbrev(tcp))
+               tprintf(", lo_init=[%#" PRIx64 ", %#" PRIx64 "]}",
+                       (uint64_t) info64.lo_init[0],
+                       (uint64_t) info64.lo_init[1]);
+       else
+               tprints(", ...}");
+}
+
+MPERS_PRINTER_DECL(int, loop_ioctl,
+                  struct tcb *tcp, const unsigned int code,
+                  const kernel_ulong_t arg)
+{
+       switch (code) {
+       case LOOP_GET_STATUS:
+               if (entering(tcp))
                        return 0;
+               /* fall through */
+       case LOOP_SET_STATUS:
+               decode_loop_info(tcp, arg);
+               break;
 
-               tprints(", {");
-
-               if (!abbrev(tcp)) {
-                       tprintf("device=%" PRIu64 ", inode=%" PRIu64 ", "
-                               "rdevice=%" PRIu64 ", offset=%#" PRIx64 ", "
-                               "sizelimit=%" PRIu64 ", number=%" PRIu32,
-                               (uint64_t) info64.lo_device,
-                               (uint64_t) info64.lo_inode,
-                               (uint64_t) info64.lo_rdevice,
-                               (uint64_t) info64.lo_offset,
-                               (uint64_t) info64.lo_sizelimit,
-                               (uint32_t) info64.lo_number);
-               } else {
-                       tprintf("offset=%#" PRIx64 ", number=%" PRIu32,
-                               (uint64_t) info64.lo_offset,
-                               (uint32_t) info64.lo_number);
-               }
-
-               if (!abbrev(tcp) || info64.lo_encrypt_type != LO_CRYPT_NONE) {
-                       tprints(", encrypt_type=");
-                       printxval(loop_crypt_type_options, info64.lo_encrypt_type,
-                               "LO_CRYPT_???");
-                       tprintf(", encrypt_key_size=%" PRIu32,
-                               info64.lo_encrypt_key_size);
-               }
-
-               tprints(", flags=");
-               printflags(loop_flags_options, info64.lo_flags, "LO_FLAGS_???");
-
-               string_quote((void *) info64.lo_file_name, s, -1, LO_NAME_SIZE);
-               tprintf(", file_name=%s", s);
-
-               if (!abbrev(tcp) || info64.lo_encrypt_type != LO_CRYPT_NONE) {
-                       string_quote((void *) info64.lo_crypt_name, s, -1, LO_NAME_SIZE);
-                       tprintf(", crypt_name=%s", s);
-                       string_quote((void *) info64.lo_encrypt_key, s, 0, LO_KEY_SIZE);
-                       tprintf(", encrypt_key=%s", s);
-               }
-
-               if (!abbrev(tcp))
-                       tprintf(", init={%#" PRIx64 ", %#" PRIx64 "}}",
-                               (uint64_t) info64.lo_init[0],
-                               (uint64_t) info64.lo_init[1]);
-               else
-                       tprints(", ...}");
-
-               return 1;
+       case LOOP_GET_STATUS64:
+               if (entering(tcp))
+                       return 0;
+               /* fall through */
+       case LOOP_SET_STATUS64:
+               decode_loop_info64(tcp, arg);
+               break;
 
        case LOOP_CLR_FD:
-#ifdef LOOP_SET_CAPACITY
        case LOOP_SET_CAPACITY:
-#endif
-#ifdef LOOP_CTL_GET_FREE
        /* newer loop-control stuff */
        case LOOP_CTL_GET_FREE:
-#endif
                /* Takes no arguments */
-               return 1;
+               break;
 
        case LOOP_SET_FD:
        case LOOP_CHANGE_FD:
-#ifdef LOOP_CTL_ADD
+               tprints(", ");
+               printfd(tcp, arg);
+               break;
+
        /* newer loop-control stuff */
        case LOOP_CTL_ADD:
        case LOOP_CTL_REMOVE:
-#endif
-               /* These take simple args, so let default printer handle it */
+               tprintf(", %d", (int) arg);
+               break;
+
+       case LOOP_SET_DIRECT_IO:
+               tprintf(", %" PRI_klu, arg);
+               break;
 
        default:
-               return 0;
+               return RVAL_DECODED;
        }
+
+       return RVAL_DECODED | 1;
 }