[PATCH v6] Implement decoding of statx syscall

Eugene Syromyatnikov evgsyr at gmail.com
Fri Mar 17 18:09:59 UTC 2017


On Fri, Mar 17, 2017 at 08:08:29PM +0300, Victor Krapivensky wrote:
> * 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.
This hunk does not apply, please rebase to the latest version.

error: patch failed: NEWS:9
error: NEWS: patch does not apply

>  
>  * 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))
In strace project it is preferred to indent continuations with tabs and
then fill the remainder only with spaces.

> +		{
In strace project opening curly brace is usually kept on the same line.
Moreover, for conditionals with a single statement they are not used at
all.

> +			tprints("|");
> +		}
> +		printxval(at_statx_sync_types,
> +		          tcp->u_arg[2] & AT_STATX_SYNC_TYPE, "AT_STATX_???");
Continuation formatting.

> +		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)) {
Braces can be avoided here.

> +			return 0;
> +		}
> +
> +		tprints("{stx_mask=");
> +		printflags(statx_masks, stx.stx_mask, "STATX_???");
> +
> +		if (!abbrev(tcp)) {
Braces can be avoided here.

> +			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)) {
Braces can be avoided here.

> +			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 {
Note that in this case (when one of branches has more than one statement) braces
are preferred to stay in place. No change needed here.

> +			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
Please use /* ... */ comment syntax.

> +	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
Please use /* ... */ comment syntax.

> +	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 at lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/strace-devel




More information about the Strace-devel mailing list