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
/*