(root)/
strace-6.5/
tests-mx32/
ioctl_fiemap.c
       1  /*
       2   * Check decoding of FS_IOC_FIEMAP ioctl command.
       3   *
       4   * Copyright (c) 2016-2021 The strace developers.
       5   * All rights reserved.
       6   *
       7   * SPDX-License-Identifier: GPL-2.0-or-later
       8   */
       9  
      10  #include "tests.h"
      11  
      12  #include <stdio.h>
      13  #include <stdlib.h>
      14  #include <sys/ioctl.h>
      15  #include <linux/types.h>
      16  #include <linux/fiemap.h>
      17  #include <linux/fs.h>
      18  
      19  static const char *errstr;
      20  
      21  static int
      22  do_ioctl(kernel_ulong_t cmd, kernel_ulong_t arg)
      23  {
      24  	int rc = ioctl(-1, cmd, arg);
      25  	errstr = sprintrc(rc);
      26  
      27  #ifdef INJECT_RETVAL
      28  	if (rc != INJECT_RETVAL)
      29  		error_msg_and_fail("Return value [%d] does not match"
      30  				   " expectations [%d]", rc, INJECT_RETVAL);
      31  
      32  	static char inj_errstr[4096];
      33  
      34  	snprintf(inj_errstr, sizeof(inj_errstr), "%s (INJECTED)", errstr);
      35  	errstr = inj_errstr;
      36  #endif
      37  
      38  	return rc;
      39  }
      40  
      41  static int
      42  do_ioctl_ptr(kernel_ulong_t cmd, const void *arg)
      43  {
      44  	return do_ioctl(cmd, (uintptr_t) arg);
      45  }
      46  
      47  #ifdef INJECT_RETVAL
      48  static void
      49  skip_ioctls(int argc, const char *argv[])
      50  {
      51  	if (argc < 2)
      52  		error_msg_and_fail("Usage: %s NUM_SKIP", argv[0]);
      53  
      54  	unsigned long num_skip = strtoul(argv[1], NULL, 0);
      55  
      56  	for (size_t i = 0; i < num_skip; ++i) {
      57  		int rc = ioctl(-1, FS_IOC_FIEMAP, 0);
      58  
      59  		printf("ioctl(-1, %s, NULL) = %s%s\n",
      60  		       XLAT_STR(FS_IOC_FIEMAP), sprintrc(rc),
      61  		       rc == INJECT_RETVAL ? " (INJECTED)" : "");
      62  
      63  		if (rc == INJECT_RETVAL)
      64  			return;
      65  	}
      66  
      67  	error_msg_and_fail("Issued %lu ioctl syscalls but failed"
      68  			   " to detect an injected return code %d",
      69  			   num_skip, INJECT_RETVAL);
      70  }
      71  #endif /* INJECT_RETVAL */
      72  
      73  int
      74  main(int argc, const char *argv[])
      75  {
      76  #ifdef INJECT_RETVAL
      77  	skip_ioctls(argc, argv);
      78  #endif
      79  
      80  	TAIL_ALLOC_OBJECT_VAR_PTR(struct fiemap, fiemap);
      81  
      82  	do_ioctl_ptr(FS_IOC_FIEMAP, (char *) fiemap + 1);
      83  	printf("ioctl(-1, %s, %p) = %s\n",
      84  	       XLAT_STR(FS_IOC_FIEMAP), (char *) fiemap + 1, errstr);
      85  
      86  #define VALID_FM_FLAGS        0x7
      87  #define INVALID_FM_FLAGS 0xfffffff8
      88  
      89  	fiemap->fm_start = (typeof(fiemap->fm_start)) 0xdeadbeefcafef00dULL;
      90  	fiemap->fm_length = (typeof(fiemap->fm_length)) 0xfacefeedbabec0deULL;
      91  	fiemap->fm_flags = VALID_FM_FLAGS;
      92  	fiemap->fm_mapped_extents = 0xbadc0ded;
      93  	fiemap->fm_extent_count = 0xdeadc0de;
      94  
      95  	int rc = do_ioctl_ptr(FS_IOC_FIEMAP, fiemap);
      96  	printf("ioctl(-1, %s, {fm_start=%ju, fm_length=%ju"
      97  	       ", fm_flags=%s, fm_extent_count=%u}",
      98  	       XLAT_STR(FS_IOC_FIEMAP),
      99  	       (uintmax_t) fiemap->fm_start, (uintmax_t) fiemap->fm_length,
     100  	       XLAT_KNOWN(VALID_FM_FLAGS,
     101  			  "FIEMAP_FLAG_SYNC|FIEMAP_FLAG_XATTR|"
     102  			  "FIEMAP_FLAG_CACHE"),
     103  	       fiemap->fm_extent_count);
     104  	if (rc < 0) {
     105  		printf(") = %s\n", errstr);
     106  	} else {
     107  		printf(" => {fm_flags=%s, fm_mapped_extents=%u, ",
     108  		       XLAT_KNOWN(VALID_FM_FLAGS,
     109  				  "FIEMAP_FLAG_SYNC|FIEMAP_FLAG_XATTR|"
     110  				  "FIEMAP_FLAG_CACHE"),
     111  		       fiemap->fm_mapped_extents);
     112  #if VERBOSE
     113  		printf("fm_extents=%p", fiemap + 1);
     114  #else
     115  		printf("...");
     116  #endif
     117  		printf("}) = %s\n", errstr);
     118  	}
     119  
     120  #define VALID_FE_FLAGS     0x3f8f
     121  #define INVALID_FE_FLAGS 0xffffc070
     122  
     123  	fiemap = tail_alloc(sizeof(*fiemap) + 2 * sizeof(fiemap->fm_extents[0]));
     124  	fiemap->fm_start = (typeof(fiemap->fm_start)) 0xdeadbeefcafef00dULL;
     125  	fiemap->fm_length = (typeof(fiemap->fm_length)) 0xfacefeedbabec0deULL;
     126  	fiemap->fm_flags = ~VALID_FM_FLAGS;
     127  	fiemap->fm_mapped_extents = 2;
     128  	fiemap->fm_extent_count = 0xdeadc0de;
     129  
     130  	fiemap->fm_extents[0].fe_logical = 0xfacefed1deadbef1;
     131  	fiemap->fm_extents[0].fe_physical = 0xfacefed2deadbef2;
     132  	fiemap->fm_extents[0].fe_length = 0xfacefed3deadbef3;
     133  	fiemap->fm_extents[0].fe_flags = VALID_FE_FLAGS;
     134  
     135  	fiemap->fm_extents[1].fe_logical = 0xfacefed1deadbef4;
     136  	fiemap->fm_extents[1].fe_physical = 0xfacefed2deadbef5;
     137  	fiemap->fm_extents[1].fe_length = 0xfacefed3deadbef6;
     138  	fiemap->fm_extents[1].fe_flags = ~VALID_FE_FLAGS;
     139  
     140  	rc = do_ioctl_ptr(FS_IOC_FIEMAP, fiemap);
     141  	printf("ioctl(-1, %s, {fm_start=%ju, fm_length=%ju"
     142  	       ", fm_flags=%s, fm_extent_count=%u}",
     143  	       XLAT_STR(FS_IOC_FIEMAP),
     144  	       (uintmax_t) fiemap->fm_start, (uintmax_t) fiemap->fm_length,
     145  	       XLAT_UNKNOWN(INVALID_FM_FLAGS, "FIEMAP_FLAG_???"),
     146  	       fiemap->fm_extent_count);
     147  	if (rc < 0) {
     148  		printf(") = %s\n", errstr);
     149  	} else {
     150  		printf(" => {fm_flags=%s, fm_mapped_extents=%u, ",
     151  		       XLAT_UNKNOWN(INVALID_FM_FLAGS, "FIEMAP_FLAG_???"),
     152  		       fiemap->fm_mapped_extents);
     153  #if VERBOSE
     154  		printf("fm_extents=[{fe_logical=%ju, fe_physical=%ju"
     155  		       ", fe_length=%ju, fe_flags=%s}"
     156  		       ", {fe_logical=%ju, fe_physical=%ju"
     157  		       ", fe_length=%ju, fe_flags=%s}]",
     158  		       (uintmax_t) fiemap->fm_extents[0].fe_logical,
     159  		       (uintmax_t) fiemap->fm_extents[0].fe_physical,
     160  		       (uintmax_t) fiemap->fm_extents[0].fe_length,
     161  		       XLAT_KNOWN(VALID_FE_FLAGS,
     162  			          "FIEMAP_EXTENT_LAST|"
     163  				  "FIEMAP_EXTENT_UNKNOWN|"
     164  				  "FIEMAP_EXTENT_DELALLOC|"
     165  				  "FIEMAP_EXTENT_ENCODED|"
     166  				  "FIEMAP_EXTENT_DATA_ENCRYPTED|"
     167  				  "FIEMAP_EXTENT_NOT_ALIGNED|"
     168  				  "FIEMAP_EXTENT_DATA_INLINE|"
     169  				  "FIEMAP_EXTENT_DATA_TAIL|"
     170  				  "FIEMAP_EXTENT_UNWRITTEN|"
     171  				  "FIEMAP_EXTENT_MERGED|"
     172  				  "FIEMAP_EXTENT_SHARED"),
     173  		       (uintmax_t) fiemap->fm_extents[1].fe_logical,
     174  		       (uintmax_t) fiemap->fm_extents[1].fe_physical,
     175  		       (uintmax_t) fiemap->fm_extents[1].fe_length,
     176  		       XLAT_UNKNOWN(INVALID_FE_FLAGS, "FIEMAP_EXTENT_???"));
     177  #else
     178  		printf("...");
     179  #endif
     180  		printf("}) = %s\n", errstr);
     181  	}
     182  
     183  	/* The live version of this test is in btrfs.c */
     184  
     185  	puts("+++ exited with 0 +++");
     186  	return 0;
     187  }