(root)/
strace-6.5/
src/
fs_f_ioctl.c
       1  /*
       2   * Copyright (c) 2016 Jeff Mahoney <jeffm@suse.com>
       3   * Copyright (c) 2016-2021 The strace developers.
       4   * All rights reserved.
       5   *
       6   * SPDX-License-Identifier: LGPL-2.1-or-later
       7   */
       8  
       9  #include "defs.h"
      10  #include <linux/fs.h>
      11  #include <linux/fiemap.h>
      12  #include "xlat/fiemap_flags.h"
      13  #include "xlat/fiemap_extent_flags.h"
      14  #include "xlat/fs_ioc_flags.h"
      15  
      16  static bool
      17  print_fiemap_extent(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
      18  {
      19  	const struct fiemap_extent *fe = elem_buf;
      20  
      21  	tprint_struct_begin();
      22  	PRINT_FIELD_U(*fe, fe_logical);
      23  	tprint_struct_next();
      24  	PRINT_FIELD_U(*fe, fe_physical);
      25  	tprint_struct_next();
      26  	PRINT_FIELD_U(*fe, fe_length);
      27  	tprint_struct_next();
      28  	PRINT_FIELD_FLAGS(*fe, fe_flags, fiemap_extent_flags,
      29  			  "FIEMAP_EXTENT_???");
      30  	tprint_struct_end();
      31  
      32  	return true;
      33  }
      34  
      35  static int
      36  decode_fiemap(struct tcb *const tcp, const kernel_ulong_t arg)
      37  {
      38  	struct fiemap args;
      39  
      40  	if (entering(tcp))
      41  		tprint_arg_next();
      42  	else if (syserror(tcp))
      43  		return RVAL_IOCTL_DECODED;
      44  	else
      45  		tprint_value_changed();
      46  
      47  	if (umove_or_printaddr(tcp, arg, &args))
      48  		return RVAL_IOCTL_DECODED;
      49  
      50  	if (entering(tcp)) {
      51  		tprint_struct_begin();
      52  		PRINT_FIELD_U(args, fm_start);
      53  		tprint_struct_next();
      54  		PRINT_FIELD_U(args, fm_length);
      55  		tprint_struct_next();
      56  		PRINT_FIELD_FLAGS(args, fm_flags, fiemap_flags,
      57  				  "FIEMAP_FLAG_???");
      58  		tprint_struct_next();
      59  		PRINT_FIELD_U(args, fm_extent_count);
      60  		tprint_struct_end();
      61  		return 0;
      62  	}
      63  
      64  	tprint_struct_begin();
      65  	PRINT_FIELD_FLAGS(args, fm_flags, fiemap_flags, "FIEMAP_FLAG_???");
      66  	tprint_struct_next();
      67  	PRINT_FIELD_U(args, fm_mapped_extents);
      68  	if (abbrev(tcp)) {
      69  		tprint_struct_next();
      70  		tprint_more_data_follows();
      71  	} else {
      72  		struct fiemap_extent fe;
      73  		tprint_struct_next();
      74  		tprints_field_name("fm_extents");
      75  		print_array(tcp, arg + offsetof(typeof(args), fm_extents),
      76  			    args.fm_mapped_extents, &fe, sizeof(fe),
      77  			    tfetch_mem, print_fiemap_extent, 0);
      78  	}
      79  	tprint_struct_end();
      80  
      81  	return RVAL_IOCTL_DECODED;
      82  }
      83  
      84  static void
      85  decode_fs_ioc_flags(struct tcb *const tcp, const kernel_ulong_t arg)
      86  {
      87  	unsigned int flags;
      88  
      89  	if (!umove_or_printaddr(tcp, arg, &flags)) {
      90  		tprint_indirect_begin();
      91  		printflags(fs_ioc_flags, flags, "FS_???_FL");
      92  		tprint_indirect_end();
      93  	}
      94  }
      95  
      96  int
      97  fs_f_ioctl(struct tcb *const tcp, const unsigned int code,
      98  	   const kernel_ulong_t arg)
      99  {
     100  	switch (code) {
     101  	case FS_IOC_FIEMAP:
     102  		return decode_fiemap(tcp, arg);
     103  
     104  	case FS_IOC_GETFLAGS:
     105  #if SIZEOF_LONG > 4
     106  	case FS_IOC32_GETFLAGS:
     107  #endif
     108  		if (entering(tcp))
     109  			return 0;
     110  		ATTRIBUTE_FALLTHROUGH;
     111  
     112  	case FS_IOC_SETFLAGS:
     113  #if SIZEOF_LONG > 4
     114  	case FS_IOC32_SETFLAGS:
     115  #endif
     116  		tprint_arg_next();
     117  		decode_fs_ioc_flags(tcp, arg);
     118  		break;
     119  
     120  	default:
     121  		return RVAL_DECODED;
     122  	};
     123  
     124  	return RVAL_IOCTL_DECODED;
     125  }