updated: [master] [eb1375b] vfs: implement support for all known stat formats and centralize handling

0 views
Skip to first unread message

Yury V. Zaytsev

unread,
Jul 28, 2024, 4:01:35 AM7/28/24
to mc-co...@googlegroups.com
The following commit has been merged in the master branch:
commit eb1375b65d88ede942195261fbc9e36986f2c7f4
Author: Yury V. Zaytsev <yu...@shurup.com>
Date: Sat Jun 1 17:44:28 2024 +0200

vfs: implement support for all known stat formats and centralize handling

Signed-off-by: Yury V. Zaytsev <yu...@shurup.com>

diff --git a/configure.ac b/configure.ac
index 12556f5..a18defa 100644
--- a/configure.ac
+++ b/configure.ac
@@ -261,7 +261,7 @@ AC_CHECK_TYPE([major_t], [], [AC_DEFINE([major_t], [int], [Type of major device
AC_CHECK_TYPE([minor_t], [], [AC_DEFINE([minor_t], [int], [Type of minor device numbers.])])

AC_STRUCT_ST_BLOCKS
-AC_CHECK_MEMBERS([struct stat.st_blksize, struct stat.st_rdev, struct stat.st_mtim])
+AC_CHECK_MEMBERS([struct stat.st_blksize, struct stat.st_rdev, struct stat.st_mtim, struct stat.st_mtimespec, struct stat.st_mtimensec])
gl_STAT_SIZE

AH_TEMPLATE([sig_atomic_t],
@@ -387,14 +387,7 @@ AC_EGREP_CPP([yes],
])

dnl utimensat is supported since glibc 2.6 and specified in POSIX.1-2008
-dnl utimensat() causes different timespec structures to cause failures on IBM i and AIX
-case $host_os in
-*os400 | aix*)
- ;;
-*)
- AC_CHECK_FUNCS([utimensat])
- ;;
-esac
+AC_CHECK_FUNCS([utimensat])

case $host_os in
*os400)
diff --git a/lib/unixcompat.h b/lib/unixcompat.h
index 591a709..c5d3aac 100644
--- a/lib/unixcompat.h
+++ b/lib/unixcompat.h
@@ -113,13 +113,6 @@
#define get_default_editor() "vi"
#define OS_SORT_CASE_SENSITIVE_DEFAULT TRUE

-/* struct stat members */
-#ifdef __APPLE__
-#define st_atim st_atimespec
-#define st_ctim st_ctimespec
-#define st_mtim st_mtimespec
-#endif
-
/*** enums ***************************************************************************************/

/*** structures declarations (and typedefs of structures)*****************************************/
diff --git a/lib/vfs/direntry.c b/lib/vfs/direntry.c
index 294df5f..b0db914 100644
--- a/lib/vfs/direntry.c
+++ b/lib/vfs/direntry.c
@@ -1030,10 +1030,7 @@ vfs_s_default_stat (struct vfs_class *me, mode_t mode)
#endif
st.st_size = 0;

- st.st_mtime = st.st_atime = st.st_ctime = time (NULL);
-#ifdef HAVE_STRUCT_STAT_ST_MTIM
- st.st_atim.tv_nsec = st.st_mtim.tv_nsec = st.st_ctim.tv_nsec = 0;
-#endif
+ vfs_zero_stat_times (&st);

vfs_adjust_stat (&st);

diff --git a/lib/vfs/parse_ls_vga.c b/lib/vfs/parse_ls_vga.c
index dd30425..0f8de3d 100644
--- a/lib/vfs/parse_ls_vga.c
+++ b/lib/vfs/parse_ls_vga.c
@@ -796,15 +796,14 @@ vfs_parse_ls_lga (const char *p, struct stat *s, char **filename, char **linknam
#endif
}

+ vfs_zero_stat_times (s);
+
idx = vfs_parse_filedate (idx, &s->st_mtime);
if (idx == 0)
goto error;

/* Use resulting time value */
s->st_atime = s->st_ctime = s->st_mtime;
-#ifdef HAVE_STRUCT_STAT_ST_MTIM
- s->st_atim.tv_nsec = s->st_mtim.tv_nsec = s->st_ctim.tv_nsec = 0;
-#endif

/* s->st_dev and s->st_ino must be initialized by vfs_s_new_inode () */
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
diff --git a/lib/vfs/utilvfs.c b/lib/vfs/utilvfs.c
index b322d63..0fb0a3c 100644
--- a/lib/vfs/utilvfs.c
+++ b/lib/vfs/utilvfs.c
@@ -408,15 +408,70 @@ vfs_get_timespecs_from_timesbuf (mc_timesbuf_t *times, mc_timespec_t *atime, mc_
/* --------------------------------------------------------------------------------------------- */

void
-vfs_get_timesbuf_from_stat (const struct stat *sb, mc_timesbuf_t *times)
+vfs_get_timesbuf_from_stat (const struct stat *s, mc_timesbuf_t *times)
{
#ifdef HAVE_UTIMENSAT
- (*times)[0] = sb->st_atim;
- (*times)[1] = sb->st_mtim;
+#ifdef HAVE_STRUCT_STAT_ST_MTIM
+ /* POSIX IEEE Std 1003.1-2008 should be the preferred way
+ *
+ * AIX has internal type st_timespec_t conflicting with timespec, so assign per field, for details see:
+ * https://github.com/libuv/libuv/pull/4404
+ */
+ (*times)[0].tv_sec = s->st_atim.tv_sec;
+ (*times)[0].tv_nsec = s->st_atim.tv_nsec;
+ (*times)[1].tv_sec = s->st_mtim.tv_sec;
+ (*times)[1].tv_nsec = s->st_mtim.tv_nsec;
+#elif HAVE_STRUCT_STAT_ST_MTIMESPEC
+ /* Modern BSD solution */
+ (*times)[0] = s->st_atimespec;
+ (*times)[1] = s->st_mtimespec;
+#elif HAVE_STRUCT_STAT_ST_MTIMENSEC
+ /* Legacy BSD solution */
+ (*times)[0].tv_sec = s->st_atime;
+ (*times)[0].tv_nsec = s->st_atimensec;
+ (*times)[1].tv_sec = s->st_mtime;
+ (*times)[1].tv_nsec = s->st_mtimensec;
#else
- times->actime = sb->st_atime;
- times->modtime = sb->st_mtime;
+#error "Found utimensat for nanosecond timestamps, but unsupported struct stat format!"
#endif
+#else
+ times->actime = s->st_atime;
+ times->modtime = s->st_mtime;
+#endif
+}
+
+/* --------------------------------------------------------------------------------------------- */
+
+void
+vfs_copy_stat_times (const struct stat *src, struct stat *dst)
+{
+ dst->st_atime = src->st_atime;
+ dst->st_mtime = src->st_mtime;
+ dst->st_ctime = src->st_ctime;
+
+#ifdef HAVE_STRUCT_STAT_ST_MTIM
+ dst->st_atim.tv_nsec = src->st_atim.tv_nsec;
+ dst->st_mtim.tv_nsec = src->st_mtim.tv_nsec;
+ dst->st_ctim.tv_nsec = src->st_ctim.tv_nsec;
+#elif HAVE_STRUCT_STAT_ST_MTIMESPEC
+ dst->st_atimespec.tv_nsec = src->st_atimespec.tv_nsec;
+ dst->st_mtimespec.tv_nsec = src->st_mtimespec.tv_nsec;
+ dst->st_ctimespec.tv_nsec = src->st_ctimespec.tv_nsec;
+#elif HAVE_STRUCT_STAT_ST_MTIMENSEC
+ dst->st_atimensec = src->st_atimensec;
+ dst->st_mtimensec = src->st_mtimensec;
+ dst->st_ctimensec = src->st_ctimensec;
+#endif
+}
+
+/* --------------------------------------------------------------------------------------------- */
+
+void
+vfs_zero_stat_times (struct stat *s)
+{
+ const struct stat empty = { 0 };
+
+ vfs_copy_stat_times (&empty, s);
}

/* --------------------------------------------------------------------------------------------- */
diff --git a/lib/vfs/utilvfs.h b/lib/vfs/utilvfs.h
index 4f4772d..ff94bdb 100644
--- a/lib/vfs/utilvfs.h
+++ b/lib/vfs/utilvfs.h
@@ -63,7 +63,9 @@ int vfs_parse_filedate (int idx, time_t * t);
int vfs_utime (const char *path, mc_timesbuf_t *times);
void vfs_get_timespecs_from_timesbuf (mc_timesbuf_t *times, mc_timespec_t *atime,
mc_timespec_t *mtime);
-void vfs_get_timesbuf_from_stat (const struct stat *sb, mc_timesbuf_t *times);
+void vfs_get_timesbuf_from_stat (const struct stat *s, mc_timesbuf_t *times);
+void vfs_copy_stat_times (const struct stat *src, struct stat *dst);
+void vfs_zero_stat_times (struct stat *s);

/*** inline functions ****************************************************************************/

diff --git a/src/vfs/cpio/cpio.c b/src/vfs/cpio/cpio.c
index f14443f..035876e 100644
--- a/src/vfs/cpio/cpio.c
+++ b/src/vfs/cpio/cpio.c
@@ -470,15 +470,8 @@ cpio_create_entry (struct vfs_class *me, struct vfs_s_super *super, struct stat
entry->ino->st.st_mode = st->st_mode;
entry->ino->st.st_uid = st->st_uid;
entry->ino->st.st_gid = st->st_gid;
-#ifdef HAVE_STRUCT_STAT_ST_MTIM
- entry->ino->st.st_atim = st->st_atim;
- entry->ino->st.st_mtim = st->st_mtim;
- entry->ino->st.st_ctim = st->st_ctim;
-#else
- entry->ino->st.st_atime = st->st_atime;
- entry->ino->st.st_mtime = st->st_mtime;
- entry->ino->st.st_ctime = st->st_ctime;
-#endif
+
+ vfs_copy_stat_times (st, &entry->ino->st);
}

g_free (name);
@@ -603,9 +596,9 @@ cpio_read_bin_head (struct vfs_class *me, struct vfs_s_super *super)
st.st_rdev = u.buf.c_rdev;
#endif
st.st_size = ((off_t) u.buf.c_filesizes[0] << 16) | u.buf.c_filesizes[1];
-#ifdef HAVE_STRUCT_STAT_ST_MTIM
- st.st_atim.tv_nsec = st.st_mtim.tv_nsec = st.st_ctim.tv_nsec = 0;
-#endif
+
+ vfs_zero_stat_times (&st);
+
st.st_atime = st.st_mtime = st.st_ctime =
((time_t) u.buf.c_mtimes[0] << 16) | u.buf.c_mtimes[1];

@@ -676,9 +669,8 @@ cpio_read_oldc_head (struct vfs_class *me, struct vfs_s_super *super)
u.st.st_rdev = hd.c_rdev;
#endif
u.st.st_size = hd.c_filesize;
-#ifdef HAVE_STRUCT_STAT_ST_MTIM
- u.st.st_atim.tv_nsec = u.st.st_mtim.tv_nsec = u.st.st_ctim.tv_nsec = 0;
-#endif
+
+ vfs_zero_stat_times (&u.st);
u.st.st_atime = u.st.st_mtime = u.st.st_ctime = hd.c_mtime;

return cpio_create_entry (me, super, &u.st, name);
@@ -757,9 +749,8 @@ cpio_read_crc_head (struct vfs_class *me, struct vfs_s_super *super)
u.st.st_rdev = makedev (hd.c_rdev, hd.c_rdevmin);
#endif
u.st.st_size = hd.c_filesize;
-#ifdef HAVE_STRUCT_STAT_ST_MTIM
- u.st.st_atim.tv_nsec = u.st.st_mtim.tv_nsec = u.st.st_ctim.tv_nsec = 0;
-#endif
+
+ vfs_zero_stat_times (&u.st);
u.st.st_atime = u.st.st_mtime = u.st.st_ctime = hd.c_mtime;

return cpio_create_entry (me, super, &u.st, name);
diff --git a/src/vfs/extfs/extfs.c b/src/vfs/extfs/extfs.c
index 2e85227..279c7f1 100644
--- a/src/vfs/extfs/extfs.c
+++ b/src/vfs/extfs/extfs.c
@@ -1230,15 +1230,22 @@ extfs_closedir (void *data)
static void
extfs_stat_move (struct stat *buf, const struct vfs_s_inode *inode)
{
+ const time_t atime = inode->st.st_atime;
+ const time_t mtime = inode->st.st_mtime;
+ const time_t ctime = inode->st.st_ctime;
+
*buf = inode->st;

#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
buf->st_blksize = RECORDSIZE;
#endif
+
vfs_adjust_stat (buf);
-#ifdef HAVE_STRUCT_STAT_ST_MTIM
- buf->st_atim.tv_nsec = buf->st_mtim.tv_nsec = buf->st_ctim.tv_nsec = 0;
-#endif
+ vfs_zero_stat_times (buf);
+
+ buf->st_atime = atime;
+ buf->st_mtime = mtime;
+ buf->st_ctime = ctime;
}

/* --------------------------------------------------------------------------------------------- */
diff --git a/src/vfs/sftpfs/internal.c b/src/vfs/sftpfs/internal.c
index a229de4..b94668d 100644
--- a/src/vfs/sftpfs/internal.c
+++ b/src/vfs/sftpfs/internal.c
@@ -37,6 +37,7 @@

#include "lib/global.h"
#include "lib/util.h"
+#include "lib/vfs/utilvfs.h"

#include "internal.h"

@@ -255,12 +256,10 @@ sftpfs_attr_to_stat (const LIBSSH2_SFTP_ATTRIBUTES *attrs, struct stat *s)

if ((attrs->flags & LIBSSH2_SFTP_ATTR_ACMODTIME) != 0)
{
+ vfs_zero_stat_times (s);
s->st_atime = attrs->atime;
s->st_mtime = attrs->mtime;
s->st_ctime = attrs->mtime;
-#ifdef HAVE_STRUCT_STAT_ST_MTIM
- s->st_atim.tv_nsec = s->st_mtim.tv_nsec = s->st_ctim.tv_nsec = 0;
-#endif
}

if ((attrs->flags & LIBSSH2_SFTP_ATTR_SIZE) != 0)
diff --git a/src/vfs/shell/shell.c b/src/vfs/shell/shell.c
index dc053cd..f413377 100644
--- a/src/vfs/shell/shell.c
+++ b/src/vfs/shell/shell.c
@@ -860,12 +860,10 @@ shell_parse_ls (char *buffer, struct vfs_s_entry *ent)

case 'd':
vfs_split_text (buffer);
+ vfs_zero_stat_times (&ST);
if (vfs_parse_filedate (0, &ST.st_ctime) == 0)
break;
ST.st_atime = ST.st_mtime = ST.st_ctime;
-#ifdef HAVE_STRUCT_STAT_ST_MTIM
- ST.st_atim.tv_nsec = ST.st_mtim.tv_nsec = ST.st_ctim.tv_nsec = 0;
-#endif
break;

case 'D':
@@ -877,10 +875,8 @@ shell_parse_ls (char *buffer, struct vfs_s_entry *ent)
if (sscanf (buffer, "%d %d %d %d %d %d", &tim.tm_year, &tim.tm_mon,
&tim.tm_mday, &tim.tm_hour, &tim.tm_min, &tim.tm_sec) != 6)
break;
+ vfs_zero_stat_times (&ST);
ST.st_atime = ST.st_mtime = ST.st_ctime = mktime (&tim);
-#ifdef HAVE_STRUCT_STAT_ST_MTIM
- ST.st_atim.tv_nsec = ST.st_mtim.tv_nsec = ST.st_ctim.tv_nsec = 0;
-#endif
}
break;

diff --git a/src/vfs/undelfs/undelfs.c b/src/vfs/undelfs/undelfs.c
index 6292612..d8cefcd 100644
--- a/src/vfs/undelfs/undelfs.c
+++ b/src/vfs/undelfs/undelfs.c
@@ -631,12 +631,12 @@ undelfs_stat_int (int inode_index, struct stat *buf)
buf->st_uid = delarray[inode_index].uid;
buf->st_gid = delarray[inode_index].gid;
buf->st_size = delarray[inode_index].size;
+
+ vfs_zero_stat_times (buf);
buf->st_atime = delarray[inode_index].dtime;
buf->st_ctime = delarray[inode_index].dtime;
buf->st_mtime = delarray[inode_index].dtime;
-#ifdef HAVE_STRUCT_STAT_ST_MTIM
- buf->st_atim.tv_nsec = buf->st_mtim.tv_nsec = buf->st_ctim.tv_nsec = 0;
-#endif
+
return 0;
}

diff --git a/tests/lib/vfs/vfs_parse_ls_lga.c b/tests/lib/vfs/vfs_parse_ls_lga.c
index 316de8f..4867ada 100644
--- a/tests/lib/vfs/vfs_parse_ls_lga.c
+++ b/tests/lib/vfs/vfs_parse_ls_lga.c
@@ -106,10 +106,7 @@ message (int flags, const char *title, const char *text, ...)
static void
fill_stat_struct (struct stat *etalon_stat, int iterator)
{
-
-#ifdef HAVE_STRUCT_STAT_ST_MTIM
- etalon_stat->st_atim.tv_nsec = etalon_stat->st_mtim.tv_nsec = etalon_stat->st_ctim.tv_nsec = 0;
-#endif
+ vfs_zero_stat_times (etalon_stat);

switch (iterator)
{

--
Midnight Commander Development
Reply all
Reply to author
Forward
0 new messages