#include "xgethostname.h"
#include "c-ctype.h"
#include "canonicalize.h"
+#include "statx.h"
/* Include <sys/capability.h> last to avoid a clash of <sys/types.h>
include guards with some premature versions of libcap.
}
}
+#if HAVE_STATX && defined STATX_INO
+static unsigned int _GL_ATTRIBUTE_PURE
+time_type_to_statx (void)
+{
+ switch (time_type)
+ {
+ case time_ctime:
+ return STATX_CTIME;
+ case time_mtime:
+ return STATX_MTIME;
+ case time_atime:
+ return STATX_ATIME;
+ default:
+ abort ();
+ }
+ return 0;
+}
+
+static unsigned int _GL_ATTRIBUTE_PURE
+calc_req_mask (void)
+{
+ unsigned int mask = STATX_MODE;
+
+ if (print_inode)
+ mask |= STATX_INO;
+
+ if (print_block_size)
+ mask |= STATX_BLOCKS;
+
+ if (format == long_format) {
+ mask |= STATX_NLINK | STATX_SIZE | time_type_to_statx ();
+ if (print_owner || print_author)
+ mask |= STATX_UID;
+ if (print_group)
+ mask |= STATX_GID;
+ }
+
+ switch (sort_type)
+ {
+ case sort_none:
+ case sort_name:
+ case sort_version:
+ case sort_extension:
+ break;
+ case sort_time:
+ mask |= time_type_to_statx ();
+ break;
+ case sort_size:
+ mask |= STATX_SIZE;
+ break;
+ default:
+ abort ();
+ }
+
+ return mask;
+}
+
+static int
+do_statx (int fd, const char *name, struct stat *st, int flags,
+ unsigned int mask)
+{
+ struct statx stx;
+ int ret = statx (fd, name, flags, mask, &stx);
+ if (ret >= 0)
+ statx_to_stat (&stx, st);
+ return ret;
+}
+
+static inline int
+do_stat (const char *name, struct stat *st)
+{
+ return do_statx (AT_FDCWD, name, st, 0, calc_req_mask ());
+}
+
+static inline int
+do_lstat (const char *name, struct stat *st)
+{
+ return do_statx (AT_FDCWD, name, st, AT_SYMLINK_NOFOLLOW, calc_req_mask ());
+}
+
+static inline int
+stat_for_mode (const char *name, struct stat *st)
+{
+ return do_statx (AT_FDCWD, name, st, 0, STATX_MODE);
+}
+
+/* dev+ino should be static, so no need to sync with backing store */
+static inline int
+stat_for_ino (const char *name, struct stat *st)
+{
+ return do_statx (AT_FDCWD, name, st, 0, STATX_INO);
+}
+
+static inline int
+fstat_for_ino (int fd, struct stat *st)
+{
+ return do_statx (fd, "", st, AT_EMPTY_PATH, STATX_INO);
+}
+#else
+static inline int
+do_stat (const char *name, struct stat *st)
+{
+ return stat (name, st);
+}
+
+static inline int
+do_lstat (const char *name, struct stat *st)
+{
+ return lstat (name, st);
+}
+
+static inline int
+stat_for_mode (const char *name, struct stat *st)
+{
+ return stat (name, st);
+}
+
+static inline int
+stat_for_ino (const char *name, struct stat *st)
+{
+ return stat (name, st);
+}
+
+static inline int
+fstat_for_ino (int fd, struct stat *st)
+{
+ return fstat (fd, st);
+}
+#endif
+
/* Return the address of the first plain %b spec in FMT, or NULL if
there is no such spec. %5b etc. do not match, so that user
widths/flags are honored. */
struct stat dir_stat;
int fd = dirfd (dirp);
- /* If dirfd failed, endure the overhead of using stat. */
+ /* If dirfd failed, endure the overhead of stat'ing by path */
if ((0 <= fd
- ? fstat (fd, &dir_stat)
- : stat (name, &dir_stat)) < 0)
+ ? fstat_for_ino (fd, &dir_stat)
+ : stat_for_ino (name, &dir_stat)) < 0)
{
file_failure (command_line_arg,
_("cannot determine device and inode of %s"), name);
switch (dereference)
{
case DEREF_ALWAYS:
- err = stat (full_name, &f->stat);
+ err = do_stat (full_name, &f->stat);
do_deref = true;
break;
if (command_line_arg)
{
bool need_lstat;
- err = stat (full_name, &f->stat);
+ err = do_stat (full_name, &f->stat);
do_deref = true;
if (dereference == DEREF_COMMAND_LINE_ARGUMENTS)
FALLTHROUGH;
default: /* DEREF_NEVER */
- err = lstat (full_name, &f->stat);
+ err = do_lstat (full_name, &f->stat);
do_deref = false;
break;
}
they won't be traced and when no indicator is needed. */
if (linkname
&& (file_type <= indicator_style || check_symlink_mode)
- && stat (linkname, &linkstats) == 0)
+ && stat_for_mode (linkname, &linkstats) == 0)
{
f->linkok = true;
f->linkmode = linkstats.st_mode;
#include "strftime.h"
#include "find-mount-point.h"
#include "xvasprintf.h"
+#include "statx.h"
#if HAVE_STATX && defined STATX_INO
# define USE_STATX 1
static bool force_sync;
#if USE_STATX
-/* Much of the format printing requires a struct stat or timespec */
-static struct timespec
-statx_timestamp_to_timespec (struct statx_timestamp tsx)
-{
- struct timespec ts;
-
- ts.tv_sec = tsx.tv_sec;
- ts.tv_nsec = tsx.tv_nsec;
- return ts;
-}
-
-static void
-statx_to_stat (struct statx *stx, struct stat *stat)
-{
- stat->st_dev = makedev (stx->stx_dev_major, stx->stx_dev_minor);
- stat->st_ino = stx->stx_ino;
- stat->st_mode = stx->stx_mode;
- stat->st_nlink = stx->stx_nlink;
- stat->st_uid = stx->stx_uid;
- stat->st_gid = stx->stx_gid;
- stat->st_rdev = makedev (stx->stx_rdev_major, stx->stx_rdev_minor);
- stat->st_size = stx->stx_size;
- stat->st_blksize = stx->stx_blksize;
-/* define to avoid sc_prohibit_stat_st_blocks. */
-# define SC_ST_BLOCKS st_blocks
- stat->SC_ST_BLOCKS = stx->stx_blocks;
- stat->st_atim = statx_timestamp_to_timespec (stx->stx_atime);
- stat->st_mtim = statx_timestamp_to_timespec (stx->stx_mtime);
- stat->st_ctim = statx_timestamp_to_timespec (stx->stx_ctime);
-}
-
static unsigned int
fmt_to_mask (char fmt)
{
--- /dev/null
+/* statx -> stat conversion functions for coreutils
+ Copyright (C) 2019 Free Software Foundation, Inc.
+
+ 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 3 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, see <https://www.gnu.org/licenses/>. */
+
+#ifndef COREUTILS_STATX_H
+# define COREUTILS_STATX_H
+
+# if HAVE_STATX && defined STATX_INO
+/* Much of the format printing requires a struct stat or timespec */
+static inline struct timespec
+statx_timestamp_to_timespec (struct statx_timestamp tsx)
+{
+ struct timespec ts;
+
+ ts.tv_sec = tsx.tv_sec;
+ ts.tv_nsec = tsx.tv_nsec;
+ return ts;
+}
+
+static inline void
+statx_to_stat (struct statx *stx, struct stat *stat)
+{
+ stat->st_dev = makedev (stx->stx_dev_major, stx->stx_dev_minor);
+ stat->st_ino = stx->stx_ino;
+ stat->st_mode = stx->stx_mode;
+ stat->st_nlink = stx->stx_nlink;
+ stat->st_uid = stx->stx_uid;
+ stat->st_gid = stx->stx_gid;
+ stat->st_rdev = makedev (stx->stx_rdev_major, stx->stx_rdev_minor);
+ stat->st_size = stx->stx_size;
+ stat->st_blksize = stx->stx_blksize;
+/* define to avoid sc_prohibit_stat_st_blocks. */
+# define SC_ST_BLOCKS st_blocks
+ stat->SC_ST_BLOCKS = stx->stx_blocks;
+ stat->st_atim = statx_timestamp_to_timespec (stx->stx_atime);
+ stat->st_mtim = statx_timestamp_to_timespec (stx->stx_mtime);
+ stat->st_ctim = statx_timestamp_to_timespec (stx->stx_ctime);
+}
+# endif /* HAVE_STATX && defined STATX_INO */
+#endif /* COREUTILS_STATX_H */