File psmisc-23.0-statx.patch of Package psmisc.23622

---
 Makefile.am   |    5 +
 configure.ac  |   15 +++++
 src/fuser.c   |   23 ++++++++
 src/statx.c   |  155 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/statx.h   |   70 ++++++++++++++++++++++++++
 src/timeout.c |   12 ++++
 6 files changed, 278 insertions(+), 2 deletions(-)

--- Makefile.am
+++ Makefile.am	2022-03-02 14:53:43.874374488 +0000
@@ -62,6 +62,9 @@ src_fuser_SOURCES = \
 src_fuser_SOURCES += src/timeout.c src/timeout.h
 endif
 src_fuser_LDADD = @LIBINTL@ -lpthread
+if HAVE_SYSCALL_STATX
+  src_fuser_SOURCES += src/statx.c src/statx.h
+endif
 src_killall_SOURCES = src/killall.c src/comm.h src/signals.c src/signals.h src/i18n.h
 src_killall_LDADD = @LIBINTL@ @SELINUX_LIB@
 src_peekfd_SOURCES = src/peekfd.c
--- configure.ac
+++ configure.ac	2022-03-02 13:07:53.629494835 +0000
@@ -71,6 +71,21 @@ if test "$enable_mountinfo_list" = "yes"
   AC_DEFINE([WITH_MOUNTINFO_LIST], [1], [Use list in /proc/self/mountinfo to replace stat calls])
 fi
 
+AC_CHECK_HEADERS([sys/syscall.h])
+AC_CHECK_DECLS([SYS_statx],
+  [has_syscall_statx="yes"],
+  [has_syscall_statx="no"],
+  [[#include <sys/syscall.h>]]
+)
+AC_CHECK_FUNCS([statx])
+# Check for linux specific statx(2) system call
+AC_SUBST([HAS_SYSCALL_STATX])
+AC_ARG_ENABLE([disable_statx],
+  [AS_HELP_STRING([--disable-statx], [Do not use linux specific statx(2) system call as replacement for stat(2), lstat(2), and fstat(2)])],
+  [enable_syscall_statx="no"],
+  [enable_syscall_statx=$has_syscall_statx])
+AM_CONDITIONAL([HAVE_SYSCALL_STATX], [test "$enable_syscall_statx" = "yes"])
+
 # Enable hardened compile and link flags
 AC_ARG_ENABLE([harden_flags],
   [AS_HELP_STRING([--disable-harden-flags], [disable hardened compilier and linker flags])],
--- src/fuser.c
+++ src/fuser.c	2022-03-02 13:17:05.279133044 +0000
@@ -62,6 +62,9 @@
 #include "signals.h"
 #include "i18n.h"
 #include "timeout.h"
+#if defined(HAVE_SYSCALL_STATX) || (defined(HAVE_DECL_SYS_STATX) && HAVE_DECL_SYS_STATX == 1)
+#include "statx.h"
+#endif
 
 //#define DEBUG 1
 
@@ -122,7 +125,11 @@ static int find_mountpoint(const char *p
 #if defined(WITH_MOUNTINFO_LIST)
 static int mntstat(const char *path, struct stat *buf);
 #endif
+#if defined(HAVE_SYSCALL_STATX) || (defined(HAVE_DECL_SYS_STATX) && HAVE_DECL_SYS_STATX == 1)
+static stat_t thestat = statn;
+#else
 static stat_t thestat = stat;
+#endif
 static char *expandpath(const char *path);
 static struct unixsocket_list *unixsockets = NULL;
 static struct names *names_head = NULL, *names_tail = NULL;
@@ -173,7 +180,11 @@ static void usage(const char *errormsg)
 
 void print_version()
 {
+#if defined(HAVE_SYSCALL_STATX) || (defined(HAVE_DECL_SYS_STATX) && HAVE_DECL_SYS_STATX == 1)
+	fprintf(stderr, _("fuser (PSmisc, with statx support) %s\n"), VERSION);
+#else
 	fprintf(stderr, _("fuser (PSmisc) %s\n"), VERSION);
+#endif
 	fprintf(stderr,
 		_
 		("Copyright (C) 1993-2017 Werner Almesberger and Craig Small\n\n"));
@@ -2529,14 +2540,22 @@ static int mntstat(const char *path, str
 		 * Could be a special file (socket, pipe, inotify)
 		 */
 		errno = 0;
+#if defined(HAVE_SYSCALL_STATX) || (defined(HAVE_DECL_SYS_STATX) && HAVE_DECL_SYS_STATX == 1)
+		return statn(path, buf);
+#else
 		return stat(path, buf);
+#endif
 	}
 	if (strncmp("/dev/", use, 5) == 0) {
 		/*
 		 * Could be a special file (socket, pipe, inotify)
 		 */
 		errno = 0;
+#if defined(HAVE_SYSCALL_STATX) || (defined(HAVE_DECL_SYS_STATX) && HAVE_DECL_SYS_STATX == 1)
+		return statn(path, buf);
+#else
 		return stat(path, buf);
+#endif
 	}
 
 	if (find_mountpoint(use, &mnt) < 0) {
@@ -2550,7 +2569,11 @@ static int mntstat(const char *path, str
 		return 0;		    /* found on NFS */
 	}
 
+#if defined(HAVE_SYSCALL_STATX) || (defined(HAVE_DECL_SYS_STATX) && HAVE_DECL_SYS_STATX == 1)
+	return statn(path, buf);
+#else
 	return stat(path, buf);
+#endif
 }
 #endif				/* WITH_MOUNTINFO_LIST */
 
--- src/statx.c
+++ src/statx.c	2022-03-02 13:07:53.629494835 +0000
@@ -0,0 +1,155 @@
+/*
+ * statx.c - Map modern statx(2) system call to older stat(2), lstat(2),
+ *	     and fstat(2) replacements named {,l,f}statn()
+ *
+ * Copyright (C) 2018 Werner Fink
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifndef HAVE_STATX
+# define _ASM_GENERIC_FCNTL_H	/* Avoid collisions between asm/fcntl.h and bits/fcntl.h ! */
+# include <linux/fcntl.h>	/* Definition of AT_* and AT_STATX_* constants ! */
+#endif
+#include <fcntl.h>		/* Definition of AT_* constants */
+#include <sys/stat.h>
+#ifndef HAVE_STATX
+# ifndef STATX_TYPE
+#  include <linux/stat.h>	/* Provides 'struct statx' and STATX_* ! */
+# endif
+#endif
+#include <errno.h>
+#include <sys/sysmacros.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+int stat_flags = AT_NO_AUTOMOUNT|AT_STATX_DONT_SYNC;
+
+int statn(const char *pathname, /* unsigned int mask, */ struct stat *st)
+{
+    int flags = stat_flags;
+    int dirfd = pathname && *pathname == '/' ? 0 : AT_FDCWD;
+    int ret;
+    struct statx stx;
+
+    unsigned int mask = STATX_UID|STATX_INO|STATX_TYPE;
+
+#ifndef HAVE_STATX
+    ret = syscall(SYS_statx, dirfd, pathname, flags, mask, &stx);
+#else
+    ret = statx(dirfd, pathname, flags, mask, &stx);
+#endif
+    if (ret >= 0) {
+	st->st_dev  = makedev(stx.stx_dev_major,  stx.stx_dev_minor);
+	st->st_rdev = makedev(stx.stx_rdev_major, stx.stx_rdev_minor);
+
+	st->st_ino  = stx.stx_ino;
+	st->st_mode = stx.stx_mode;
+	st->st_nlink = stx.stx_nlink;
+	st->st_uid = stx.stx_uid;
+	st->st_gid = stx.stx_gid;
+	st->st_size = stx.stx_size;
+	st->st_blksize = stx.stx_blksize;
+	st->st_blocks = stx.stx_blocks;
+
+	st->st_atim.tv_sec = stx.stx_atime.tv_sec;
+	st->st_atim.tv_nsec = stx.stx_atime.tv_nsec;
+	st->st_mtim.tv_sec = stx.stx_mtime.tv_sec;
+	st->st_mtim.tv_nsec = stx.stx_mtime.tv_nsec;
+	st->st_ctim.tv_sec = stx.stx_ctime.tv_sec;
+	st->st_ctim.tv_nsec = stx.stx_ctime.tv_nsec;
+    } else if (ret < 0 && errno == ENOSYS)
+	ret = stat(pathname, st);
+    return ret;
+}
+
+#if 0
+int fstatn(int fd, unsigned int mask, struct stat *st)
+{
+    int flags = AT_EMPTY_PATH|stat_flags;
+    int ret;
+    struct statx stx;
+
+#ifndef HAVE_STATX
+    ret = syscall(SYS_statx, fd, "", flags, mask, &stx);
+#else
+    ret = statx(fd, "", flags, mask, &stx);
+#endif
+    if (ret >= 0) {
+	st->st_dev  = makedev(stx.stx_dev_major,  stx.stx_dev_minor);
+	st->st_rdev = makedev(stx.stx_rdev_major, stx.stx_rdev_minor);
+
+	st->st_ino  = stx.stx_ino;
+	st->st_mode = stx.stx_mode;
+	st->st_nlink = stx.stx_nlink;
+	st->st_uid = stx.stx_uid;
+	st->st_gid = stx.stx_gid;
+	st->st_size = stx.stx_size;
+	st->st_blksize = stx.stx_blksize;
+	st->st_blocks = stx.stx_blocks;
+
+	st->st_atim.tv_sec = stx.stx_atime.tv_sec;
+	st->st_atim.tv_nsec = stx.stx_atime.tv_nsec;
+	st->st_mtim.tv_sec = stx.stx_mtime.tv_sec;
+	st->st_mtim.tv_nsec = stx.stx_mtime.tv_nsec;
+	st->st_ctim.tv_sec = stx.stx_ctime.tv_sec;
+	st->st_ctim.tv_nsec = stx.stx_ctime.tv_nsec;
+    }
+    return ret;
+}
+
+int lstatn(const char *pathname, unsigned int mask, struct stat *st)
+{
+    int flags = AT_SYMLINK_NOFOLLOW|stat_flags;
+    int dirfd = pathname && *pathname == '/' ? 0 : AT_FDCWD;
+    int ret;
+    struct statx stx;
+
+#ifndef HAVE_STATX
+    ret = syscall(SYS_statx, dirfd, pathname, flags, mask, &stx);
+#else
+    ret = statx(dirfd, pathname, flags, mask, &stx);
+#endif
+    if (ret >= 0) {
+	st->st_dev  = makedev(stx.stx_dev_major,  stx.stx_dev_minor);
+	st->st_rdev = makedev(stx.stx_rdev_major, stx.stx_rdev_minor);
+
+	st->st_ino  = stx.stx_ino;
+	st->st_mode = stx.stx_mode;
+	st->st_nlink = stx.stx_nlink;
+	st->st_uid = stx.stx_uid;
+	st->st_gid = stx.stx_gid;
+	st->st_size = stx.stx_size;
+	st->st_blksize = stx.stx_blksize;
+	st->st_blocks = stx.stx_blocks;
+
+	st->st_atim.tv_sec = stx.stx_atime.tv_sec;
+	st->st_atim.tv_nsec = stx.stx_atime.tv_nsec;
+	st->st_mtim.tv_sec = stx.stx_mtime.tv_sec;
+	st->st_mtim.tv_nsec = stx.stx_mtime.tv_nsec;
+	st->st_ctim.tv_sec = stx.stx_ctime.tv_sec;
+	st->st_ctim.tv_nsec = stx.stx_ctime.tv_nsec;
+    }
+    return ret;
+}
+#endif
--- src/statx.h
+++ src/statx.h	2022-03-02 13:07:53.629494835 +0000
@@ -0,0 +1,70 @@
+/*
+ * statx.h - Map modern statx(2) system call to older stat(2), lstat(2),
+ *           and fstat(2) replacements named {,l,f}statn()
+ *
+ * Copyright (C) 2018 Werner Fink
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _STATX_H
+#define _STATX_H
+
+extern int stat_flags;
+#if defined(HAVE_DECL_SYS_STATX) && HAVE_DECL_SYS_STATX == 1
+# ifndef HAVE_STATX
+#  define _ASM_GENERIC_FCNTL_H	/* Avoid collisions between asm/fcntl.h and bits/fcntl.h ! */
+#  include <linux/fcntl.h>	/* Definition of AT_* and AT_STATX_* constants ! */
+#  ifndef STATX_TYPE
+#   include <linux/stat.h>	/* Provides 'struct statx' and STATX_* ! */
+#  endif
+# endif
+extern int statn(const char*, /* unsigned int, */ struct stat*);
+# if 0
+extern int fstatn(int, unsigned int, struct stat*);
+extern int lstatn(const char*, unsigned int, struct stat*);
+# endif
+#else
+extern inline int
+statn(const char *path, unsigned int mask __attribute__((unused)), struct stat *st)
+{
+    return stat(path, st);
+}
+extern inline int
+fstatn(int fd, unsigned int mask __attribute__((unused)), struct stat *st)
+{
+    return fstat(fd, st);
+}
+extern inline int
+lstatn(const char *path, unsigned int mask __attribute__((unused)), struct stat *st)
+{
+    return lstat(path, st);
+}
+#define STATX_TYPE		0
+#define STATX_MODE		0
+#define STATX_NLINK		0
+#define STATX_UID		0
+#define STATX_GID		0
+#define STATX_ATIME		0
+#define STATX_MTIME		0
+#define STATX_CTIME		0
+#define STATX_INO		0
+#define STATX_SIZE		0
+#define STATX_BLOCKS		0
+#define STATX_BASIC_STATS	0
+#define STATX_BTIME		0
+#define STATX_ALL		0
+#endif
+#endif
--- src/timeout.c
+++ src/timeout.c	2022-03-02 13:13:55.046708714 +0000
@@ -42,6 +42,9 @@
 #include <wait.h>
 
 #include "timeout.h"
+#if defined(HAVE_SYSCALL_STATX) || (defined(HAVE_DECL_SYS_STATX) && HAVE_DECL_SYS_STATX == 1)
+#include "statx.h"
+#endif
 
 #if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L)
 # ifndef  destructor
@@ -72,6 +75,7 @@
 # define strcpy(d,s)		__builtin_strcpy((d),(s))   /* Without boundary check please */
 #endif
 
+#if !defined(HAVE_SYSCALL_STATX) && !(defined(HAVE_DECL_SYS_STATX) && HAVE_DECL_SYS_STATX == 1)
 #if WITH_TIMEOUT_STAT
 static sigjmp_buf jenv;
 static void sigjump(int sig attribute((unused)))
@@ -79,6 +83,7 @@ static void sigjump(int sig attribute((u
 	siglongjmp(jenv, 1);
 }
 #endif
+#endif
 
 #if WITH_TIMEOUT_STAT == 2
 /*
@@ -103,6 +108,7 @@ typedef struct _handle {
  * with (p)threads as SIGKILL would kill all threads including main.
  */
 
+#if !defined(HAVE_SYSCALL_STATX) && !(defined(HAVE_DECL_SYS_STATX) && HAVE_DECL_SYS_STATX == 1)
 static volatile pid_t active;
 static handle_t *handle;
 static const size_t buflen = PATH_MAX+sizeof(handle_t)+1;
@@ -198,6 +204,7 @@ static void attribute((destructor)) stop
 	if (active && waitpid(active, NULL, WNOHANG|WUNTRACED) == 0)
 		kill(active, SIGKILL);
 }
+#endif
 
 /*
  * External routine
@@ -209,14 +216,16 @@ static void attribute((destructor)) stop
 int
 timeout(stat_t function, const char *path, struct stat *restrict argument, time_t seconds)
 {
+#if !defined(HAVE_SYSCALL_STATX) && !(defined(HAVE_DECL_SYS_STATX) && HAVE_DECL_SYS_STATX == 1)
 	struct sigaction alrm_act, new_act;
 	sigset_t sigset, oldset;
 
 	if (active <= 0)	/* Oops, last one failed therefore clear status and restart */
 		start();
 	if (!handle)		/* No shared memory area */
+#endif
 		return function(path, argument);
-
+#if !defined(HAVE_SYSCALL_STATX) && !(defined(HAVE_DECL_SYS_STATX) && HAVE_DECL_SYS_STATX == 1)
 	handle->len = strlen(path) + 1;
 	if (handle->len >= PATH_MAX) {
 		errno = ENAMETOOLONG;
@@ -269,6 +278,7 @@ timed:
 	errno = ETIMEDOUT;
 error:
 	return -1;
+#endif
 }
 #elif WITH_TIMEOUT_STAT == 1
 /*
openSUSE Build Service is sponsored by