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;
int send_dir_ndx = -1, send_dir_depth = -1;
int flist_cnt = 0; /* how many (non-tmp) file list objects exist */
int file_total = 0; /* total of all active items over all file-lists */
+int file_old_total = 0; /* total of active items that will soon be gone */
int flist_eof = 0; /* all the file-lists are now known */
#define NORMAL_NAME 0
if (link_stat(path, stp, copy_dirlinks) < 0)
return -1;
if (S_ISLNK(stp->st_mode)) {
- int llen = readlink(path, linkbuf, MAXPATHLEN - 1);
+ int llen = do_readlink(path, linkbuf, MAXPATHLEN - 1);
if (llen < 0)
return -1;
linkbuf[llen] = '\0';
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) {
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)) {
stats.total_size += F_LENGTH(file);
}
-static struct file_struct *recv_file_entry(struct file_list *flist,
- int xflags, int f)
+static struct file_struct *recv_file_entry(int f, struct file_list *flist, int xflags)
{
static int64 modtime;
static mode_t mode;
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;
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);
} 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));
#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");
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)) {
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
#ifdef SUPPORT_ACLS
if (preserve_acls && !S_ISLNK(mode))
- receive_acl(file, f);
+ receive_acl(f, file);
#endif
#ifdef SUPPORT_XATTRS
if (preserve_xattrs)
- receive_xattr(file, f );
+ receive_xattr(f, file);
#endif
if (S_ISREG(mode) || S_ISLNK(mode))
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;
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;
#endif
#ifdef SUPPORT_XATTRS
if (preserve_xattrs) {
+ sx.st.st_mode = file->mode;
if (get_xattr(fname, &sx) < 0) {
io_error |= IOERR_GENERAL;
return NULL;
#ifdef SUPPORT_ACLS
if (preserve_acls && !S_ISLNK(file->mode)) {
- send_acl(&sx, f);
+ send_acl(f, &sx);
free_acl(&sx);
}
#endif
#ifdef SUPPORT_XATTRS
if (preserve_xattrs) {
- F_XATTR(file) = send_xattr(&sx, f);
+ F_XATTR(file) = send_xattr(f, &sx);
free_xattr(&sx);
}
#endif
struct file_list *flist;
int64 start_write;
uint16 prev_flags;
- int old_cnt, save_io_error = io_error;
+ int save_io_error = io_error;
if (flist_eof)
return;
+ if (at_least < 0)
+ at_least = file_total - file_old_total + 1;
+
/* Keep sending data until we have the requested number of
* files in the upcoming file-lists. */
- old_cnt = cur_flist->used;
- for (flist = first_flist; flist != cur_flist; flist = flist->next)
- old_cnt += flist->used;
- while (file_total - old_cnt < at_least) {
+ while (file_total - file_old_total < at_least) {
struct file_struct *file = dir_flist->sorted[send_dir_ndx];
int dir_ndx, dstart = stats.num_dirs;
const char *pathname = F_PATHNAME(file);
}
flist_expand(flist, 1);
- file = recv_file_entry(flist, flags, f);
+ file = recv_file_entry(f, flist, flags);
if (S_ISREG(file->mode)) {
/* Already counted */