(root)/
strace-6.5/
src/
file_handle.c
       1  /*
       2   * Copyright (c) 2015 Dmitry V. Levin <ldv@strace.io>
       3   * Copyright (c) 2015-2023 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/fcntl.h>
      11  #include "xlat/name_to_handle_at_flags.h"
      12  
      13  #ifndef MAX_HANDLE_SZ
      14  # define MAX_HANDLE_SZ 128
      15  #endif
      16  
      17  typedef struct {
      18  	unsigned int handle_bytes;
      19  	int handle_type;
      20  } file_handle_header;
      21  
      22  static void
      23  print_f_handle(struct tcb *tcp, kernel_ulong_t addr, unsigned int handle_bytes)
      24  {
      25  	unsigned int len = MIN(handle_bytes, MAX_HANDLE_SZ);
      26  	char f_handle[MAX_HANDLE_SZ];
      27  	addr += sizeof(file_handle_header);
      28  	if (addr > sizeof(file_handle_header) &&
      29  	    !umoven(tcp, addr, len, f_handle)) {
      30  		print_quoted_string(f_handle, len, QUOTE_FORCE_HEX);
      31  		if (handle_bytes > len)
      32  			tprint_more_data_follows();
      33  	} else {
      34  		tprint_unavailable();
      35  	}
      36  }
      37  
      38  SYS_FUNC(name_to_handle_at)
      39  {
      40  	file_handle_header h;
      41  	const kernel_ulong_t addr = tcp->u_arg[2];
      42  
      43  	if (entering(tcp)) {
      44  		/* dirfd */
      45  		print_dirfd(tcp, tcp->u_arg[0]);
      46  		tprint_arg_next();
      47  
      48  		/* pathname */
      49  		printpath(tcp, tcp->u_arg[1]);
      50  		tprint_arg_next();
      51  
      52  		/* handle */
      53  		if (umove_or_printaddr(tcp, addr, &h)) {
      54  			tprint_arg_next();
      55  
      56  			/* mount_id */
      57  			printaddr(tcp->u_arg[3]);
      58  			tprint_arg_next();
      59  
      60  			/* flags */
      61  			printflags(name_to_handle_at_flags, tcp->u_arg[4],
      62  				   "AT_???");
      63  
      64  			return RVAL_DECODED;
      65  		}
      66  
      67  		tprint_struct_begin();
      68  		PRINT_FIELD_U(h, handle_bytes);
      69  
      70  		set_tcb_priv_ulong(tcp, h.handle_bytes);
      71  
      72  		return 0;
      73  	} else {
      74  		if ((!syserror(tcp) || EOVERFLOW == tcp->u_error)
      75  		    && !umove(tcp, addr, &h)) {
      76  
      77  			if (h.handle_bytes != get_tcb_priv_ulong(tcp)) {
      78  				tprint_value_changed();
      79  				PRINT_VAL_U(h.handle_bytes);
      80  			}
      81  			if (!syserror(tcp)) {
      82  				tprint_struct_next();
      83  				PRINT_FIELD_D(h, handle_type);
      84  				tprint_struct_next();
      85  				tprints_field_name("f_handle");
      86  				print_f_handle(tcp, addr, h.handle_bytes);
      87  			}
      88  		}
      89  		tprint_struct_end();
      90  		tprint_arg_next();
      91  
      92  		/* mount_id */
      93  		printnum_int(tcp, tcp->u_arg[3], "%d");
      94  		tprint_arg_next();
      95  
      96  		/* flags */
      97  		printflags(name_to_handle_at_flags, tcp->u_arg[4], "AT_???");
      98  	}
      99  	return 0;
     100  }
     101  
     102  SYS_FUNC(open_by_handle_at)
     103  {
     104  	file_handle_header h;
     105  	const kernel_ulong_t addr = tcp->u_arg[1];
     106  
     107  	/* mount_fd */
     108  	printfd(tcp, tcp->u_arg[0]);
     109  	tprint_arg_next();
     110  
     111  	/* handle */
     112  	if (!umove_or_printaddr(tcp, addr, &h)) {
     113  		tprint_struct_begin();
     114  		PRINT_FIELD_U(h, handle_bytes);
     115  		tprint_struct_next();
     116  		PRINT_FIELD_D(h, handle_type);
     117  		tprint_struct_next();
     118  		tprints_field_name("f_handle");
     119  		print_f_handle(tcp, addr, h.handle_bytes);
     120  		tprint_struct_end();
     121  	}
     122  	tprint_arg_next();
     123  
     124  	/* flags */
     125  	tprint_open_modes(tcp->u_arg[2]);
     126  
     127  	return RVAL_DECODED | RVAL_FD;
     128  }