X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/3b7bcaaf3477be6a50fde54e06b80c9a5e698bd9..1b42f628f495ff0cdaa8a7c219d8ce33192281fe:/flist.c diff --git a/flist.c b/flist.c index de5f2929..42518d9a 100644 --- a/flist.c +++ b/flist.c @@ -21,6 +21,7 @@ */ #include "rsync.h" +#include "ifuncs.h" #include "rounding.h" #include "io.h" @@ -75,6 +76,7 @@ extern struct filter_list_struct server_filter_list; #ifdef ICONV_OPTION extern int ic_ndx; +extern int filesfrom_convert; extern int need_unsorted_flist; extern iconv_t ic_send, ic_recv; #endif @@ -115,6 +117,7 @@ static char tmp_sum[MAX_DIGEST_LEN]; static char empty_sum[MAX_DIGEST_LEN]; static int flist_count_offset; /* for --delete --progress */ static int dir_count = 0; +static int high_hlink_ndx; static void clean_flist(struct file_list *flist, int strip_root); static void output_flist(struct file_list *flist); @@ -376,22 +379,21 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_ #ifdef ICONV_OPTION if (ic_send != (iconv_t)-1) { - ICONV_CONST char *ibuf; - char *obuf = fname; - size_t ocnt = MAXPATHLEN, icnt; - - iconv(ic_send, NULL,0, NULL,0); - if ((ibuf = (ICONV_CONST char *)file->dirname) != NULL) { - icnt = strlen(ibuf); - ocnt--; /* pre-subtract the space for the '/' */ - if (iconv(ic_send, &ibuf,&icnt, &obuf,&ocnt) == (size_t)-1) - goto convert_error; - *obuf++ = '/'; - } - - ibuf = (ICONV_CONST char *)file->basename; - icnt = strlen(ibuf); - if (iconv(ic_send, &ibuf,&icnt, &obuf,&ocnt) == (size_t)-1) { + xbuf outbuf, inbuf; + + INIT_CONST_XBUF(outbuf, fname); + + 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) + goto convert_error; + outbuf.size += 2; + outbuf.buf[outbuf.len++] = '/'; + } + + INIT_XBUF_STRLEN(inbuf, (char*)file->basename); + if (iconvbufs(ic_send, &inbuf, &outbuf, 0) < 0) { convert_error: io_error |= IOERR_GENERAL; rprintf(FINFO, @@ -399,7 +401,7 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_ who_am_i(), f_name(file, fname), strerror(errno)); return; } - *obuf = '\0'; + outbuf.buf[outbuf.len] = '\0'; } else #endif f_name(file, fname); @@ -467,7 +469,8 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_ struct ht_int64_node *np = idev_find(tmp_dev, tmp_ino); first_hlink_ndx = (int32)(long)np->data - 1; if (first_hlink_ndx < 0) { - np->data = (void*)(long)(ndx + first_ndx + 1); + high_hlink_ndx = ndx + first_ndx; + np->data = (void*)(long)(high_hlink_ndx + 1); xflags |= XMIT_HLINK_FIRST; } xflags |= XMIT_HLINKED; @@ -665,25 +668,19 @@ static struct file_struct *recv_file_entry(struct file_list *flist, #ifdef ICONV_OPTION if (ic_recv != (iconv_t)-1) { - char *obuf = thisname; - ICONV_CONST char *ibuf = (ICONV_CONST char *)lastname; - size_t ocnt = MAXPATHLEN, icnt = basename_len; + xbuf outbuf, inbuf; - if (icnt >= MAXPATHLEN) { - errno = E2BIG; - goto convert_error; - } + INIT_CONST_XBUF(outbuf, thisname); + INIT_XBUF(inbuf, lastname, basename_len, -1); - iconv(ic_recv, NULL,0, NULL,0); - if (iconv(ic_recv, &ibuf,&icnt, &obuf,&ocnt) == (size_t)-1) { - convert_error: + if (iconvbufs(ic_recv, &inbuf, &outbuf, 0) < 0) { io_error |= IOERR_GENERAL; rprintf(FINFO, "[%s] cannot convert filename: %s (%s)\n", who_am_i(), lastname, strerror(errno)); - obuf = thisname; + outbuf.len = 0; } - *obuf = '\0'; + outbuf.buf[outbuf.len] = '\0'; } #endif @@ -941,9 +938,11 @@ static struct file_struct *recv_file_entry(struct file_list *flist, #ifdef SUPPORT_HARD_LINKS if (preserve_hard_links && xflags & XMIT_HLINKED) { if (protocol_version >= 30) { - F_HL_GNUM(file) = xflags & XMIT_HLINK_FIRST - ? flist->ndx_start + flist->used - : first_hlink_ndx; + if (xflags & XMIT_HLINK_FIRST) { + high_hlink_ndx = flist->ndx_start + flist->used; + F_HL_GNUM(file) = high_hlink_ndx; + } else + F_HL_GNUM(file) = first_hlink_ndx; } else { static int32 cnt = 0; struct ht_int64_node *np; @@ -1551,6 +1550,7 @@ void send_extra_file_list(int f, int at_least) while (future_cnt < at_least) { struct file_struct *file = dir_flist->sorted[send_dir_ndx]; int dir_ndx, dstart = dir_count; + const char *pathname = F_PATHNAME(file); int32 *dp; flist = flist_new(0, "send_extra_file_list"); @@ -1575,7 +1575,8 @@ void send_extra_file_list(int f, int at_least) && dir_flist->sorted[dir_ndx]->flags & FLAG_DUPLICATE) { send_dir_ndx = dir_ndx; file = dir_flist->sorted[dir_ndx]; - send1extra(f, file, flist); + if (F_PATHNAME(file) != pathname) + send1extra(f, file, flist); dp = F_DIR_NODE_P(file); } @@ -1644,7 +1645,11 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) int use_ff_fd = 0; int flags, disable_buffering; int reading_remotely = filesfrom_host != NULL; - int rl_nulls = eol_nulls || reading_remotely; + int rl_flags = (reading_remotely ? 0 : RL_DUMP_COMMENTS) +#ifdef ICONV_OPTION + | (filesfrom_convert ? RL_CONVERT : 0) +#endif + | (eol_nulls || reading_remotely ? RL_EOL_NULLS : 0); rprintf(FLOG, "building file list\n"); if (show_filelist_p()) @@ -1685,7 +1690,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) int is_dot_dir; if (use_ff_fd) { - if (read_line(filesfrom_fd, fbuf, sizeof fbuf, !reading_remotely, rl_nulls) == 0) + if (read_line(filesfrom_fd, fbuf, sizeof fbuf, rl_flags) == 0) break; sanitize_path(fbuf, fbuf, "", 0, NULL); } else { @@ -2200,6 +2205,8 @@ struct file_list *flist_new(int flags, char *msg) flist->file_pool = first_flist->file_pool; flist->ndx_start = first_flist->prev->ndx_end + 2; + if (flist->ndx_start <= high_hlink_ndx) + flist->ndx_start = high_hlink_ndx + 1; flist->prev = first_flist->prev; flist->prev->next = first_flist->prev = flist; @@ -2298,19 +2305,20 @@ static void clean_flist(struct file_list *flist, int strip_root) int keep, drop; /* If one is a dir and the other is not, we want to * keep the dir because it might have contents in the - * list. */ + * list. Otherwise keep the first one. */ if (S_ISDIR(file->mode)) { struct file_struct *fp = flist->sorted[j]; - if (!S_ISDIR(fp->mode)) + if (!S_ISDIR(fp->mode) || !(fp->flags & FLAG_XFER_DIR)) keep = i, drop = j; - else + else { + if (am_sender) + file->flags |= FLAG_DUPLICATE; keep = j, drop = i; + } } else keep = j, drop = i; - if (am_sender) - flist->sorted[drop]->flags |= FLAG_DUPLICATE; - else { + if (!am_sender) { if (verbose > 1) { rprintf(FINFO, "removing duplicate name %s from file list (%d)\n",