From: ChenXiaoSong <chenxiaosong@chenxiaosong.com>
To: smfrench@gmail.com, linkinjeon@kernel.org, pc@manguebit.org,
ronniesahlberg@gmail.com, sprasad@microsoft.com, tom@talpey.com,
bharathsm@microsoft.com, senozhatsky@chromium.org,
dhowells@redhat.com, metze@samba.org, zlang@kernel.org,
lukas@herbolt.com
Cc: linux-cifs@vger.kernel.org, fstests@vger.kernel.org,
ChenXiaoSong <chenxiaosong@kylinos.cn>
Subject: [PATCH v2 xfstests resend 1/3] src: factor out common stat code
Date: Mon, 20 Jul 2026 16:42:05 +0000 [thread overview]
Message-ID: <20260720164207.732522-2-chenxiaosong@chenxiaosong.com> (raw)
In-Reply-To: <20260720164207.732522-1-chenxiaosong@chenxiaosong.com>
From: ChenXiaoSong <chenxiaosong@kylinos.cn>
To see only the differences in the code copied from lstat64.c to
stat_common.c, run:
git show --find-copies --diff-filter=C <commit-id>
Move command-line parsing and stat output formatting from lstat64 into
stat_common so the implementation can be shared by other stat helpers.
No functional change.
Suggested-by: Zorro Lang <zlang@kernel.org>
Signed-off-by: ChenXiaoSong <chenxiaosong@kylinos.cn>
---
src/Makefile | 11 ++-
src/lstat64.c | 166 +----------------------------------------
src/stat_common.c | 185 ++++++++++++++++++++++++++++++++++++++++++++++
src/stat_common.h | 16 ++++
4 files changed, 212 insertions(+), 166 deletions(-)
create mode 100644 src/stat_common.c
create mode 100644 src/stat_common.h
diff --git a/src/Makefile b/src/Makefile
index 31ac43b2..7fab5d05 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -115,7 +115,8 @@ ifeq ($(NEED_INTERNAL_XFS_IOC_EXCHANGE_RANGE),yes)
LCFLAGS += -DNEED_INTERNAL_XFS_IOC_EXCHANGE_RANGE
endif
-CFILES = $(TARGETS:=.c)
+CFILES = $(TARGETS:=.c) stat_common.c
+HFILES = stat_common.h
LDIRT = $(TARGETS) fssum
@@ -129,7 +130,13 @@ fssum: fssum.c md5.c
@echo " [CC] $@"
$(Q)$(LTLINK) fssum.c md5.c -o $@ $(CFLAGS) $(LDFLAGS) $(LDLIBS)
-$(TARGETS): $(LIBTEST)
+STAT_TARGETS = lstat64
+
+$(STAT_TARGETS): %: %.c stat_common.c stat_common.h $(LIBTEST)
+ @echo " [CC] $@"
+ $(Q)$(LTLINK) $@.c stat_common.c -o $@ $(CFLAGS) $(LDFLAGS) $(LDLIBS) $(LIBTEST)
+
+$(filter-out $(STAT_TARGETS),$(TARGETS)): $(LIBTEST)
@echo " [CC] $@"
$(Q)$(LTLINK) $@.c -o $@ $(CFLAGS) $(LDFLAGS) $(LDLIBS) $(LIBTEST)
diff --git a/src/lstat64.c b/src/lstat64.c
index db8726fd..5cca2347 100644
--- a/src/lstat64.c
+++ b/src/lstat64.c
@@ -12,172 +12,10 @@
#include <sys/stat.h>
#include <sys/sysmacros.h>
-long timebuf;
-
-void
-timesince(long timesec)
-{
- long d_since; /* days */
- long h_since; /* hours */
- long m_since; /* minutes */
- long s_since; /* seconds */
-
- s_since = timebuf - timesec;
- d_since = s_since / 86400l ;
- s_since -= d_since * 86400l ;
- h_since = s_since / 3600l ;
- s_since -= h_since * 3600l ;
- m_since = s_since / 60l ;
- s_since -= m_since * 60l ;
-
- printf("(%05ld.%02ld:%02ld:%02ld)\n",
- d_since, h_since, m_since, s_since);
-}
-
-void
-usage(void)
-{
- fprintf(stderr, "Usage: lstat64 [-t] filename ...\n");
- exit(1);
-}
+#include "stat_common.h"
int
main(int argc, char **argv)
{
- struct stat64 sbuf;
- int i, c;
- int terse_flag = 0;
-
- while ((c = getopt(argc, argv, "t")) != EOF) {
- switch (c) {
- case 't':
- terse_flag = 1;
- break;
-
- case '?':
- usage();
- }
- }
- if (optind == argc) {
- usage();
- }
-
- time(&timebuf);
-
- for (i = optind; i < argc; i++) {
- char mode[] = "----------";
-
- if( lstat64(argv[i], &sbuf) < 0) {
- perror(argv[i]);
- continue;
- }
-
- if (terse_flag) {
- printf("%s %llu ", argv[i], (unsigned long long)sbuf.st_size);
- }
- else {
- printf(" File: \"%s\"\n", argv[i]);
- printf(" Size: %-10llu", (unsigned long long)sbuf.st_size);
- }
-
- if (sbuf.st_mode & S_IXOTH)
- mode[9] = 'x';
- if (sbuf.st_mode & S_IWOTH)
- mode[8] = 'w';
- if (sbuf.st_mode & S_IROTH)
- mode[7] = 'r';
- if (sbuf.st_mode & S_IXGRP)
- mode[6] = 'x';
- if (sbuf.st_mode & S_IWGRP)
- mode[5] = 'w';
- if (sbuf.st_mode & S_IRGRP)
- mode[4] = 'r';
- if (sbuf.st_mode & S_IXUSR)
- mode[3] = 'x';
- if (sbuf.st_mode & S_IWUSR)
- mode[2] = 'w';
- if (sbuf.st_mode & S_IRUSR)
- mode[1] = 'r';
- if (sbuf.st_mode & S_ISVTX)
- mode[9] = 't';
- if (sbuf.st_mode & S_ISGID)
- mode[6] = 's';
- if (sbuf.st_mode & S_ISUID)
- mode[3] = 's';
-
- if (!terse_flag)
- printf(" Filetype: ");
- switch (sbuf.st_mode & S_IFMT) {
- case S_IFSOCK:
- if (!terse_flag)
- puts("Socket");
- mode[0] = 's';
- break;
- case S_IFDIR:
- if (!terse_flag)
- puts("Directory");
- mode[0] = 'd';
- break;
- case S_IFCHR:
- if (!terse_flag)
- puts("Character Device");
- mode[0] = 'c';
- break;
- case S_IFBLK:
- if (!terse_flag)
- puts("Block Device");
- mode[0] = 'b';
- break;
- case S_IFREG:
- if (!terse_flag)
- puts("Regular File");
- mode[0] = '-';
- break;
- case S_IFLNK:
- if (!terse_flag)
- puts("Symbolic Link");
- mode[0] = 'l';
- break;
- case S_IFIFO:
- if (!terse_flag)
- puts("Fifo File");
- mode[0] = 'f';
- break;
- default:
- if (!terse_flag)
- puts("Unknown");
- mode[0] = '?';
- }
-
- if (terse_flag) {
- printf("%s %d,%d\n", mode, (int)sbuf.st_uid, (int)sbuf.st_gid);
- continue;
- }
-
- printf(" Mode: (%04o/%s)", (unsigned int)(sbuf.st_mode & 07777), mode);
- printf(" Uid: (%d)", (int)sbuf.st_uid);
- printf(" Gid: (%d)\n", (int)sbuf.st_gid);
- printf("Device: %2d,%-2d", major(sbuf.st_dev),
- minor(sbuf.st_dev));
- printf(" Inode: %-9llu", (unsigned long long)sbuf.st_ino);
- printf(" Links: %-5ld", (long)sbuf.st_nlink);
-
- if ( ((sbuf.st_mode & S_IFMT) == S_IFCHR)
- || ((sbuf.st_mode & S_IFMT) == S_IFBLK) )
- printf(" Device type: %2d,%-2d\n",
- major(sbuf.st_rdev), minor(sbuf.st_rdev));
- else
- printf("\n");
-
- printf("Access: %.24s",ctime(&sbuf.st_atime));
- timesince(sbuf.st_atime);
- printf("Modify: %.24s",ctime(&sbuf.st_mtime));
- timesince(sbuf.st_mtime);
- printf("Change: %.24s",ctime(&sbuf.st_ctime));
- timesince(sbuf.st_ctime);
-
- if (i+1 < argc)
- printf("\n");
- }
- exit(0);
+ return handle_stat(argc, argv, "lstat64", lstat64);
}
diff --git a/src/stat_common.c b/src/stat_common.c
new file mode 100644
index 00000000..e94114ff
--- /dev/null
+++ b/src/stat_common.c
@@ -0,0 +1,185 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2000-2002 Silicon Graphics, Inc.
+ * All Rights Reserved.
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <sys/sysmacros.h>
+
+#include "stat_common.h"
+
+long timebuf;
+
+void
+timesince(long timesec)
+{
+ long d_since; /* days */
+ long h_since; /* hours */
+ long m_since; /* minutes */
+ long s_since; /* seconds */
+
+ s_since = timebuf - timesec;
+ d_since = s_since / 86400l ;
+ s_since -= d_since * 86400l ;
+ h_since = s_since / 3600l ;
+ s_since -= h_since * 3600l ;
+ m_since = s_since / 60l ;
+ s_since -= m_since * 60l ;
+
+ printf("(%05ld.%02ld:%02ld:%02ld)\n",
+ d_since, h_since, m_since, s_since);
+}
+
+void
+usage(const char *program)
+{
+ fprintf(stderr, "Usage: %s [-t] filename ...\n", program);
+ exit(1);
+}
+
+int
+handle_stat(int argc, char **argv, const char *program, get_stat_fn get_stat)
+{
+ struct stat64 sbuf;
+ int i, c;
+ int terse_flag = 0;
+
+ while ((c = getopt(argc, argv, "t")) != EOF) {
+ switch (c) {
+ case 't':
+ terse_flag = 1;
+ break;
+
+ case '?':
+ usage(program);
+ }
+ }
+ if (optind == argc) {
+ usage(program);
+ }
+
+ time(&timebuf);
+
+ for (i = optind; i < argc; i++) {
+ char mode[] = "----------";
+
+ if(get_stat(argv[i], &sbuf) < 0) {
+ perror(argv[i]);
+ continue;
+ }
+
+ if (terse_flag) {
+ printf("%s %llu ", argv[i], (unsigned long long)sbuf.st_size);
+ }
+ else {
+ printf(" File: \"%s\"\n", argv[i]);
+ printf(" Size: %-10llu", (unsigned long long)sbuf.st_size);
+ }
+
+ if (sbuf.st_mode & S_IXOTH)
+ mode[9] = 'x';
+ if (sbuf.st_mode & S_IWOTH)
+ mode[8] = 'w';
+ if (sbuf.st_mode & S_IROTH)
+ mode[7] = 'r';
+ if (sbuf.st_mode & S_IXGRP)
+ mode[6] = 'x';
+ if (sbuf.st_mode & S_IWGRP)
+ mode[5] = 'w';
+ if (sbuf.st_mode & S_IRGRP)
+ mode[4] = 'r';
+ if (sbuf.st_mode & S_IXUSR)
+ mode[3] = 'x';
+ if (sbuf.st_mode & S_IWUSR)
+ mode[2] = 'w';
+ if (sbuf.st_mode & S_IRUSR)
+ mode[1] = 'r';
+ if (sbuf.st_mode & S_ISVTX)
+ mode[9] = 't';
+ if (sbuf.st_mode & S_ISGID)
+ mode[6] = 's';
+ if (sbuf.st_mode & S_ISUID)
+ mode[3] = 's';
+
+ if (!terse_flag)
+ printf(" Filetype: ");
+ switch (sbuf.st_mode & S_IFMT) {
+ case S_IFSOCK:
+ if (!terse_flag)
+ puts("Socket");
+ mode[0] = 's';
+ break;
+ case S_IFDIR:
+ if (!terse_flag)
+ puts("Directory");
+ mode[0] = 'd';
+ break;
+ case S_IFCHR:
+ if (!terse_flag)
+ puts("Character Device");
+ mode[0] = 'c';
+ break;
+ case S_IFBLK:
+ if (!terse_flag)
+ puts("Block Device");
+ mode[0] = 'b';
+ break;
+ case S_IFREG:
+ if (!terse_flag)
+ puts("Regular File");
+ mode[0] = '-';
+ break;
+ case S_IFLNK:
+ if (!terse_flag)
+ puts("Symbolic Link");
+ mode[0] = 'l';
+ break;
+ case S_IFIFO:
+ if (!terse_flag)
+ puts("Fifo File");
+ mode[0] = 'f';
+ break;
+ default:
+ if (!terse_flag)
+ puts("Unknown");
+ mode[0] = '?';
+ }
+
+ if (terse_flag) {
+ printf("%s %d,%d\n", mode, (int)sbuf.st_uid, (int)sbuf.st_gid);
+ continue;
+ }
+
+ printf(" Mode: (%04o/%s)", (unsigned int)(sbuf.st_mode & 07777), mode);
+ printf(" Uid: (%d)", (int)sbuf.st_uid);
+ printf(" Gid: (%d)\n", (int)sbuf.st_gid);
+ printf("Device: %2d,%-2d", major(sbuf.st_dev),
+ minor(sbuf.st_dev));
+ printf(" Inode: %-9llu", (unsigned long long)sbuf.st_ino);
+ printf(" Links: %-5ld", (long)sbuf.st_nlink);
+
+ if ( ((sbuf.st_mode & S_IFMT) == S_IFCHR)
+ || ((sbuf.st_mode & S_IFMT) == S_IFBLK) )
+ printf(" Device type: %2d,%-2d\n",
+ major(sbuf.st_rdev), minor(sbuf.st_rdev));
+ else
+ printf("\n");
+
+ printf("Access: %.24s",ctime(&sbuf.st_atime));
+ timesince(sbuf.st_atime);
+ printf("Modify: %.24s",ctime(&sbuf.st_mtime));
+ timesince(sbuf.st_mtime);
+ printf("Change: %.24s",ctime(&sbuf.st_ctime));
+ timesince(sbuf.st_ctime);
+
+ if (i+1 < argc)
+ printf("\n");
+ }
+ exit(0);
+}
diff --git a/src/stat_common.h b/src/stat_common.h
new file mode 100644
index 00000000..290643d7
--- /dev/null
+++ b/src/stat_common.h
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2000-2002 Silicon Graphics, Inc.
+ * All Rights Reserved.
+ */
+
+#ifndef STAT_COMMON_H
+#define STAT_COMMON_H
+
+#include <sys/stat.h>
+
+typedef int (*get_stat_fn)(const char *path, struct stat64 *sbuf);
+
+int handle_stat(int argc, char **argv, const char *program, get_stat_fn get_stat);
+
+#endif /* STAT_COMMON_H */
--
2.43.0
next prev parent reply other threads:[~2026-07-20 16:42 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-20 16:42 [PATCH v2 xfstests resend 0/3] add generic/795 ChenXiaoSong
2026-07-20 16:42 ` ChenXiaoSong [this message]
2026-07-20 16:42 ` [PATCH v2 xfstests resend 2/3] generic/002: clean up the test ChenXiaoSong
2026-07-20 16:42 ` [PATCH v2 xfstests resend 3/3] generic/795: check nlink returned by fstat() ChenXiaoSong
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260720164207.732522-2-chenxiaosong@chenxiaosong.com \
--to=chenxiaosong@chenxiaosong.com \
--cc=bharathsm@microsoft.com \
--cc=chenxiaosong@kylinos.cn \
--cc=dhowells@redhat.com \
--cc=fstests@vger.kernel.org \
--cc=linkinjeon@kernel.org \
--cc=linux-cifs@vger.kernel.org \
--cc=lukas@herbolt.com \
--cc=metze@samba.org \
--cc=pc@manguebit.org \
--cc=ronniesahlberg@gmail.com \
--cc=senozhatsky@chromium.org \
--cc=smfrench@gmail.com \
--cc=sprasad@microsoft.com \
--cc=tom@talpey.com \
--cc=zlang@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox