Implement full decoding of 64-bit capabilities

Unlike v1 capabilities which are 32-bit, v2 and v3 are 64-bit, but
before this change only lower 32 capability bits were decoded for
v2 and v3.

* xlat/capabilities1.in: New file.
* capability.c: Define v2/v3 CAP_* constants.
Include xlat/capabilities1.h.
(get_cap_header): New function.
(print_cap_header): Update to use get_cap_header result.
(print_cap_data): Decoder higher capability bits for v2 and v3.
(sys_capget, sys_capset): Use get_cap_header, update print_cap_header
and print_cap_data calls.
* tests/caps.c: New file.
* tests/caps.awk: New file.
* tests/caps.test: New test.
* tests/Makefile.am (CHECK_PROGRAMS): Add caps.
(TESTS): Add caps.test.
(EXTRA_DIST): Add caps.awk.
diff --git a/tests/Makefile.am b/tests/Makefile.am
index aef6a56..0784f24 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -4,6 +4,7 @@
 
 check_PROGRAMS = \
 	inet-accept-connect-send-recv \
+	caps \
 	mmsg \
 	net-accept-connect \
 	netlink_inet_diag \
@@ -23,6 +24,7 @@
 	ptrace_setoptions.test \
 	strace-f.test \
 	qual_syscall.test \
+	caps.test \
 	getdents.test \
 	scm_rights-fd.test \
 	sigaction.test \
@@ -44,6 +46,7 @@
 TEST_LOG_COMPILER = $(srcdir)/run.sh
 
 EXTRA_DIST = init.sh run.sh \
+	     caps.awk \
 	     getdents.awk \
 	     mmsg.expected \
 	     net-yy-accept.awk \
diff --git a/tests/caps.awk b/tests/caps.awk
new file mode 100644
index 0000000..9f99280
--- /dev/null
+++ b/tests/caps.awk
@@ -0,0 +1,25 @@
+BEGIN {
+  fail = 0
+  lines = 3
+  cap = "(0|CAP_[A-Z_]+(\\|CAP_[A-Z_]+)*)"
+  capget = "^capget\\({_LINUX_CAPABILITY_VERSION_3, 0}, {" cap ", " cap ", " cap "}\\) = 0$"
+}
+
+NR == 1 {if (match($0, capget)) next}
+
+NR == 2 && $0 == "capset({_LINUX_CAPABILITY_VERSION_3, 0}, {CAP_DAC_OVERRIDE|CAP_WAKE_ALARM, CAP_DAC_READ_SEARCH|CAP_BLOCK_SUSPEND, 0}) = -1 EPERM (Operation not permitted)" {next}
+
+NR == lines && $0 == "+++ exited with 0 +++" {next}
+
+{
+  print "Line " NR " does not match."
+  fail = 1
+  exit 1
+}
+
+END {
+  if (fail == 0 && NR != lines) {
+    print "Expected " lines " lines, found " NR " line(s)."
+    exit 1
+  }
+}
diff --git a/tests/caps.c b/tests/caps.c
new file mode 100644
index 0000000..918d6a8
--- /dev/null
+++ b/tests/caps.c
@@ -0,0 +1,19 @@
+#include <errno.h>
+
+extern int capget(int *, int *);
+extern int capset(int *, const int *);
+
+int
+main(void)
+{
+	int unused[6];
+	const int data[] = { 2, 4, 0, 8, 16, 0 };
+	const int v3 = 0x20080522;
+	int head[] = { v3, 0 };
+
+	if (capget(head, unused) || head[0] != v3 ||
+	    capset(head, data) == 0 || errno != EPERM)
+		return 77;
+
+	return 0;
+}
diff --git a/tests/caps.test b/tests/caps.test
new file mode 100755
index 0000000..ac0a85d
--- /dev/null
+++ b/tests/caps.test
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+# Check capget/capset syscalls decoding.
+
+. "${srcdir=.}/init.sh"
+
+check_prog awk
+
+./caps || {
+	if [ $? -eq 77 ]; then
+		framework_skip_ 'capget/capset syscalls do not behave as expected'
+	else
+		fail_ 'caps failed'
+	fi
+}
+
+args="-e trace=capget,capset ./caps"
+$STRACE -o "$LOG" $args || {
+	cat "$LOG"
+	fail_ "$STRACE $args failed"
+}
+
+awk -f "$srcdir"/caps.awk "$LOG" ||
+	{ cat "$LOG"; fail_ 'unexpected output'; }
+
+exit 0