(root)/
strace-6.5/
src/
dirent.c
       1  /*
       2   * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
       3   * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
       4   * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
       5   * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
       6   * Copyright (c) 2005-2015 Dmitry V. Levin <ldv@strace.io>
       7   * Copyright (c) 2014-2021 The strace developers.
       8   * All rights reserved.
       9   *
      10   * SPDX-License-Identifier: LGPL-2.1-or-later
      11   */
      12  
      13  #include "defs.h"
      14  #include "kernel_dirent.h"
      15  
      16  #include DEF_MPERS_TYPE(kernel_dirent_t)
      17  
      18  #include MPERS_DEFS
      19  
      20  #include "xgetdents.h"
      21  
      22  #define D_NAME_LEN_MAX 256
      23  
      24  /* The minimum size of a valid directory entry.  */
      25  static const unsigned int header_size =
      26  	offsetof(kernel_dirent_t, d_name);
      27  
      28  static void
      29  print_dentry_head(const kernel_dirent_t *const dent)
      30  {
      31  	tprint_struct_begin();
      32  	PRINT_FIELD_U(*dent, d_ino);
      33  	tprint_struct_next();
      34  	PRINT_FIELD_U(*dent, d_off);
      35  	tprint_struct_next();
      36  	PRINT_FIELD_U(*dent, d_reclen);
      37  }
      38  
      39  static unsigned int
      40  decode_dentry_head(struct tcb *const tcp, const void *const arg)
      41  {
      42  	const kernel_dirent_t *const dent = arg;
      43  
      44  	if (!abbrev(tcp))
      45  		print_dentry_head(dent);
      46  
      47  	return dent->d_reclen;
      48  }
      49  
      50  static int
      51  decode_dentry_tail(struct tcb *const tcp, kernel_ulong_t addr,
      52  		   const void *const arg, const unsigned int d_name_type_len)
      53  {
      54  	int rc = 0;
      55  
      56  	/* !abbrev(tcp) */
      57  
      58  	if (d_name_type_len) {
      59  		unsigned int d_name_len = d_name_type_len - 1;
      60  		if (d_name_len) {
      61  			if (d_name_len > D_NAME_LEN_MAX)
      62  				d_name_len = D_NAME_LEN_MAX;
      63  			tprint_struct_next();
      64  			tprints_field_name("d_name");
      65  			rc = printpathn(tcp, addr, d_name_len - 1);
      66  		}
      67  		tprint_struct_next();
      68  		tprints_field_name("d_type");
      69  		const kernel_ulong_t d_type_addr =
      70  			addr + (d_name_type_len - 1);
      71  		unsigned char d_type;
      72  		if (umove_or_printaddr(tcp, d_type_addr, &d_type))
      73  			rc = -1;
      74  		else
      75  			printxval(dirent_types, d_type, "DT_???");
      76  	}
      77  	tprint_struct_end();
      78  
      79  	return rc;
      80  }
      81  
      82  SYS_FUNC(getdents)
      83  {
      84  	return xgetdents(tcp, header_size,
      85  			 decode_dentry_head, decode_dentry_tail);
      86  }
      87  
      88  static void
      89  print_old_dirent(struct tcb *const tcp, const kernel_ulong_t addr)
      90  {
      91  	kernel_dirent_t dent;
      92  
      93  	if (umove_or_printaddr(tcp, addr, &dent))
      94  		return;
      95  
      96  	print_dentry_head(&dent);
      97  	tprint_struct_next();
      98  	tprints_field_name("d_name");
      99  	printpathn(tcp, addr + header_size,
     100  		   MIN(dent.d_reclen, D_NAME_LEN_MAX));
     101  	tprint_struct_end();
     102  }
     103  
     104  SYS_FUNC(readdir)
     105  {
     106  	if (entering(tcp)) {
     107  		/* fd */
     108  		printfd(tcp, tcp->u_arg[0]);
     109  #ifdef ENABLE_SECONTEXT
     110  		tcp->last_dirfd = (int) tcp->u_arg[0];
     111  #endif
     112  		tprint_arg_next();
     113  	} else {
     114  		/* dirp */
     115  		if (tcp->u_rval == 0)
     116  			printaddr(tcp->u_arg[1]);
     117  		else
     118  			print_old_dirent(tcp, tcp->u_arg[1]);
     119  
     120  		/* count */
     121  		const unsigned int count = tcp->u_arg[2];
     122  		/* Not much point in printing this out, it is always 1. */
     123  		if (count != 1) {
     124  			tprint_arg_next();
     125  			PRINT_VAL_U(count);
     126  		}
     127  	}
     128  	return 0;
     129  }