]> granicus.if.org Git - strace/blob - open.c
e97be426fd450f1a7dc4b4b16ba82707e02e3deb
[strace] / open.c
1 #include "defs.h"
2
3 #include <fcntl.h>
4
5 #ifdef O_LARGEFILE
6 # if O_LARGEFILE == 0          /* biarch platforms in 64-bit mode */
7 #  undef O_LARGEFILE
8 #  ifdef SPARC64
9 #   define O_LARGEFILE 0x40000
10 #  elif defined X86_64 || defined S390X
11 #   define O_LARGEFILE 0100000
12 #  endif
13 # endif
14 #endif
15
16 #include "xlat/open_access_modes.h"
17 #include "xlat/open_mode_flags.h"
18
19 #ifndef AT_FDCWD
20 # define AT_FDCWD                -100
21 #endif
22
23 /* The fd is an "int", so when decoding x86 on x86_64, we need to force sign
24  * extension to get the right value.  We do this by declaring fd as int here.
25  */
26 void
27 print_dirfd(struct tcb *tcp, int fd)
28 {
29         if (fd == AT_FDCWD)
30                 tprints("AT_FDCWD, ");
31         else {
32                 printfd(tcp, fd);
33                 tprints(", ");
34         }
35 }
36
37 /*
38  * low bits of the open(2) flags define access mode,
39  * other bits are real flags.
40  */
41 const char *
42 sprint_open_modes(int flags)
43 {
44         static char outstr[(1 + ARRAY_SIZE(open_mode_flags)) * sizeof("O_LARGEFILE")];
45         char *p;
46         char sep;
47         const char *str;
48         const struct xlat *x;
49
50         sep = ' ';
51         p = stpcpy(outstr, "flags");
52         str = xlookup(open_access_modes, flags & 3);
53         if (str) {
54                 *p++ = sep;
55                 p = stpcpy(p, str);
56                 flags &= ~3;
57                 if (!flags)
58                         return outstr;
59                 sep = '|';
60         }
61
62         for (x = open_mode_flags; x->str; x++) {
63                 if ((flags & x->val) == x->val) {
64                         *p++ = sep;
65                         p = stpcpy(p, x->str);
66                         flags &= ~x->val;
67                         if (!flags)
68                                 return outstr;
69                         sep = '|';
70                 }
71         }
72         /* flags is still nonzero */
73         *p++ = sep;
74         sprintf(p, "%#x", flags);
75         return outstr;
76 }
77
78 void
79 tprint_open_modes(int flags)
80 {
81         tprints(sprint_open_modes(flags) + sizeof("flags"));
82 }
83
84 static int
85 decode_open(struct tcb *tcp, int offset)
86 {
87         if (entering(tcp)) {
88                 printpath(tcp, tcp->u_arg[offset]);
89                 tprints(", ");
90                 /* flags */
91                 tprint_open_modes(tcp->u_arg[offset + 1]);
92                 if (tcp->u_arg[offset + 1] & O_CREAT) {
93                         /* mode */
94                         tprintf(", %#lo", tcp->u_arg[offset + 2]);
95                 }
96         }
97         return RVAL_FD;
98 }
99
100 int
101 sys_open(struct tcb *tcp)
102 {
103         return decode_open(tcp, 0);
104 }
105
106 int
107 sys_openat(struct tcb *tcp)
108 {
109         if (entering(tcp))
110                 print_dirfd(tcp, tcp->u_arg[0]);
111         return decode_open(tcp, 1);
112 }
113
114 int
115 sys_creat(struct tcb *tcp)
116 {
117         if (entering(tcp)) {
118                 printpath(tcp, tcp->u_arg[0]);
119                 tprintf(", %#lo", tcp->u_arg[1]);
120         }
121         return RVAL_FD;
122 }
123
124 #if defined(SPARC) || defined(SPARC64)
125 # include "xlat/openmodessol.h"
126
127 int
128 solaris_open(struct tcb *tcp)
129 {
130         if (entering(tcp)) {
131                 printpath(tcp, tcp->u_arg[0]);
132                 tprints(", ");
133                 /* flags */
134                 printflags(openmodessol, tcp->u_arg[1] + 1, "O_???");
135                 if (tcp->u_arg[1] & 0x100) {
136                         /* mode */
137                         tprintf(", %#lo", tcp->u_arg[2]);
138                 }
139         }
140         return 0;
141 }
142
143 #endif /* SPARC || SPARC64 */