Mirror of strace – the linux syscall tracer
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

dirent.c 3.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  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@altlinux.org>
  7. * Copyright (c) 2014-2018 The strace developers.
  8. * All rights reserved.
  9. *
  10. * SPDX-License-Identifier: LGPL-2.1-or-later
  11. */
  12. #include "defs.h"
  13. #include DEF_MPERS_TYPE(kernel_dirent)
  14. #include MPERS_DEFS
  15. #define D_NAME_LEN_MAX 256
  16. static void
  17. print_old_dirent(struct tcb *const tcp, const kernel_ulong_t addr)
  18. {
  19. kernel_dirent d;
  20. if (umove_or_printaddr(tcp, addr, &d))
  21. return;
  22. tprintf("{d_ino=%llu, d_off=%llu, d_reclen=%u, d_name=",
  23. zero_extend_signed_to_ull(d.d_ino),
  24. zero_extend_signed_to_ull(d.d_off), d.d_reclen);
  25. if (d.d_reclen > D_NAME_LEN_MAX)
  26. d.d_reclen = D_NAME_LEN_MAX;
  27. printpathn(tcp, addr + offsetof(kernel_dirent, d_name), d.d_reclen);
  28. tprints("}");
  29. }
  30. SYS_FUNC(readdir)
  31. {
  32. if (entering(tcp)) {
  33. printfd(tcp, tcp->u_arg[0]);
  34. tprints(", ");
  35. } else {
  36. if (tcp->u_rval == 0)
  37. printaddr(tcp->u_arg[1]);
  38. else
  39. print_old_dirent(tcp, tcp->u_arg[1]);
  40. /* Not much point in printing this out, it is always 1. */
  41. if (tcp->u_arg[2] != 1)
  42. tprintf(", %" PRI_klu, tcp->u_arg[2]);
  43. }
  44. return 0;
  45. }
  46. SYS_FUNC(getdents)
  47. {
  48. unsigned int i, len, dents = 0;
  49. unsigned char *buf;
  50. if (entering(tcp)) {
  51. printfd(tcp, tcp->u_arg[0]);
  52. return 0;
  53. }
  54. const unsigned int count = tcp->u_arg[2];
  55. if (syserror(tcp) || !verbose(tcp)) {
  56. tprints(", ");
  57. printaddr(tcp->u_arg[1]);
  58. tprintf(", %u", count);
  59. return 0;
  60. }
  61. /* Beware of insanely large or too small values in tcp->u_rval */
  62. if (tcp->u_rval > 1024*1024)
  63. len = 1024*1024;
  64. else if (tcp->u_rval < (int) sizeof(kernel_dirent))
  65. len = 0;
  66. else
  67. len = tcp->u_rval;
  68. if (len) {
  69. buf = malloc(len);
  70. if (!buf || umoven(tcp, tcp->u_arg[1], len, buf) < 0) {
  71. tprints(", ");
  72. printaddr(tcp->u_arg[1]);
  73. tprintf(", %u", count);
  74. free(buf);
  75. return 0;
  76. }
  77. } else {
  78. buf = NULL;
  79. }
  80. tprints(",");
  81. if (!abbrev(tcp))
  82. tprints(" [");
  83. for (i = 0; len && i <= len - sizeof(kernel_dirent); ) {
  84. kernel_dirent *d = (kernel_dirent *) &buf[i];
  85. if (!abbrev(tcp)) {
  86. int oob = d->d_reclen < sizeof(kernel_dirent) ||
  87. i + d->d_reclen - 1 >= len;
  88. int d_name_len = oob ? len - i : d->d_reclen;
  89. d_name_len -= offsetof(kernel_dirent, d_name) + 1;
  90. if (d_name_len > D_NAME_LEN_MAX)
  91. d_name_len = D_NAME_LEN_MAX;
  92. tprintf("%s{d_ino=%llu, d_off=%llu, d_reclen=%u"
  93. ", d_name=", i ? ", " : "",
  94. zero_extend_signed_to_ull(d->d_ino),
  95. zero_extend_signed_to_ull(d->d_off),
  96. d->d_reclen);
  97. print_quoted_cstring(d->d_name, d_name_len);
  98. tprints(", d_type=");
  99. if (oob)
  100. tprints("?");
  101. else
  102. printxval(dirent_types, buf[i + d->d_reclen - 1], "DT_???");
  103. tprints("}");
  104. }
  105. dents++;
  106. if (d->d_reclen < sizeof(kernel_dirent)) {
  107. tprints_comment("d_reclen < sizeof(struct dirent)");
  108. break;
  109. }
  110. i += d->d_reclen;
  111. }
  112. if (!abbrev(tcp))
  113. tprints("]");
  114. else
  115. tprintf_comment("%u entries", dents);
  116. tprintf(", %u", count);
  117. free(buf);
  118. return 0;
  119. }