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
print_dirfd(struct tcb * tcp,int fd)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 *
sprint_open_modes(int flags)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
tprint_open_modes(int flags)79 tprint_open_modes(int flags)
80 {
81 	tprints(sprint_open_modes(flags) + sizeof("flags"));
82 }
83 
84 static int
decode_open(struct tcb * tcp,int offset)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 
SYS_FUNC(open)100 SYS_FUNC(open)
101 {
102 	return decode_open(tcp, 0);
103 }
104 
SYS_FUNC(openat)105 SYS_FUNC(openat)
106 {
107 	if (entering(tcp))
108 		print_dirfd(tcp, tcp->u_arg[0]);
109 	return decode_open(tcp, 1);
110 }
111 
SYS_FUNC(creat)112 SYS_FUNC(creat)
113 {
114 	if (entering(tcp)) {
115 		printpath(tcp, tcp->u_arg[0]);
116 		tprintf(", %#lo", tcp->u_arg[1]);
117 	}
118 	return RVAL_FD;
119 }
120