# define LONG_LONG(a,b) \
((long long)((unsigned long long)(unsigned)(b) | ((unsigned long long)(a)<<32)))
#endif
+extern int getllval(struct tcb *, unsigned long long *, int);
extern int printllval(struct tcb *, const char *, int);
extern void printxval(const struct xlat *, const unsigned int, const char *);
int
sys_fanotify_mark(struct tcb *tcp)
{
+ unsigned long long mask = 0;
+ int argn;
+
if (exiting(tcp))
return 0;
tprints(", ");
printflags(fan_mark_flags, (unsigned) tcp->u_arg[1], "FAN_MARK_???");
tprints(", ");
- printflags(fan_event_flags, tcp->u_arg[2], "FAN_???");
+ /*
+ * the mask argument is defined as 64-bit,
+ * but kernel uses the lower 32 bits only.
+ */
+ argn = getllval(tcp, &mask, 2);
+ printflags(fan_event_flags, mask, "FAN_???");
tprints(", ");
- if ((int) tcp->u_arg[3] == FAN_NOFD)
+ if ((int) tcp->u_arg[argn] == FAN_NOFD)
tprints("FAN_NOFD, ");
else
- print_dirfd(tcp, tcp->u_arg[3]);
- printpath(tcp, tcp->u_arg[4]);
+ print_dirfd(tcp, tcp->u_arg[argn]);
+ printpath(tcp, tcp->u_arg[argn + 1]);
return 0;
}
--- /dev/null
+#!/bin/sh
+
+# Check fanotify_mark syscall decoding.
+
+. "${srcdir=.}/init.sh"
+
+check_prog grep
+
+./fanotify_mark || {
+ if [ $? -eq 77 ]; then
+ framework_skip_ 'fanotify_mark is not available'
+ else
+ fail_ 'fanotify_mark failed'
+ fi
+}
+
+args="-efanotify_mark ./fanotify_mark"
+$STRACE -o "$LOG" $args || {
+ cat "$LOG"
+ fail_ "$STRACE $args failed"
+}
+
+grep_log()
+{
+ local syscall="$1"; shift
+
+ LC_ALL=C grep -E -x "$syscall$*" $LOG > /dev/null || {
+ cat $LOG
+ fail_ "$STRACE $args failed to trace \"$syscall\" properly"
+ }
+}
+
+grep_log fanotify_mark '\(-1, FAN_MARK_ADD, FAN_MODIFY\|FAN_ONDIR, AT_FDCWD, "\."\) += -1.*'
+
+exit 0
}
/*
- * Print 64bit argument at position arg_no and return the index of the next
- * argument.
+ * Fetch 64bit argument at position arg_no and
+ * return the index of the next argument.
*/
int
-printllval(struct tcb *tcp, const char *format, int arg_no)
+getllval(struct tcb *tcp, unsigned long long *val, int arg_no)
{
#if SIZEOF_LONG > 4 && SIZEOF_LONG == SIZEOF_LONG_LONG
# if SUPPORTED_PERSONALITIES > 1
if (current_wordsize > 4) {
# endif
- tprintf(format, tcp->u_arg[arg_no]);
+ *val = tcp->u_arg[arg_no];
arg_no++;
# if SUPPORTED_PERSONALITIES > 1
} else {
# if defined(AARCH64) || defined(POWERPC64)
/* Align arg_no to the next even number. */
arg_no = (arg_no + 1) & 0xe;
-# endif
- tprintf(format, LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]));
+# endif /* AARCH64 || POWERPC64 */
+ *val = LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]);
arg_no += 2;
}
-# endif /* SUPPORTED_PERSONALITIES */
+# endif /* SUPPORTED_PERSONALITIES > 1 */
#elif SIZEOF_LONG > 4
# error Unsupported configuration: SIZEOF_LONG > 4 && SIZEOF_LONG_LONG > SIZEOF_LONG
#elif defined LINUX_MIPSN32
- tprintf(format, tcp->ext_arg[arg_no]);
+ *val = tcp->ext_arg[arg_no];
arg_no++;
#elif defined X32
if (current_personality == 0) {
- tprintf(format, tcp->ext_arg[arg_no]);
+ *val = tcp->ext_arg[arg_no];
arg_no++;
} else {
- tprintf(format, LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]));
+ *val = LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]);
arg_no += 2;
}
#else
/* Align arg_no to the next even number. */
arg_no = (arg_no + 1) & 0xe;
# endif
- tprintf(format, LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]));
+ *val = LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]);
arg_no += 2;
#endif
return arg_no;
}
+/*
+ * Print 64bit argument at position arg_no and
+ * return the index of the next argument.
+ */
+int
+printllval(struct tcb *tcp, const char *format, int arg_no)
+{
+ unsigned long long val = 0;
+
+ arg_no = getllval(tcp, &val, arg_no);
+ tprintf(format, val);
+ return arg_no;
+}
+
/*
* Interpret `xlat' as an array of flags
* print the entries whose bits are on in `flags'