Add support for transferring & setting nsec time values.
[rsync/rsync.git] / flist.c
diff --git a/flist.c b/flist.c
index 8b08ff6..7a28b73 100644 (file)
--- a/flist.c
+++ b/flist.c
@@ -87,6 +87,14 @@ extern int filesfrom_convert;
 extern iconv_t ic_send, ic_recv;
 #endif
 
+#ifdef HAVE_UTIMENSAT
+#ifdef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
+#define ST_MTIME_NSEC st_mtim.tv_nsec
+#elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
+#define ST_MTIME_NSEC st_mtimensec
+#endif
+#endif
+
 #define PTR_SIZE (sizeof (struct file_struct *))
 
 int io_error;
@@ -495,6 +503,8 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
                xflags |= XMIT_SAME_TIME;
        else
                modtime = file->modtime;
+       if (NSEC_BUMP(file) && protocol_version >= 31)
+               xflags |= XMIT_MOD_NSEC;
 
 #ifdef SUPPORT_HARD_LINKS
        if (tmp_dev != 0) {
@@ -577,6 +587,8 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
                else
                        write_int(f, modtime);
        }
+       if (xflags & XMIT_MOD_NSEC)
+               write_varint(f, F_MOD_NSEC(file));
        if (!(xflags & XMIT_SAME_MODE))
                write_int(f, to_wire_mode(mode));
        if (preserve_uid && !(xflags & XMIT_SAME_UID)) {
@@ -685,6 +697,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
        int extra_len = file_extra_cnt * EXTRA_LEN;
        int first_hlink_ndx = -1;
        int64 file_length;
+       uint32 modtime_nsec;
        const char *basename;
        struct file_struct *file;
        alloc_pool_t *pool;
@@ -768,6 +781,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
                        struct file_struct *first = flist->files[first_hlink_ndx - flist->ndx_start];
                        file_length = F_LENGTH(first);
                        modtime = first->modtime;
+                       modtime_nsec = F_MOD_NSEC(first);
                        mode = first->mode;
                        if (preserve_uid)
                                uid = F_OWNER(first);
@@ -801,6 +815,10 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
                } else
                        modtime = read_int(f);
        }
+       if (xflags & XMIT_MOD_NSEC)
+               modtime_nsec = read_varint(f);
+       else
+               modtime_nsec = 0;
        if (!(xflags & XMIT_SAME_MODE))
                mode = from_wire_mode(read_int(f));
 
@@ -898,6 +916,10 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
 #if SIZEOF_INT64 >= 8
        if (file_length > 0xFFFFFFFFu && S_ISREG(mode))
                extra_len += EXTRA_LEN;
+#endif
+#ifdef HAVE_UTIMENSAT
+       if (modtime_nsec)
+               extra_len += EXTRA_LEN;
 #endif
        if (file_length < 0) {
                rprintf(FERROR, "Offset underflow: file-length is negative\n");
@@ -934,6 +956,12 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
                file->flags |= FLAG_HLINKED;
 #endif
        file->modtime = (time_t)modtime;
+#ifdef HAVE_UTIMENSAT
+       if (modtime_nsec) {
+               file->flags |= FLAG_MOD_NSEC;
+               OPT_EXTRA(file, 0)->unum = modtime_nsec;
+       }
+#endif
        file->len32 = (uint32)file_length;
 #if SIZEOF_INT64 >= 8
        if (file_length > 0xFFFFFFFFu && S_ISREG(mode)) {
@@ -942,7 +970,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
                exit_cleanup(RERR_UNSUPPORTED);
 #else
                file->flags |= FLAG_LENGTH64;
-               OPT_EXTRA(file, 0)->unum = (uint32)(file_length >> 32);
+               OPT_EXTRA(file, NSEC_BUMP(file))->unum = (uint32)(file_length >> 32);
 #endif
        }
 #endif
@@ -1272,6 +1300,10 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
        linkname_len = 0;
 #endif
 
+#ifdef ST_MTIME_NSEC
+       if (st.ST_MTIME_NSEC && protocol_version >= 31)
+               extra_len += EXTRA_LEN;
+#endif
 #if SIZEOF_CAPITAL_OFF_T >= 8
        if (st.st_size > 0xFFFFFFFFu && S_ISREG(st.st_mode))
                extra_len += EXTRA_LEN;
@@ -1326,11 +1358,17 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
 
        file->flags = flags;
        file->modtime = st.st_mtime;
+#ifdef ST_MTIME_NSEC
+       if (st.ST_MTIME_NSEC && protocol_version >= 31) {
+               file->flags |= FLAG_MOD_NSEC;
+               OPT_EXTRA(file, 0)->unum = st.ST_MTIME_NSEC;
+       }
+#endif
        file->len32 = (uint32)st.st_size;
 #if SIZEOF_CAPITAL_OFF_T >= 8
        if (st.st_size > 0xFFFFFFFFu && S_ISREG(st.st_mode)) {
                file->flags |= FLAG_LENGTH64;
-               OPT_EXTRA(file, 0)->unum = (uint32)(st.st_size >> 32);
+               OPT_EXTRA(file, NSEC_BUMP(file))->unum = (uint32)(st.st_size >> 32);
        }
 #endif
        file->mode = st.st_mode;