Skip to content

Instantly share code, notes, and snippets.

Created April 9, 2017 08:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/1eb789c825a8eaa1bdb4116334ba52da to your computer and use it in GitHub Desktop.
Save anonymous/1eb789c825a8eaa1bdb4116334ba52da to your computer and use it in GitHub Desktop.
a proposed patch for rsync v. 3.1.1 to fix faulty nanosecond mtimes -- ignoring 1 second overflow in .st_mtim.tv_nsec as well
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)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment