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.

open.c 3.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  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-2007 Roland McGrath <roland@redhat.com>
  7. * Copyright (c) 2006-2007 Ulrich Drepper <drepper@redhat.com>
  8. * Copyright (c) 2009-2013 Denys Vlasenko <dvlasenk@redhat.com>
  9. * Copyright (c) 2005-2015 Dmitry V. Levin <ldv@altlinux.org>
  10. * Copyright (c) 2014-2020 The strace developers.
  11. * All rights reserved.
  12. *
  13. * SPDX-License-Identifier: LGPL-2.1-or-later
  14. */
  15. #include "defs.h"
  16. #include "xstring.h"
  17. #include <asm/fcntl.h>
  18. #include "print_fields.h"
  19. #include "types/openat2.h"
  20. /* some libcs are guilty of messing up with O_ACCMODE */
  21. #undef O_ACCMODE
  22. #define O_ACCMODE 03
  23. #ifdef O_LARGEFILE
  24. # if O_LARGEFILE == 0 /* biarch platforms in 64-bit mode */
  25. # undef O_LARGEFILE
  26. # endif
  27. #endif
  28. #include "xlat/open_access_modes.h"
  29. #include "xlat/open_mode_flags.h"
  30. #include "xlat/open_resolve_flags.h"
  31. #ifndef AT_FDCWD
  32. # define AT_FDCWD -100
  33. #endif
  34. /* The fd is an "int", so when decoding x86 on x86_64, we need to force sign
  35. * extension to get the right value. We do this by declaring fd as int here.
  36. */
  37. void
  38. print_dirfd(struct tcb *tcp, int fd)
  39. {
  40. if (fd == AT_FDCWD)
  41. print_xlat_d(AT_FDCWD);
  42. else
  43. printfd(tcp, fd);
  44. }
  45. /*
  46. * low bits of the open(2) flags define access mode,
  47. * other bits are real flags.
  48. */
  49. static const char *
  50. sprint_open_modes64(uint64_t flags)
  51. {
  52. static char outstr[sizeof("flags O_ACCMODE")];
  53. char *p;
  54. char sep;
  55. const char *str;
  56. sep = ' ';
  57. p = stpcpy(outstr, "flags");
  58. str = xlookup(open_access_modes, flags & 3);
  59. if (str) {
  60. *p++ = sep;
  61. p = stpcpy(p, str);
  62. flags &= ~3;
  63. if (!flags)
  64. return outstr;
  65. sep = '|';
  66. }
  67. *p = '\0';
  68. return sprintflags_ex(outstr, open_mode_flags, flags, sep,
  69. XLAT_STYLE_ABBREV) ?: outstr;
  70. }
  71. const char *
  72. sprint_open_modes(unsigned int flags)
  73. {
  74. return sprint_open_modes64(flags);
  75. }
  76. static void
  77. tprint_open_modes64(uint64_t flags)
  78. {
  79. print_xlat_ex(flags, sprint_open_modes64(flags) + sizeof("flags"),
  80. XLAT_STYLE_DEFAULT);
  81. }
  82. void
  83. tprint_open_modes(unsigned int flags)
  84. {
  85. tprint_open_modes64(flags);
  86. }
  87. static int
  88. decode_open(struct tcb *tcp, int offset)
  89. {
  90. printpath(tcp, tcp->u_arg[offset]);
  91. tprints(", ");
  92. /* flags */
  93. tprint_open_modes(tcp->u_arg[offset + 1]);
  94. if (tcp->u_arg[offset + 1] & (O_CREAT | __O_TMPFILE)) {
  95. /* mode */
  96. tprints(", ");
  97. print_numeric_umode_t(tcp->u_arg[offset + 2]);
  98. }
  99. return RVAL_DECODED | RVAL_FD;
  100. }
  101. SYS_FUNC(open)
  102. {
  103. return decode_open(tcp, 0);
  104. }
  105. static void
  106. print_open_how(struct tcb *tcp, kernel_ulong_t addr, kernel_ulong_t size)
  107. {
  108. enum { OPEN_HOW_MIN_SIZE = 24 };
  109. struct_open_how how;
  110. if (size < OPEN_HOW_MIN_SIZE) {
  111. printaddr(addr);
  112. return;
  113. }
  114. if (umoven_or_printaddr(tcp, addr, MIN(size, sizeof(how)), &how))
  115. return;
  116. tprints("{flags=");
  117. tprint_open_modes64(how.flags);
  118. if ((how.flags & (O_CREAT| __O_TMPFILE)) || how.mode) {
  119. tprints(", mode=");
  120. print_numeric_umode_t_64(how.mode);
  121. }
  122. PRINT_FIELD_FLAGS(", ", how, resolve, open_resolve_flags,
  123. "RESOLVE_???");
  124. if (size > sizeof(how)) {
  125. print_nonzero_bytes(tcp, ", ", addr, sizeof(how),
  126. MIN(size, get_pagesize()), QUOTE_FORCE_HEX);
  127. }
  128. tprints("}");
  129. }
  130. SYS_FUNC(openat)
  131. {
  132. print_dirfd(tcp, tcp->u_arg[0]);
  133. tprints(", ");
  134. return decode_open(tcp, 1);
  135. }
  136. SYS_FUNC(openat2)
  137. {
  138. print_dirfd(tcp, tcp->u_arg[0]);
  139. tprints(", ");
  140. printpath(tcp, tcp->u_arg[1]);
  141. tprints(", ");
  142. print_open_how(tcp, tcp->u_arg[2], tcp->u_arg[3]);
  143. tprintf(", %" PRI_klu, tcp->u_arg[3]);
  144. return RVAL_DECODED | RVAL_FD;
  145. }
  146. SYS_FUNC(creat)
  147. {
  148. printpath(tcp, tcp->u_arg[0]);
  149. tprints(", ");
  150. print_numeric_umode_t(tcp->u_arg[1]);
  151. return RVAL_DECODED | RVAL_FD;
  152. }