(root)/
strace-6.5/
src/
fs_0x94_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  
      12  static void
      13  decode_file_clone_range(struct tcb *const tcp, const kernel_ulong_t arg)
      14  {
      15  	struct file_clone_range range;
      16  
      17  	if (!umove_or_printaddr(tcp, arg, &range)) {
      18  		tprint_struct_begin();
      19  		PRINT_FIELD_FD(range, src_fd, tcp);
      20  		tprint_struct_next();
      21  		PRINT_FIELD_U(range, src_offset);
      22  		tprint_struct_next();
      23  		PRINT_FIELD_U(range, src_length);
      24  		tprint_struct_next();
      25  		PRINT_FIELD_U(range, dest_offset);
      26  		tprint_struct_end();
      27  	}
      28  }
      29  
      30  static bool
      31  print_file_dedupe_range_info(struct tcb *tcp, void *elem_buf,
      32  			     size_t elem_size, void *data)
      33  {
      34  	const struct file_dedupe_range_info *info = elem_buf;
      35  	unsigned int *count = data;
      36  
      37  	if (count) {
      38  		if (*count == 0) {
      39  			tprint_more_data_follows();
      40  			return false;
      41  		}
      42  		--*count;
      43  	}
      44  
      45  	if (entering(tcp)) {
      46  		tprint_struct_begin();
      47  		PRINT_FIELD_FD(*info, dest_fd, tcp);
      48  		tprint_struct_next();
      49  		PRINT_FIELD_U(*info, dest_offset);
      50  	} else {
      51  		tprint_struct_begin();
      52  		PRINT_FIELD_U(*info, bytes_deduped);
      53  		tprint_struct_next();
      54  		PRINT_FIELD_D(*info, status);
      55  	}
      56  	tprint_struct_end();
      57  
      58  	return true;
      59  }
      60  
      61  static int
      62  decode_file_dedupe_range(struct tcb *const tcp, const kernel_ulong_t arg)
      63  {
      64  	struct file_dedupe_range range;
      65  	struct file_dedupe_range_info info;
      66  	unsigned int *limit = NULL;
      67  	unsigned int count = 2;
      68  	bool rc;
      69  
      70  	if (entering(tcp))
      71  		tprint_arg_next();
      72  	else if (syserror(tcp))
      73  		return RVAL_IOCTL_DECODED;
      74  	else
      75  		tprint_value_changed();
      76  
      77  	if (umove_or_printaddr(tcp, arg, &range))
      78  		return RVAL_IOCTL_DECODED;
      79  
      80  	tprint_struct_begin();
      81  
      82  	if (entering(tcp)) {
      83  		PRINT_FIELD_U(range, src_offset);
      84  		tprint_struct_next();
      85  		PRINT_FIELD_U(range, src_length);
      86  		tprint_struct_next();
      87  		PRINT_FIELD_U(range, dest_count);
      88  		tprint_struct_next();
      89  	}
      90  
      91  	tprints_field_name("info");
      92  
      93  	/* Limit how many elements we print in abbrev mode. */
      94  	if (abbrev(tcp) && range.dest_count > count)
      95  		limit = &count;
      96  
      97  	rc = print_array(tcp, arg + offsetof(typeof(range), info),
      98  			 range.dest_count, &info, sizeof(info),
      99  			 tfetch_mem,
     100  			 print_file_dedupe_range_info, limit);
     101  
     102  	tprint_struct_end();
     103  
     104  	if (!rc || exiting(tcp))
     105  		return RVAL_IOCTL_DECODED;
     106  
     107  	return 0;
     108  }
     109  
     110  static void
     111  decode_fslabel(struct tcb *const tcp, const kernel_ulong_t arg)
     112  {
     113  	char label[FSLABEL_MAX];
     114  
     115  	if (!umove_or_printaddr(tcp, arg, &label))
     116  		print_quoted_cstring(label, sizeof(label));
     117  }
     118  
     119  int
     120  fs_0x94_ioctl(struct tcb *const tcp, const unsigned int code,
     121  	      const kernel_ulong_t arg)
     122  {
     123  	switch (code) {
     124  	case FICLONE:	/* W */
     125  		tprint_arg_next();
     126  		PRINT_VAL_D((int) arg);
     127  		break;
     128  
     129  	case FICLONERANGE:	/* W */
     130  		tprint_arg_next();
     131  		decode_file_clone_range(tcp, arg);
     132  		break;
     133  
     134  	case FIDEDUPERANGE:	/* WR */
     135  		return decode_file_dedupe_range(tcp, arg);
     136  
     137  	case FS_IOC_GETFSLABEL:	/* R */
     138  		if (entering(tcp))
     139  			return 0;
     140  		ATTRIBUTE_FALLTHROUGH;
     141  
     142  	case FS_IOC_SETFSLABEL:	/* W */
     143  		tprint_arg_next();
     144  		decode_fslabel(tcp, arg);
     145  		break;
     146  
     147  	default:
     148  		return btrfs_ioctl(tcp, code, arg);
     149  	};
     150  
     151  	return RVAL_IOCTL_DECODED;
     152  }