summaryrefslogtreecommitdiff
path: root/src/fs_f_ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fs_f_ioctl.c')
-rw-r--r--src/fs_f_ioctl.c128
1 files changed, 128 insertions, 0 deletions
diff --git a/src/fs_f_ioctl.c b/src/fs_f_ioctl.c
new file mode 100644
index 000000000..d0de799f9
--- /dev/null
+++ b/src/fs_f_ioctl.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2016 Jeff Mahoney <jeffm@suse.com>
+ * Copyright (c) 2016-2021 The strace developers.
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "defs.h"
+#include <linux/fs.h>
+#include "types/fiemap.h"
+#include "xlat/fiemap_flags.h"
+#include "xlat/fiemap_extent_flags.h"
+#include "xlat/fs_ioc_flags.h"
+#define XLAT_MACROS_ONLY
+# include "xlat/fs_f_ioctl_cmds.h"
+#undef XLAT_MACROS_ONLY
+
+static bool
+print_fiemap_extent(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
+{
+ const struct_fiemap_extent *fe = elem_buf;
+
+ tprint_struct_begin();
+ PRINT_FIELD_U(*fe, fe_logical);
+ tprint_struct_next();
+ PRINT_FIELD_U(*fe, fe_physical);
+ tprint_struct_next();
+ PRINT_FIELD_U(*fe, fe_length);
+ tprint_struct_next();
+ PRINT_FIELD_FLAGS(*fe, fe_flags, fiemap_extent_flags,
+ "FIEMAP_EXTENT_???");
+ tprint_struct_end();
+
+ return true;
+}
+
+static int
+decode_fiemap(struct tcb *const tcp, const kernel_ulong_t arg)
+{
+ struct_fiemap args;
+
+ if (entering(tcp))
+ tprints(", ");
+ else if (syserror(tcp))
+ return RVAL_IOCTL_DECODED;
+ else
+ tprint_value_changed();
+
+ if (umove_or_printaddr(tcp, arg, &args))
+ return RVAL_IOCTL_DECODED;
+
+ if (entering(tcp)) {
+ tprint_struct_begin();
+ PRINT_FIELD_U(args, fm_start);
+ tprint_struct_next();
+ PRINT_FIELD_U(args, fm_length);
+ tprint_struct_next();
+ PRINT_FIELD_FLAGS(args, fm_flags, fiemap_flags,
+ "FIEMAP_FLAG_???");
+ tprint_struct_next();
+ PRINT_FIELD_U(args, fm_extent_count);
+ tprint_struct_end();
+ return 0;
+ }
+
+ tprint_struct_begin();
+ PRINT_FIELD_FLAGS(args, fm_flags, fiemap_flags, "FIEMAP_FLAG_???");
+ tprint_struct_next();
+ PRINT_FIELD_U(args, fm_mapped_extents);
+ if (abbrev(tcp)) {
+ tprint_struct_next();
+ tprint_more_data_follows();
+ } else {
+ struct_fiemap_extent fe;
+ tprint_struct_next();
+ tprints_field_name("fm_extents");
+ print_array(tcp, arg + offsetof(typeof(args), fm_extents),
+ args.fm_mapped_extents, &fe, sizeof(fe),
+ tfetch_mem, print_fiemap_extent, 0);
+ }
+ tprint_struct_end();
+
+ return RVAL_IOCTL_DECODED;
+}
+
+static void
+decode_fs_ioc_flags(struct tcb *const tcp, const kernel_ulong_t arg)
+{
+ unsigned int flags;
+
+ if (!umove_or_printaddr(tcp, arg, &flags)) {
+ tprints("[");
+ printflags(fs_ioc_flags, flags, "FS_???_FL");
+ tprints("]");
+ }
+}
+
+int
+fs_f_ioctl(struct tcb *const tcp, const unsigned int code,
+ const kernel_ulong_t arg)
+{
+ switch (code) {
+ case FS_IOC_FIEMAP:
+ return decode_fiemap(tcp, arg);
+
+ case FS_IOC_GETFLAGS:
+#if SIZEOF_LONG > 4
+ case FS_IOC32_GETFLAGS:
+#endif
+ if (entering(tcp))
+ return 0;
+ ATTRIBUTE_FALLTHROUGH;
+
+ case FS_IOC_SETFLAGS:
+#if SIZEOF_LONG > 4
+ case FS_IOC32_SETFLAGS:
+#endif
+ tprints(", ");
+ decode_fs_ioc_flags(tcp, arg);
+ break;
+
+ default:
+ return RVAL_DECODED;
+ };
+
+ return RVAL_IOCTL_DECODED;
+}