* linux/i386/syscallent.h [383]: Add statx entry.
* linux/x32/syscallent.h [332]: Likewise.
* linux/x86_64/syscallent.h [332]: Likewise.
* pathtrace.c (pathtrace_match): Handle SEN_statx.
* statx.c: New file.
* statx.h: Likewise.
* Makefile.am (strace_SOURCES): Add them.
* tests/.gitignore: Add statx.
* tests/Makefile.am (check_PROGRAMS): Likewise.
(DECODER_TESTS): Add statx.test.
* tests/statx.c: New file.
* tests/statx.test: Likewise.
* tests/xstatx.c: Modify to support statx.
* xlat/at_statx_sync_types.in: New file.
* xlat/statx_attrs.in: Likewise.
* xlat/statx_masks.in: Likewise.
* NEWS: Mention this change.
---
 Makefile.am                 |   2 +
 NEWS                        |   1 +
 linux/i386/syscallent.h     |   1 +
 linux/x32/syscallent.h      |   3 +-
 linux/x86_64/syscallent.h   |   1 +
 pathtrace.c                 |   1 +
 statx.c                     | 111 ++++++++++++++++++++++++++
 statx.h                     |  69 ++++++++++++++++
 tests/.gitignore            |   1 +
 tests/Makefile.am           |   2 +
 tests/statx.c               |  70 +++++++++++++++++
 tests/statx.test            |   5 ++
 tests/xstatx.c              | 188 ++++++++++++++++++++++++++++++++++++++++----
 xlat/at_statx_sync_types.in |   5 ++
 xlat/statx_attrs.in         |   6 ++
 xlat/statx_masks.in         |  15 ++++
 16 files changed, 465 insertions(+), 16 deletions(-)
 create mode 100644 statx.c
 create mode 100644 statx.h
 create mode 100644 tests/statx.c
 create mode 100755 tests/statx.test
 create mode 100644 xlat/at_statx_sync_types.in
 create mode 100644 xlat/statx_attrs.in
 create mode 100644 xlat/statx_masks.in

diff --git a/Makefile.am b/Makefile.am
index 7e837b3..65177a6 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -232,6 +232,8 @@ strace_SOURCES =    \
        stat64.c        \
        statfs.c        \
        statfs.h        \
+       statx.c         \
+       statx.h         \
        strace.c        \
        swapon.c        \
        syscall.c       \
diff --git a/NEWS b/NEWS
index 77b6678..b2bb644 100644
--- a/NEWS
+++ b/NEWS
@@ -9,6 +9,7 @@ Noteworthy changes in release ?.?? (????-??-??)
 * Improvements
   * Enhanced decoding of sched_setattr syscall.
   * Added -e trace=%sched option for tracing sched_* syscalls.
+  * Implemented decoding of statx syscall.
 
 * Bug fixes
   * Fixed decoding of flags argument of preadv2 and pwritev2 syscalls on x32.
diff --git a/linux/i386/syscallent.h b/linux/i386/syscallent.h
index 8ef1b1c..84c5bde 100644
--- a/linux/i386/syscallent.h
+++ b/linux/i386/syscallent.h
@@ -408,6 +408,7 @@
 [380] = { 4,   TM|SI,          SEN(pkey_mprotect),             "pkey_mprotect" 
        },
 [381] = { 2,   0,              SEN(pkey_alloc),                "pkey_alloc"    
        },
 [382] = { 1,   0,              SEN(pkey_free),                 "pkey_free"     
        },
+[383] = { 5,   TD|TF,          SEN(statx),                     "statx"         
        },
 
 #define SYS_socket_subcall     400
 #include "subcall.h"
diff --git a/linux/x32/syscallent.h b/linux/x32/syscallent.h
index 2699bc0..7f4e45b 100644
--- a/linux/x32/syscallent.h
+++ b/linux/x32/syscallent.h
@@ -330,7 +330,8 @@
 [329] = { 4,   TM|SI,          SEN(pkey_mprotect),             "pkey_mprotect" 
        },
 [330] = { 2,   0,              SEN(pkey_alloc),                "pkey_alloc"    
        },
 [331] = { 1,   0,              SEN(pkey_free),                 "pkey_free"     
        },
-[332 ... 511] = { },
+[332] = { 5,   TD|TF,          SEN(statx),                     "statx"         
        },
+[333 ... 511] = { },
 /*
  * x32-specific system call numbers start at 512 to avoid cache impact
  * for native 64-bit operation.
diff --git a/linux/x86_64/syscallent.h b/linux/x86_64/syscallent.h
index a1a268e..2624947 100644
--- a/linux/x86_64/syscallent.h
+++ b/linux/x86_64/syscallent.h
@@ -330,3 +330,4 @@
 [329] = { 4,   TM|SI,          SEN(pkey_mprotect),             "pkey_mprotect" 
        },
 [330] = { 2,   0,              SEN(pkey_alloc),                "pkey_alloc"    
        },
 [331] = { 1,   0,              SEN(pkey_free),                 "pkey_free"     
        },
+[332] = { 5,   TD|TF,          SEN(statx),                     "statx"         
        },
diff --git a/pathtrace.c b/pathtrace.c
index d991aed..90974f4 100644
--- a/pathtrace.c
+++ b/pathtrace.c
@@ -183,6 +183,7 @@ pathtrace_match(struct tcb *tcp)
        case SEN_newfstatat:
        case SEN_openat:
        case SEN_readlinkat:
+       case SEN_statx:
        case SEN_unlinkat:
        case SEN_utimensat:
                /* fd, path */
diff --git a/statx.c b/statx.c
new file mode 100644
index 0000000..86f27d1
--- /dev/null
+++ b/statx.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2017 The strace developers.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "defs.h"
+#include "statx.h"
+
+#include <sys/stat.h>
+
+#include "xlat/statx_masks.h"
+#include "xlat/statx_attrs.h"
+#include "xlat/at_statx_sync_types.h"
+
+SYS_FUNC(statx)
+{
+       if (entering(tcp)) {
+               print_dirfd(tcp, tcp->u_arg[0]);
+               printpath(tcp, tcp->u_arg[1]);
+               tprints(", ");
+               if (printflags(at_flags, tcp->u_arg[2] & ~AT_STATX_SYNC_TYPE,
+                              NULL))
+               {
+                       tprints("|");
+               }
+               printxval(at_statx_sync_types,
+                         tcp->u_arg[2] & AT_STATX_SYNC_TYPE, "AT_STATX_???");
+               tprints(", ");
+               printflags(statx_masks, tcp->u_arg[3], "STATX_???");
+               tprints(", ");
+       } else {
+#define PRINT_FIELD_U(field) \
+       tprintf(", %s=%llu", #field, (unsigned long long) stx.field)
+
+#define PRINT_FIELD_TIME(field)                                                
\
+       do {                                                            \
+               tprints(", " #field "=");                               \
+               tprints(sprinttime(stx.field.sec));                     \
+               if (stx.field.nsec)                                     \
+                       tprintf(".%09" PRId32, stx.field.nsec);         \
+       } while (0)
+
+               struct_statx stx;
+               if (umove_or_printaddr(tcp, tcp->u_arg[4], &stx)) {
+                       return 0;
+               }
+
+               tprints("{stx_mask=");
+               printflags(statx_masks, stx.stx_mask, "STATX_???");
+
+               if (!abbrev(tcp)) {
+                       PRINT_FIELD_U(stx_blksize);
+               }
+
+               tprints(", stx_attributes=");
+               printflags(statx_attrs, stx.stx_attributes, "STATX_ATTR_???");
+
+               if (!abbrev(tcp)) {
+                       PRINT_FIELD_U(stx_nlink);
+                       printuid(", stx_uid=", stx.stx_uid);
+                       printuid(", stx_gid=", stx.stx_gid);
+               }
+
+               tprints(", stx_mode=");
+               print_symbolic_mode_t(stx.stx_mode);
+
+               if (!abbrev(tcp)) {
+                       PRINT_FIELD_U(stx_ino);
+               }
+
+               PRINT_FIELD_U(stx_size);
+
+               if (!abbrev(tcp)) {
+                       PRINT_FIELD_U(stx_blocks);
+                       PRINT_FIELD_TIME(stx_atime);
+                       PRINT_FIELD_TIME(stx_btime);
+                       PRINT_FIELD_TIME(stx_ctime);
+                       PRINT_FIELD_TIME(stx_mtime);
+                       PRINT_FIELD_U(stx_rdev_major);
+                       PRINT_FIELD_U(stx_rdev_minor);
+                       PRINT_FIELD_U(stx_dev_major);
+                       PRINT_FIELD_U(stx_dev_minor);
+               } else {
+                       tprints(", ...");
+               }
+               tprints("}");
+       }
+       return 0;
+}
diff --git a/statx.h b/statx.h
new file mode 100644
index 0000000..d946291
--- /dev/null
+++ b/statx.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2017 The strace developers.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef STRACE_STATX_H
+#define STRACE_STATX_H
+
+#include <stdint.h>
+
+typedef struct {
+       int64_t sec;
+       int32_t nsec;
+       int32_t reserved;
+} struct_statx_timestamp;
+
+typedef struct {
+       uint32_t stx_mask; /* What results were written [uncond] */
+       uint32_t stx_blksize; /* Preferred general I/O size [uncond] */
+       uint64_t stx_attributes; /* Flags conveying information about the file
+                                   [uncond] */
+
+       uint32_t stx_nlink; /* Number of hard links */
+       uint32_t stx_uid; /* User ID of owner */
+       uint32_t stx_gid; /* Group ID of owner */
+       uint16_t stx_mode; /* File mode */
+       uint16_t reserved0[1];
+
+       uint64_t stx_ino; /* Inode number */
+       uint64_t stx_size; /* File size */
+       uint64_t stx_blocks; /* Number of 512-byte blocks allocated */
+       uint64_t reserved1[1];
+
+       struct_statx_timestamp stx_atime; /* Last access time */
+       struct_statx_timestamp stx_btime; /* File creation time */
+       struct_statx_timestamp stx_ctime; /* Last attribute change time */
+       struct_statx_timestamp stx_mtime; /* Last data modification time */
+
+       uint32_t stx_rdev_major; /* Device ID of special file [if bdev/cdev] */
+       uint32_t stx_rdev_minor;
+       uint32_t stx_dev_major; /* ID of device containing file [uncond] */
+       uint32_t stx_dev_minor;
+
+       uint64_t reserved2[14]; /* Spare space for future expansion */
+} struct_statx;
+
+#endif /* !STRACE_STATX_H */
diff --git a/tests/.gitignore b/tests/.gitignore
index 6e44e5c..e2b68bf 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -329,6 +329,7 @@ stat
 stat64
 statfs
 statfs64
+statx
 swap
 symlink
 symlinkat
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 5a7a45f..71e85fb 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -389,6 +389,7 @@ check_PROGRAMS = \
        stat64 \
        statfs \
        statfs64 \
+       statx \
        swap \
        symlink \
        symlinkat \
@@ -782,6 +783,7 @@ DECODER_TESTS = \
        stat64.test \
        statfs.test \
        statfs64.test \
+       statx.test \
        sun_path.test \
        swap.test \
        symlink.test \
diff --git a/tests/statx.c b/tests/statx.c
new file mode 100644
index 0000000..f36fb0e
--- /dev/null
+++ b/tests/statx.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2017 The strace developers.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "tests.h"
+#include <asm/unistd.h>
+
+#ifdef __NR_statx
+
+# include <linux/stat.h>
+# include "xlat.h"
+# include "xlat/statx_masks.h"
+# include "xlat/statx_attrs.h"
+# include "xlat/at_statx_sync_types.h"
+
+# define IS_STATX 1
+# define TEST_SYSCALL_STR "statx"
+# define STRUCT_STAT struct statx
+# define STRUCT_STAT_STR "struct statx"
+# define STRUCT_STAT_IS_STAT64 0
+
+static unsigned    TEST_SYSCALL_STATX_FLAGS     = AT_STATX_SYNC_AS_STAT;
+static const char *TEST_SYSCALL_STATX_FLAGS_STR = "AT_STATX_SYNC_AS_STAT";
+static unsigned    TEST_SYSCALL_STATX_MASK      = STATX_ALL;
+static const char *TEST_SYSCALL_STATX_MASK_STR  = "STATX_ALL";
+
+# define TEST_SYSCALL_INVOKE(sample, pst) \
+       syscall(__NR_statx, AT_FDCWD, sample, TEST_SYSCALL_STATX_FLAGS, \
+               TEST_SYSCALL_STATX_MASK, pst)
+# define PRINT_SYSCALL_HEADER(sample) \
+       do { \
+               int saved_errno = errno; \
+               printf("%s(AT_FDCWD, \"%s\", %s, %s, ", \
+                      TEST_SYSCALL_STR, sample, TEST_SYSCALL_STATX_FLAGS_STR, \
+                      TEST_SYSCALL_STATX_MASK_STR)
+# define PRINT_SYSCALL_FOOTER(rc) \
+               errno = saved_errno; \
+               printf(") = %s\n", sprintrc(rc)); \
+       } while (0)
+
+# include "xstatx.c"
+
+#else
+
+SKIP_MAIN_UNDEFINED("__NR_statx")
+
+#endif
diff --git a/tests/statx.test b/tests/statx.test
new file mode 100755
index 0000000..a571241
--- /dev/null
+++ b/tests/statx.test
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+# Check statx syscall decoding.
+
+. "${srcdir=.}/statx.sh"
diff --git a/tests/xstatx.c b/tests/xstatx.c
index 874f309..a486091 100644
--- a/tests/xstatx.c
+++ b/tests/xstatx.c
@@ -47,6 +47,8 @@
 # include <unistd.h>
 # include <sys/sysmacros.h>
 
+# include "statx.h"
+
 # ifndef STRUCT_STAT
 #  define STRUCT_STAT struct stat
 #  define STRUCT_STAT_STR "struct stat"
@@ -109,6 +111,10 @@ typedef off_t libc_off_t;
 #  define OLD_STAT 0
 # endif
 
+# ifndef IS_STATX
+#  define IS_STATX 0
+# endif
+
 static void
 print_ftype(const unsigned int mode)
 {
@@ -130,6 +136,8 @@ print_perms(const unsigned int mode)
        printf("%#o", mode & ~S_IFMT);
 }
 
+# if !IS_STATX
+
 static void
 print_stat(const STRUCT_STAT *st)
 {
@@ -144,12 +152,12 @@ print_stat(const STRUCT_STAT *st)
        printf(", st_nlink=%llu", zero_extend_signed_to_ull(st->st_nlink));
        printf(", st_uid=%llu", zero_extend_signed_to_ull(st->st_uid));
        printf(", st_gid=%llu", zero_extend_signed_to_ull(st->st_gid));
-# if OLD_STAT
+#  if OLD_STAT
        printf(", st_blksize=0, st_blocks=0");
-# else /* !OLD_STAT */
+#  else /* !OLD_STAT */
        printf(", st_blksize=%llu", zero_extend_signed_to_ull(st->st_blksize));
        printf(", st_blocks=%llu", zero_extend_signed_to_ull(st->st_blocks));
-# endif /* OLD_STAT */
+#  endif /* OLD_STAT */
 
        switch (st->st_mode & S_IFMT) {
        case S_IFCHR: case S_IFBLK:
@@ -161,13 +169,13 @@ print_stat(const STRUCT_STAT *st)
                printf(", st_size=%llu", 
zero_extend_signed_to_ull(st->st_size));
        }
 
-# if defined(HAVE_STRUCT_STAT_ST_MTIME_NSEC) && !OLD_STAT
-#  define TIME_NSEC(val)       zero_extend_signed_to_ull(val)
-# else
-#  define TIME_NSEC(val)       0
-# endif
+#  if defined(HAVE_STRUCT_STAT_ST_MTIME_NSEC) && !OLD_STAT
+#   define TIME_NSEC(val)      zero_extend_signed_to_ull(val)
+#  else
+#   define TIME_NSEC(val)      0
+#  endif
 
-# define PRINT_ST_TIME(field)                                          \
+#  define PRINT_ST_TIME(field)                                         \
        printf(", st_" #field "=");                                     \
        print_time_t_nsec(sign_extend_unsigned_to_ll(st->st_ ## field), \
                          TIME_NSEC(st->st_ ## field ## _nsec))
@@ -178,6 +186,57 @@ print_stat(const STRUCT_STAT *st)
        printf("}");
 }
 
+# else /* !IS_STATX */
+
+static void
+print_stat(const STRUCT_STAT *st)
+{
+#  define PRINT_FIELD_U(field) \
+       printf(", %s=%llu", #field, (unsigned long long) st->field)
+
+#  define PRINT_FIELD_U32_UID(field) \
+       if (st->field == (uint32_t) -1) \
+               printf(", %s=-1", #field); \
+       else \
+               printf(", %s=%llu", #field, (unsigned long long) st->field)
+
+#  define PRINT_FIELD_TIME(field)                              \
+       printf(", %s=", #field);                                \
+       print_time_t_nsec(st->field.tv_sec, st->field.tv_nsec)
+
+       printf("{stx_mask=");
+       printflags(statx_masks, st->stx_mask, "STATX_???");
+
+       PRINT_FIELD_U(stx_blksize);
+
+       printf(", stx_attributes=");
+       printflags(statx_attrs, st->stx_attributes, "STATX_ATTR_???");
+
+       PRINT_FIELD_U(stx_nlink);
+       PRINT_FIELD_U32_UID(stx_uid);
+       PRINT_FIELD_U32_UID(stx_gid);
+
+       printf(", stx_mode=");
+       print_ftype(st->stx_mode);
+       printf("|");
+       print_perms(st->stx_mode);
+
+       PRINT_FIELD_U(stx_ino);
+       PRINT_FIELD_U(stx_size);
+       PRINT_FIELD_U(stx_blocks);
+       PRINT_FIELD_TIME(stx_atime);
+       PRINT_FIELD_TIME(stx_btime);
+       PRINT_FIELD_TIME(stx_ctime);
+       PRINT_FIELD_TIME(stx_mtime);
+       PRINT_FIELD_U(stx_rdev_major);
+       PRINT_FIELD_U(stx_rdev_minor);
+       PRINT_FIELD_U(stx_dev_major);
+       PRINT_FIELD_U(stx_dev_minor);
+       printf("}");
+}
+
+# endif /* !IS_STATX */
+
 static int
 create_sample(const char *fname, const libc_off_t size)
 {
@@ -246,25 +305,50 @@ main(void)
                        return 77;
                }
        }
-       (void) unlink(sample);
+
+# if IS_STATX
+#  define ST_SIZE_FIELD stx_size
+# else
+#  define ST_SIZE_FIELD st_size
+# endif
        if (!rc && zero_extend_signed_to_ull(SAMPLE_SIZE) !=
-           zero_extend_signed_to_ull(st[0].st_size)) {
+           zero_extend_signed_to_ull(st[0].ST_SIZE_FIELD)) {
                fprintf(stderr, "Size mismatch: "
                                "requested size(%llu) != st_size(%llu)\n",
                        zero_extend_signed_to_ull(SAMPLE_SIZE),
-                       zero_extend_signed_to_ull(st[0].st_size));
+                       zero_extend_signed_to_ull(st[0].ST_SIZE_FIELD));
                fprintf(stderr, "The most likely reason for this is incorrect"
                                " definition of %s.\n"
                                "Here is some diagnostics that might help:\n",
                        STRUCT_STAT_STR);
 
-#define LOG_STAT_OFFSETOF_SIZEOF(object, member)                       \
+# define LOG_STAT_OFFSETOF_SIZEOF(object, member)                      \
                fprintf(stderr, "offsetof(%s, %s) = %zu"                \
                                ", sizeof(%s) = %zu\n",                 \
                                STRUCT_STAT_STR, #member,               \
                                offsetof(STRUCT_STAT, member),          \
                                #member, sizeof((object).member))
 
+# if IS_STATX
+               LOG_STAT_OFFSETOF_SIZEOF(st[0], stx_mask);
+               LOG_STAT_OFFSETOF_SIZEOF(st[0], stx_blksize);
+               LOG_STAT_OFFSETOF_SIZEOF(st[0], stx_attributes);
+               LOG_STAT_OFFSETOF_SIZEOF(st[0], stx_nlink);
+               LOG_STAT_OFFSETOF_SIZEOF(st[0], stx_uid);
+               LOG_STAT_OFFSETOF_SIZEOF(st[0], stx_gid);
+               LOG_STAT_OFFSETOF_SIZEOF(st[0], stx_mode);
+               LOG_STAT_OFFSETOF_SIZEOF(st[0], stx_ino);
+               LOG_STAT_OFFSETOF_SIZEOF(st[0], stx_size);
+               LOG_STAT_OFFSETOF_SIZEOF(st[0], stx_blocks);
+               LOG_STAT_OFFSETOF_SIZEOF(st[0], stx_atime);
+               LOG_STAT_OFFSETOF_SIZEOF(st[0], stx_btime);
+               LOG_STAT_OFFSETOF_SIZEOF(st[0], stx_ctime);
+               LOG_STAT_OFFSETOF_SIZEOF(st[0], stx_mtime);
+               LOG_STAT_OFFSETOF_SIZEOF(st[0], stx_rdev_major);
+               LOG_STAT_OFFSETOF_SIZEOF(st[0], stx_rdev_minor);
+               LOG_STAT_OFFSETOF_SIZEOF(st[0], stx_dev_major);
+               LOG_STAT_OFFSETOF_SIZEOF(st[0], stx_dev_minor);
+# else
                LOG_STAT_OFFSETOF_SIZEOF(st[0], st_dev);
                LOG_STAT_OFFSETOF_SIZEOF(st[0], st_ino);
                LOG_STAT_OFFSETOF_SIZEOF(st[0], st_mode);
@@ -273,11 +357,14 @@ main(void)
                LOG_STAT_OFFSETOF_SIZEOF(st[0], st_gid);
                LOG_STAT_OFFSETOF_SIZEOF(st[0], st_rdev);
                LOG_STAT_OFFSETOF_SIZEOF(st[0], st_size);
-# if !OLD_STAT
+#  if !OLD_STAT
                LOG_STAT_OFFSETOF_SIZEOF(st[0], st_blksize);
                LOG_STAT_OFFSETOF_SIZEOF(st[0], st_blocks);
-# endif /* !OLD_STAT */
+#  endif /* !OLD_STAT */
 
+# endif /* IS_STATX */
+
+               (void) unlink(sample);
                return 1;
        }
 
@@ -288,6 +375,77 @@ main(void)
                print_stat(st);
        PRINT_SYSCALL_FOOTER(rc);
 
+# if IS_STATX
+
+       /*
+        * Check that our idea of struct_statx is no smaller than the kernel's.
+        * (If it is, statx is expected to fail with EFAULT.)
+        */
+       STRUCT_STAT *st_cut2 = tail_alloc(sizeof(struct_statx));
+       if ((rc = TEST_SYSCALL_INVOKE(sample, st_cut2))) {
+               perror(TEST_SYSCALL_STR);
+               (void) unlink(sample);
+               return 1;
+       }
+       PRINT_SYSCALL_HEADER(sample);
+       print_stat(st_cut2);
+       PRINT_SYSCALL_FOOTER(rc);
+
+#  define INVOKE() \
+       rc = TEST_SYSCALL_INVOKE(sample, st); \
+       PRINT_SYSCALL_HEADER(sample); \
+       if (rc) \
+               printf("%p", st); \
+       else \
+               print_stat(st); \
+       PRINT_SYSCALL_FOOTER(rc)
+
+#  define SET_FLAGS_INVOKE(flags, flags_str) \
+       TEST_SYSCALL_STATX_FLAGS = flags; \
+       TEST_SYSCALL_STATX_FLAGS_STR = flags_str; \
+       INVOKE()
+
+#  define SET_MASK_INVOKE(mask, mask_str) \
+       TEST_SYSCALL_STATX_MASK = mask; \
+       TEST_SYSCALL_STATX_MASK_STR = mask_str; \
+       INVOKE()
+
+       unsigned old_flags = TEST_SYSCALL_STATX_FLAGS;
+       const char *old_flags_str = TEST_SYSCALL_STATX_FLAGS_STR;
+       unsigned old_mask = TEST_SYSCALL_STATX_MASK;
+       const char *old_mask_str = TEST_SYSCALL_STATX_MASK_STR;
+
+       SET_FLAGS_INVOKE(AT_SYMLINK_FOLLOW | 0xffff0000U,
+               "AT_SYMLINK_FOLLOW|0xffff0000|AT_STATX_SYNC_AS_STAT");
+
+       SET_FLAGS_INVOKE(AT_STATX_SYNC_TYPE, "AT_STATX_SYNC_TYPE");
+
+       SET_FLAGS_INVOKE(0xffffff,
+               "AT_SYMLINK_NOFOLLOW|AT_REMOVEDIR|AT_SYMLINK_FOLLOW|"
+               "AT_NO_AUTOMOUNT|AT_EMPTY_PATH|0xff80ff|AT_STATX_SYNC_TYPE");
+
+       // we're done playing with flags
+       TEST_SYSCALL_STATX_FLAGS = old_flags;
+       TEST_SYSCALL_STATX_FLAGS_STR = old_flags_str;
+
+       SET_MASK_INVOKE(0, "0");
+       SET_MASK_INVOKE(~STATX_ALL, "0xfffff000 /* STATX_??? */");
+
+       SET_MASK_INVOKE(~STATX_NLINK,
+               "STATX_TYPE|STATX_MODE|STATX_UID|STATX_GID|STATX_ATIME|"
+               "STATX_MTIME|STATX_CTIME|STATX_INO|STATX_SIZE|STATX_BLOCKS|"
+               "STATX_BTIME|0xfffff000");
+
+       SET_MASK_INVOKE(STATX_UID, "STATX_UID");
+
+       // ...and with mask
+       TEST_SYSCALL_STATX_MASK = old_mask;
+       TEST_SYSCALL_STATX_MASK_STR = old_mask_str;
+
+# endif /* IS_STATX */
+
+       (void) unlink(sample);
+
        puts("+++ exited with 0 +++");
        return 0;
 }
diff --git a/xlat/at_statx_sync_types.in b/xlat/at_statx_sync_types.in
new file mode 100644
index 0000000..5d0ed49
--- /dev/null
+++ b/xlat/at_statx_sync_types.in
@@ -0,0 +1,5 @@
+AT_STATX_SYNC_AS_STAT  0x0000
+AT_STATX_FORCE_SYNC    0x2000
+AT_STATX_DONT_SYNC     0x4000
+
+AT_STATX_SYNC_TYPE     0x6000
diff --git a/xlat/statx_attrs.in b/xlat/statx_attrs.in
new file mode 100644
index 0000000..f6e4078
--- /dev/null
+++ b/xlat/statx_attrs.in
@@ -0,0 +1,6 @@
+STATX_ATTR_COMPRESSED  0x00000004
+STATX_ATTR_IMMUTABLE   0x00000010
+STATX_ATTR_APPEND      0x00000020
+STATX_ATTR_NODUMP      0x00000040
+STATX_ATTR_ENCRYPTED   0x00000800
+STATX_ATTR_AUTOMOUNT   0x00001000
diff --git a/xlat/statx_masks.in b/xlat/statx_masks.in
new file mode 100644
index 0000000..d18dd25
--- /dev/null
+++ b/xlat/statx_masks.in
@@ -0,0 +1,15 @@
+STATX_ALL              0x00000fffU
+STATX_BASIC_STATS      0x000007ffU
+
+STATX_TYPE             0x00000001U
+STATX_MODE             0x00000002U
+STATX_NLINK            0x00000004U
+STATX_UID              0x00000008U
+STATX_GID              0x00000010U
+STATX_ATIME            0x00000020U
+STATX_MTIME            0x00000040U
+STATX_CTIME            0x00000080U
+STATX_INO              0x00000100U
+STATX_SIZE             0x00000200U
+STATX_BLOCKS           0x00000400U
+STATX_BTIME            0x00000800U
-- 
2.10.2


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Strace-devel mailing list
Strace-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/strace-devel

Reply via email to