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.

dirent64.c 2.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  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) 2015-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 <dirent.h>
  14. #include "xlat/dirent_types.h"
  15. #define D_NAME_LEN_MAX 256
  16. SYS_FUNC(getdents64)
  17. {
  18. /* the minimum size of a valid dirent64 structure */
  19. const unsigned int d_name_offset = offsetof(struct dirent64, d_name);
  20. unsigned int i, len, dents = 0;
  21. char *buf;
  22. if (entering(tcp)) {
  23. printfd(tcp, tcp->u_arg[0]);
  24. return 0;
  25. }
  26. const unsigned int count = tcp->u_arg[2];
  27. if (syserror(tcp) || !verbose(tcp)) {
  28. tprints(", ");
  29. printaddr(tcp->u_arg[1]);
  30. tprintf(", %u", count);
  31. return 0;
  32. }
  33. /* Beware of insanely large or too small values in tcp->u_rval */
  34. if (tcp->u_rval > 1024*1024)
  35. len = 1024*1024;
  36. else if (tcp->u_rval < (int) d_name_offset)
  37. len = 0;
  38. else
  39. len = tcp->u_rval;
  40. if (len) {
  41. buf = malloc(len);
  42. if (!buf || umoven(tcp, tcp->u_arg[1], len, buf) < 0) {
  43. tprints(", ");
  44. printaddr(tcp->u_arg[1]);
  45. tprintf(", %u", count);
  46. free(buf);
  47. return 0;
  48. }
  49. } else {
  50. buf = NULL;
  51. }
  52. tprints(",");
  53. if (!abbrev(tcp))
  54. tprints(" [");
  55. for (i = 0; len && i <= len - d_name_offset; ) {
  56. struct dirent64 *d = (struct dirent64 *) &buf[i];
  57. if (!abbrev(tcp)) {
  58. int d_name_len;
  59. if (d->d_reclen >= d_name_offset
  60. && i + d->d_reclen <= len) {
  61. d_name_len = d->d_reclen - d_name_offset;
  62. } else {
  63. d_name_len = len - i - d_name_offset;
  64. }
  65. if (d_name_len > D_NAME_LEN_MAX)
  66. d_name_len = D_NAME_LEN_MAX;
  67. tprintf("%s{d_ino=%" PRIu64 ", d_off=%" PRId64
  68. ", d_reclen=%u, d_type=",
  69. i ? ", " : "",
  70. d->d_ino,
  71. d->d_off,
  72. d->d_reclen);
  73. printxval(dirent_types, d->d_type, "DT_???");
  74. tprints(", d_name=");
  75. print_quoted_cstring(d->d_name, d_name_len);
  76. tprints("}");
  77. }
  78. if (d->d_reclen < d_name_offset) {
  79. tprints_comment("d_reclen < offsetof(struct dirent64, d_name)");
  80. break;
  81. }
  82. i += d->d_reclen;
  83. dents++;
  84. }
  85. if (!abbrev(tcp))
  86. tprints("]");
  87. else
  88. tprintf_comment("%u entries", dents);
  89. tprintf(", %u", count);
  90. free(buf);
  91. return 0;
  92. }