[PATCH] Initialize struct stat st_[acm]tim.tv_nsec when present

Yury V. Zaytsev yury at shurup.com
Sat May 6 19:06:39 UTC 2017


I've created a ticket and branch for this patch:

     https://midnight-commander.org/ticket/3821#comment:1

I've also patched all other places where stat is filled manually that I 
could find. The all builds & tests seem to run through.

Does this version work, or problems remain?

On Wed, 19 Apr 2017, Andrey Gursky wrote:

> struct stat in libc for Linux kernel contains few fields more since 14+
> years [1].
>
> from bits/stat.h:
>    struct timespec st_atim;            /* Time of last access.  */
>    struct timespec st_mtim;            /* Time of last modification.  */
>    struct timespec st_ctim;            /* Time of last status change.  */
> # define st_atime st_atim.tv_sec        /* Backward compatibility.  */
> # define st_mtime st_mtim.tv_sec
> # define st_ctime st_ctim.tv_sec
>
> The conventional fields became an alias.
>
> POSIX.1-2008 made struct stat st_[acm]tim mandatory [2].
>
> OS takes care to initialize struct stat properly [3]. By not using an
> OS syscall or a libc wrapper to fill struct stat, we have to take care
> of initializing all fields (or at least those being used later) explicitly.
>
> [1] https://www.sourceware.org/ml/libc-alpha/2002-12/msg00011.html
> [2] https://www.sourceware.org/ml/libc-alpha/2009-11/msg00102.html
> [3] https://www.sourceware.org/ml/libc-alpha/2002-12/msg00013.html
>
> Fixes: file timestamps not preserved (https://mail.gnome.org/archives/mc-devel/2017-April/msg00000.html)
> Reported-By: Nerijus Baliunas <nerijus at users.sourceforge.net>
> ---
> configure.ac        |  2 +-
> src/vfs/cpio/cpio.c | 15 +++++++++++++++
> src/vfs/tar/tar.c   |  3 +++
> 3 files changed, 19 insertions(+), 1 deletion(-)
>
> diff --git a/configure.ac b/configure.ac
> index 45836fcaf..387110daf 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -181,7 +181,7 @@ AC_TYPE_PID_T
> AC_TYPE_UID_T
>
> AC_STRUCT_ST_BLOCKS
> -AC_CHECK_MEMBERS([struct stat.st_blksize, struct stat.st_rdev])
> +AC_CHECK_MEMBERS([struct stat.st_blksize, struct stat.st_rdev, struct stat.st_mtim])
> gl_STAT_SIZE
>
> AH_TEMPLATE([sig_atomic_t],
> diff --git a/src/vfs/cpio/cpio.c b/src/vfs/cpio/cpio.c
> index dba1a07c3..ffe6267cf 100644
> --- a/src/vfs/cpio/cpio.c
> +++ b/src/vfs/cpio/cpio.c
> @@ -462,9 +462,15 @@ 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
>         }
>
>         g_free (name);
> @@ -589,6 +595,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 = (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
>     st.st_atime = st.st_mtime = st.st_ctime = (u.buf.c_mtimes[0] << 16) | u.buf.c_mtimes[1];
>
>     return cpio_create_entry (me, super, &st, name);
> @@ -658,6 +667,9 @@ 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
>     u.st.st_atime = u.st.st_mtime = u.st.st_ctime = hd.c_mtime;
>
>     return cpio_create_entry (me, super, &u.st, name);
> @@ -736,6 +748,9 @@ 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
>     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/tar/tar.c b/src/vfs/tar/tar.c
> index 3afd8d68d..4b674739d 100644
> --- a/src/vfs/tar/tar.c
> +++ b/src/vfs/tar/tar.c
> @@ -442,6 +442,9 @@ tar_fill_stat (struct vfs_s_super *archive, struct stat *st, union record *heade
>     }
>
>     st->st_size = h_size;
> +#ifdef HAVE_STRUCT_STAT_ST_MTIM
> +    st->st_atim.tv_nsec = st->st_mtim.tv_nsec = st->st_ctim.tv_nsec = 0;
> +#endif
>     st->st_mtime = tar_from_oct (1 + 12, header->header.mtime);
>     st->st_atime = 0;
>     st->st_ctime = 0;
> -- 
> 2.12.2+git20170411
> _______________________________________________
> mc-devel mailing list
> https://mail.gnome.org/mailman/listinfo/mc-devel
>

-- 
Sincerely yours,
Yury V. Zaytsev



More information about the mc-devel mailing list