diff -r 27d7a363f071 rsync.c --- a/rsync.c Sat Apr 08 21:05:18 2017 +1000 +++ b/rsync.c Sat Apr 08 23:04:43 2017 +1000 @@ -549,7 +549,29 @@ flags |= ATTRS_SKIP_MTIME; if (!(flags & ATTRS_SKIP_MTIME) && cmp_time(sxp->st.st_mtime, file->modtime) != 0) { - int ret = set_modtime(fname, file->modtime, F_MOD_NSEC(file), sxp->st.st_mode); + + /* tv_nsec is a long type */ + long ns = F_MOD_NSEC(file) ; + /* check and complain */ + if ( ns < 0 ) { + rprintf(FWARNING, "warning: negative ns mtime (%ld) on %s\n", + ns, full_fname(fname)); + } else if ( ns >= NSEC_MAX ) { + rprintf(FWARNING, "warning: ns mtime >= 1 sec (%ld) on %s\n", + ns, full_fname(fname)); + } + /* Ok, now let's fix it */ + if ( NSEC_UNEXPECTED(ns) ) { + if (DEBUG_GTE(TIME, 1)) { + rprintf(FINFO, "! changing nsec time (%ld) to 0 on %s\n", + ns, full_fname(fname)); + } + + /* for negative values, that would also avoid implicit conversions */ + ns = 0 ; + } + + int ret = set_modtime(fname, file->modtime, ns, sxp->st.st_mode); if (ret < 0) { rsyserr(FERROR_XFER, errno, "failed to set times on %s", full_fname(fname)); diff -r 27d7a363f071 rsync.h --- a/rsync.h Sat Apr 08 21:05:18 2017 +1000 +++ b/rsync.h Sat Apr 08 23:04:43 2017 +1000 @@ -737,6 +737,11 @@ #endif #define F_MOD_NSEC(f) ((f)->flags & FLAG_MOD_NSEC ? OPT_EXTRA(f, 0)->unum : 0) +/* since we use unsigned ns, and since they are not supposed to be negative: */ +#define ZERO_IF_NEG(ns) ( ((ns) < 0) ? 0 : (ns) ) +/* ns tail is expected to be < 10^9 */ +#define NSEC_MAX 1000000000 /* nb: fits in int32 */ +#define NSEC_UNEXPECTED(ns) ( ((ns) < 0) || (ns) >= NSEC_MAX ) /* If there is a symlink string, it is always right after the basename */ #define F_SYMLINK(f) ((f)->basename + strlen((f)->basename) + 1)