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