(root)/
strace-6.5/
src/
print_timespec.h
       1  /*
       2   * Copyright (c) 2015-2016 Dmitry V. Levin <ldv@strace.io>
       3   * Copyright (c) 2016-2023 The strace developers.
       4   * All rights reserved.
       5   *
       6   * SPDX-License-Identifier: LGPL-2.1-or-later
       7   */
       8  
       9  #include "xstring.h"
      10  
      11  #ifndef TIMESPEC_NSEC
      12  # define TIMESPEC_NSEC tv_nsec
      13  #endif
      14  
      15  #ifndef UTIME_NOW
      16  # define UTIME_NOW ((1l << 30) - 1l)
      17  #endif
      18  #ifndef UTIME_OMIT
      19  # define UTIME_OMIT ((1l << 30) - 2l)
      20  #endif
      21  
      22  #define TIMESPEC_TO_SEC_NSEC(t_)	\
      23  	((long long) (t_)->tv_sec),	\
      24  	 zero_extend_signed_to_ull((t_)->TIMESPEC_NSEC)
      25  
      26  static const char timespec_fmt[] =
      27  	"{tv_sec=%lld, " STRINGIFY_VAL(TIMESPEC_NSEC) "=%llu}";
      28  
      29  static void
      30  print_timespec_t(const TIMESPEC_T *t)
      31  {
      32  	tprint_struct_begin();
      33  	PRINT_FIELD_D(*t, tv_sec);
      34  	tprint_struct_next();
      35  	tprints_field_name(STRINGIFY_VAL(TIMESPEC_NSEC));
      36  	PRINT_VAL_U(t->TIMESPEC_NSEC);
      37  	tprint_struct_end();
      38  }
      39  
      40  #if defined PRINT_TIMESPEC_DATA_SIZE || defined PRINT_TIMESPEC_ARRAY_DATA_SIZE
      41  static void
      42  print_unaligned_timespec_t(const void *arg)
      43  {
      44  	TIMESPEC_T t;
      45  	memcpy(&t, arg, sizeof(t));
      46  	print_timespec_t(&t);
      47  }
      48  #endif /* PRINT_TIMESPEC_DATA_SIZE || PRINT_TIMESPEC_ARRAY_DATA_SIZE */
      49  
      50  #ifdef PRINT_TIMESPEC_DATA_SIZE
      51  bool
      52  PRINT_TIMESPEC_DATA_SIZE(const void *arg, const size_t size)
      53  {
      54  	if (size < sizeof(TIMESPEC_T)) {
      55  		tprint_unavailable();
      56  		return false;
      57  	}
      58  
      59  	print_unaligned_timespec_t(arg);
      60  	return true;
      61  }
      62  #endif /* PRINT_TIMESPEC_DATA_SIZE */
      63  
      64  #ifdef PRINT_TIMESPEC_ARRAY_DATA_SIZE
      65  bool
      66  PRINT_TIMESPEC_ARRAY_DATA_SIZE(const void *arg, const unsigned int nmemb,
      67  			       const size_t size)
      68  {
      69  	if (nmemb > size / sizeof(TIMESPEC_T)) {
      70  		tprint_unavailable();
      71  		return false;
      72  	}
      73  
      74  	tprint_array_begin();
      75  
      76  	for (unsigned int i = 0; i < nmemb; i++, arg += sizeof(TIMESPEC_T)) {
      77  		if (i)
      78  			tprint_array_next();
      79  		print_unaligned_timespec_t(arg);
      80  	}
      81  
      82  	tprint_array_end();
      83  	return true;
      84  }
      85  #endif /* PRINT_TIMESPEC_ARRAY_DATA_SIZE */
      86  
      87  #ifdef PRINT_TIMESPEC
      88  int
      89  PRINT_TIMESPEC(struct tcb *const tcp, const kernel_ulong_t addr)
      90  {
      91  	TIMESPEC_T t;
      92  
      93  	if (umove_or_printaddr(tcp, addr, &t))
      94  		return -1;
      95  
      96  	print_timespec_t(&t);
      97  	return 0;
      98  }
      99  #endif /* PRINT_TIMESPEC */
     100  
     101  #ifdef SPRINT_TIMESPEC
     102  const char *
     103  SPRINT_TIMESPEC(struct tcb *const tcp, const kernel_ulong_t addr)
     104  {
     105  	TIMESPEC_T t;
     106  	static char buf[sizeof(timespec_fmt) + 3 * sizeof(t)];
     107  
     108  	if (!addr) {
     109  		strcpy(buf, "NULL");
     110  	} else if (!verbose(tcp) || (exiting(tcp) && syserror(tcp)) ||
     111  		   umove(tcp, addr, &t)) {
     112  		xsprintf(buf, "%#" PRI_klx, addr);
     113  	} else {
     114  		xsprintf(buf, timespec_fmt, TIMESPEC_TO_SEC_NSEC(&t));
     115  	}
     116  
     117  	return buf;
     118  }
     119  #endif /* SPRINT_TIMESPEC */
     120  
     121  #ifdef PRINT_TIMESPEC_UTIME_PAIR
     122  static bool
     123  print_timespec_t_utime(struct tcb *tcp, void *elem_buf, size_t elem_size,
     124  		       void *data)
     125  {
     126  	const TIMESPEC_T *const t = elem_buf;
     127  	switch (t->TIMESPEC_NSEC) {
     128  	case UTIME_NOW:
     129  	case UTIME_OMIT:
     130  		if (xlat_verbose(xlat_verbosity) != XLAT_STYLE_ABBREV)
     131  			print_timespec_t(t);
     132  		if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_RAW)
     133  			break;
     134  
     135  		(xlat_verbose(xlat_verbosity) == XLAT_STYLE_VERBOSE
     136  			? tprints_comment : tprints_string)(t->TIMESPEC_NSEC == UTIME_NOW
     137  				? "UTIME_NOW" : "UTIME_OMIT");
     138  		break;
     139  	default:
     140  		print_timespec_t(t);
     141  		tprints_comment(sprinttime_nsec(TIMESPEC_TO_SEC_NSEC(t)));
     142  		break;
     143  	}
     144  	return true;
     145  }
     146  
     147  int
     148  PRINT_TIMESPEC_UTIME_PAIR(struct tcb *const tcp, const kernel_ulong_t addr)
     149  {
     150  	TIMESPEC_T t[2];
     151  
     152  	if (umove_or_printaddr(tcp, addr, &t))
     153  		return -1;
     154  
     155  	print_local_array(tcp, t, print_timespec_t_utime);
     156  	return 0;
     157  }
     158  #endif /* PRINT_TIMESPEC_UTIME_PAIR */
     159  
     160  #ifdef PRINT_ITIMERSPEC
     161  int
     162  PRINT_ITIMERSPEC(struct tcb *const tcp, const kernel_ulong_t addr)
     163  {
     164  	struct { TIMESPEC_T it_interval, it_value; } t;
     165  
     166  	if (umove_or_printaddr(tcp, addr, &t))
     167  		return -1;
     168  
     169  	tprint_struct_begin();
     170  	PRINT_FIELD_OBJ_PTR(t, it_interval, print_timespec_t);
     171  	tprint_struct_next();
     172  	PRINT_FIELD_OBJ_PTR(t, it_value, print_timespec_t);
     173  	tprint_struct_end();
     174  	return 0;
     175  }
     176  #endif /* PRINT_ITIMERSPEC */