X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/ce827c3e50cd168027a555ec961b6636e5b63e59..5692657757a6c0e3ba60320719ef51af6f78c909:/flist.c diff --git a/flist.c b/flist.c index 6eb02c7b..ac0a903f 100644 --- a/flist.c +++ b/flist.c @@ -42,7 +42,6 @@ extern int xfer_dirs; extern int filesfrom_fd; extern int one_file_system; extern int copy_dirlinks; -extern int keep_dirlinks; extern int preserve_uid; extern int preserve_gid; extern int preserve_acls; @@ -87,6 +86,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; @@ -196,7 +203,7 @@ static int readlink_stat(const char *path, STRUCT_STAT *stp, char *linkbuf) 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'; @@ -495,6 +502,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 +586,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)) { @@ -662,8 +673,7 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file, 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; @@ -685,6 +695,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; @@ -719,7 +730,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist, INIT_CONST_XBUF(outbuf, thisname); INIT_XBUF(inbuf, lastname, basename_len, (size_t)-1); - if (iconvbufs(ic_recv, &inbuf, &outbuf, 0) < 0) { + if (iconvbufs(ic_recv, &inbuf, &outbuf, ICB_INIT) < 0) { io_error |= IOERR_GENERAL; rprintf(FERROR_UTF8, "[%s] cannot convert filename: %s (%s)\n", @@ -768,6 +779,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 +813,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 +914,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 +954,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 +968,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 @@ -1022,7 +1048,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist, read_sbuf(f, inbuf.buf, inbuf.len); INIT_XBUF(outbuf, bp, 0, alloc_len); - if (iconvbufs(ic_recv, &inbuf, &outbuf, 0) < 0) { + if (iconvbufs(ic_recv, &inbuf, &outbuf, ICB_INIT) < 0) { io_error |= IOERR_GENERAL; rprintf(FERROR_XFER, "[%s] cannot convert symlink data for: %s (%s)\n", @@ -1088,11 +1114,11 @@ static struct file_struct *recv_file_entry(struct file_list *flist, #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)) @@ -1272,6 +1298,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 +1356,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; @@ -1427,14 +1463,14 @@ static struct file_struct *send_file_name(int f, struct file_list *flist, if (file->dirname) { INIT_XBUF_STRLEN(inbuf, (char*)file->dirname); outbuf.size -= 2; /* Reserve room for '/' & 1 more char. */ - if (iconvbufs(ic_send, &inbuf, &outbuf, 0) < 0) + if (iconvbufs(ic_send, &inbuf, &outbuf, ICB_INIT) < 0) goto convert_error; outbuf.size += 2; fbuf[outbuf.len++] = '/'; } INIT_XBUF_STRLEN(inbuf, (char*)file->basename); - if (iconvbufs(ic_send, &inbuf, &outbuf, 0) < 0) { + if (iconvbufs(ic_send, &inbuf, &outbuf, ICB_INIT) < 0) { convert_error: io_error |= IOERR_GENERAL; rprintf(FERROR_XFER, @@ -1448,7 +1484,7 @@ static struct file_struct *send_file_name(int f, struct file_list *flist, if (symlink_len && sender_symlink_iconv) { INIT_XBUF(inbuf, (char*)symlink_name, symlink_len, (size_t)-1); INIT_CONST_XBUF(outbuf, symlink_buf); - if (iconvbufs(ic_send, &inbuf, &outbuf, 0) < 0) { + if (iconvbufs(ic_send, &inbuf, &outbuf, ICB_INIT) < 0) { io_error |= IOERR_GENERAL; f_name(file, fbuf); rprintf(FERROR_XFER, @@ -1493,13 +1529,13 @@ static struct file_struct *send_file_name(int f, struct file_list *flist, #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 @@ -1985,6 +2021,8 @@ void send_extra_file_list(int f, int at_least) if ((send_dir_ndx = DIR_PARENT(dp)) < 0) { write_ndx(f, NDX_FLIST_EOF); flist_eof = 1; + if (DEBUG_GTE(FLIST, 3)) + rprintf(FINFO, "[%s] flist_eof=1\n", who_am_i()); change_local_filter_dir(NULL, 0, 0); goto finish; } @@ -2012,7 +2050,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) struct timeval start_tv, end_tv; int64 start_write; int use_ff_fd = 0; - int disable_buffering; + int disable_buffering, reenable_multiplex = -1; int flags = recurse ? FLAG_CONTENT_DIR : 0; int reading_remotely = filesfrom_host != NULL; int rl_flags = (reading_remotely ? 0 : RL_DUMP_COMMENTS) @@ -2053,6 +2091,12 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) full_fname(argv[0])); exit_cleanup(RERR_FILESELECT); } + if (protocol_version < 31) { + /* Older protocols send the files-from data w/o packaging + * it in multiplexed I/O packets, so temporarily switch + * to buffered I/O to match this behavior. */ + reenable_multiplex = io_end_multiplex_in(MPLX_TO_BUFFERED); + } use_ff_fd = 1; } @@ -2258,6 +2302,9 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) send_file_name(f, flist, fbuf, &st, flags, NO_FILTERS); } + if (reenable_multiplex >= 0) + io_start_multiplex_in(reenable_multiplex); + gettimeofday(&end_tv, NULL); stats.flist_buildtime = (int64)(end_tv.tv_sec - start_tv.tv_sec) * 1000 + (end_tv.tv_usec - start_tv.tv_usec) / 1000; @@ -2302,12 +2349,11 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) flist->sorted = flist->files; flist_sort_and_clean(flist, 0); file_total += flist->used; + file_old_total += flist->used; if (numeric_ids <= 0 && !inc_recurse) send_id_list(f); - set_msg_fd_in(-1); - /* send the io_error flag */ if (protocol_version < 30) write_int(f, ignore_errors ? 0 : io_error); @@ -2315,7 +2361,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) send_msg_int(MSG_IO_ERROR, io_error); if (disable_buffering) - io_end_buffering_out(); + io_end_buffering_out(IOBUF_FREE_BUFS); stats.flist_size = stats.total_written - start_write; stats.num_files = flist->used; @@ -2335,6 +2381,8 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) if (send_dir_ndx < 0) { write_ndx(f, NDX_FLIST_EOF); flist_eof = 1; + if (DEBUG_GTE(FLIST, 3)) + rprintf(FINFO, "[%s] flist_eof=1\n", who_am_i()); } else if (file_total == 1) { /* If we're creating incremental file-lists and there @@ -2342,8 +2390,11 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) * file-list to check if this is a 1-file xfer. */ send_extra_file_list(f, 1); } - } else + } else { flist_eof = 1; + if (DEBUG_GTE(FLIST, 3)) + rprintf(FINFO, "[%s] flist_eof=1\n", who_am_i()); + } return flist; } @@ -2403,7 +2454,7 @@ struct file_list *recv_file_list(int f) } 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 */ @@ -2472,6 +2523,8 @@ struct file_list *recv_file_list(int f) else if (f >= 0) { recv_id_list(f, flist); flist_eof = 1; + if (DEBUG_GTE(FLIST, 3)) + rprintf(FINFO, "[%s] flist_eof=1\n", who_am_i()); } flist_sort_and_clean(flist, relative_paths); @@ -2506,6 +2559,8 @@ void recv_additional_file_list(int f) int ndx = read_ndx(f); if (ndx == NDX_FLIST_EOF) { flist_eof = 1; + if (DEBUG_GTE(FLIST, 3)) + rprintf(FINFO, "[%s] flist_eof=1\n", who_am_i()); change_local_filter_dir(NULL, 0, 0); } else { ndx = NDX_FLIST_OFFSET - ndx;