X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/9585b27678ee8b94f2f260e8d8d61ff4381f2fa3..62a6b8df72d18f0b13462ee7ac33f9a8a46ef0b5:/flist.c diff --git a/flist.c b/flist.c index 72dded84..960e6a11 100644 --- a/flist.c +++ b/flist.c @@ -121,9 +121,8 @@ 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 flist_sort_and_clean(struct file_list *flist, int strip_root); static void output_flist(struct file_list *flist); void init_flist(void) @@ -352,7 +351,7 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_ static uint32 rdev_major; static uid_t uid; static gid_t gid; - static char *user_name, *group_name; + static const char *user_name, *group_name; static char lastname[MAXPATHLEN]; char fname[MAXPATHLEN]; int first_hlink_ndx = -1; @@ -390,6 +389,7 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_ /* Initialize starting value of xflags. */ if (protocol_version >= 30 && S_ISDIR(file->mode)) { + dir_count++; if (file->flags & FLAG_CONTENT_DIR) xflags = file->flags & FLAG_TOP_DIR; else if (file->flags & FLAG_IMPLIED_DIR) @@ -457,8 +457,7 @@ 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) { - high_hlink_ndx = ndx + first_ndx; - np->data = (void*)(long)(high_hlink_ndx + 1); + np->data = (void*)(long)(first_ndx + ndx + 1); xflags |= XMIT_HLINK_FIRST; } xflags |= XMIT_HLINKED; @@ -731,7 +730,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist, if (protocol_version >= 30) { modtime = read_varlong(f, 4); #if SIZEOF_TIME_T < SIZEOF_INT64 - if ((modtime > INT_MAX || modtime < INT_MIN) && !am_generator) { + if (!am_generator && (int64)(time_t)modtime != modtime) { rprintf(FERROR_XFER, "Time value of %s truncated on receiver.\n", lastname); @@ -829,11 +828,6 @@ static struct file_struct *recv_file_entry(struct file_list *flist, if (file_length > 0xFFFFFFFFu && S_ISREG(mode)) extra_len += EXTRA_LEN; -#if EXTRA_ROUNDING > 0 - if (extra_len & (EXTRA_ROUNDING * EXTRA_LEN)) - extra_len = (extra_len | (EXTRA_ROUNDING * EXTRA_LEN)) + EXTRA_LEN; -#endif - if (inc_recurse && S_ISDIR(mode)) { if (one_file_system) { /* Room to save the dir's device for -x */ @@ -843,6 +837,11 @@ static struct file_struct *recv_file_entry(struct file_list *flist, } else pool = flist->file_pool; +#if EXTRA_ROUNDING > 0 + if (extra_len & (EXTRA_ROUNDING * EXTRA_LEN)) + extra_len = (extra_len | (EXTRA_ROUNDING * EXTRA_LEN)) + EXTRA_LEN; +#endif + alloc_len = FILE_STRUCT_LEN + extra_len + basename_len + linkname_len; bp = pool_alloc(pool, alloc_len, "recv_file_entry"); @@ -927,8 +926,11 @@ static struct file_struct *recv_file_entry(struct file_list *flist, bp += SYMLINK_PREFIX_LEN; linkname_len -= SYMLINK_PREFIX_LEN; read_sbuf(f, bp, linkname_len - 1); - } else + } else { read_sbuf(f, bp, linkname_len - 1); + if (sanitize_paths) + sanitize_path(bp, bp, "", lastdir_depth); + } } #endif @@ -936,8 +938,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist, if (preserve_hard_links && xflags & XMIT_HLINKED) { if (protocol_version >= 30) { if (xflags & XMIT_HLINK_FIRST) { - high_hlink_ndx = flist->ndx_start + flist->used; - F_HL_GNUM(file) = high_hlink_ndx; + F_HL_GNUM(file) = flist->ndx_start + flist->used; } else F_HL_GNUM(file) = first_hlink_ndx; } else { @@ -1111,7 +1112,6 @@ struct file_struct *make_file(const char *fname, struct file_list *flist, extra_len += DIRNODE_EXTRA_CNT * EXTRA_LEN; if (relative_paths) extra_len += PTR_EXTRA_CNT * EXTRA_LEN; - dir_count++; pool = dir_flist->file_pool; } else pool = flist->file_pool; @@ -1232,11 +1232,14 @@ struct file_struct *make_file(const char *fname, struct file_list *flist, file->mode = save_mode; } - if (basename_len == 0+1) + if (basename_len == 0+1) { + if (!pool) + unmake_file(file); return NULL; + } if (unsort_ndx) - F_NDX(file) = dir_count - 1; + F_NDX(file) = dir_count; return file; } @@ -1716,11 +1719,7 @@ void send_extra_file_list(int f, int at_least) } else flist->sorted = flist->files; - clean_flist(flist, 0); - - flist->ndx_end = flist->ndx_start + flist->used - 1; - if (!need_unsorted_flist) - flist->ndx_end -= (dir_count - dstart); + flist_sort_and_clean(flist, 0); add_dirs_to_tree(send_dir_ndx, flist, dir_count - dstart); flist_done_allocating(flist); @@ -1975,7 +1974,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) file = send_file_name(f, flist, fbuf, &st, top_flags, ALL_FILTERS); if (inc_recurse) { - if (name_type == DOT_NAME) { + if (name_type == DOT_NAME && file) { if (send_dir_depth < 0) { send_dir_depth = 0; change_local_filter_dir(fbuf, len, send_dir_depth); @@ -2018,27 +2017,15 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) * recursion mode, the sender marks duplicate dirs so that it can * send them together in a single file-list. */ if (need_unsorted_flist) { - if (inc_recurse) { - if (!(flist->sorted = new_array(struct file_struct *, flist->used))) - out_of_memory("send_file_list"); - memcpy(flist->sorted, flist->files, - flist->used * sizeof (struct file_struct*)); - clean_flist(flist, 0); - } else { - flist->sorted = flist->files; - flist->low = 0; - flist->high = flist->used - 1; - } - } else { + if (!(flist->sorted = new_array(struct file_struct *, flist->used))) + out_of_memory("send_file_list"); + memcpy(flist->sorted, flist->files, + flist->used * sizeof (struct file_struct*)); + } else flist->sorted = flist->files; - clean_flist(flist, 0); - } + flist_sort_and_clean(flist, 0); file_total += flist->used; - /* We don't subtract dir_count for the first send since we - * might have one or more dot dirs which need to get sent. */ - flist->ndx_end = flist->ndx_start + flist->used - 1; - if (!numeric_ids && !inc_recurse) send_id_list(f); @@ -2137,10 +2124,6 @@ struct file_list *recv_file_list(int f) } file_total += flist->used; - flist->ndx_end = flist->ndx_start + flist->used - 1; - if (inc_recurse && !need_unsorted_flist && flist->ndx_start > 1) - flist->ndx_end -= dir_flist->used - dstart; - if (verbose > 2) rprintf(FINFO, "received %d names\n", flist->used); @@ -2158,9 +2141,13 @@ struct file_list *recv_file_list(int f) memcpy(flist->sorted, flist->files, flist->used * sizeof (struct file_struct*)); if (inc_recurse && dir_flist->used > dstart) { - dir_flist->sorted = realloc_array(dir_flist->sorted, - struct file_struct *, - dir_flist->used); + static int dir_flist_malloced = 0; + if (dir_flist_malloced < dir_flist->malloced) { + dir_flist->sorted = realloc_array(dir_flist->sorted, + struct file_struct *, + dir_flist->malloced); + dir_flist_malloced = dir_flist->malloced; + } memcpy(dir_flist->sorted + dstart, dir_flist->files + dstart, (dir_flist->used - dstart) * sizeof (struct file_struct*)); fsort(dir_flist->sorted + dstart, dir_flist->used - dstart); @@ -2178,7 +2165,7 @@ struct file_list *recv_file_list(int f) else if (f >= 0) recv_id_list(f, flist); - clean_flist(flist, relative_paths); + flist_sort_and_clean(flist, relative_paths); if (protocol_version < 30) { /* Recv the io_error flag */ @@ -2318,18 +2305,19 @@ struct file_list *flist_new(int flags, char *msg) if (!flist->file_pool) out_of_memory(msg); - flist->ndx_start = inc_recurse ? 1 : 0; + flist->ndx_start = flist->flist_num = inc_recurse ? 1 : 0; first_flist = cur_flist = flist->prev = flist; } else { + struct file_list *prev = first_flist->prev; + 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->ndx_start = prev->ndx_start + prev->used + 1; + flist->flist_num = prev->flist_num + 1; - flist->prev = first_flist->prev; - flist->prev->next = first_flist->prev = flist; + flist->prev = prev; + prev->next = first_flist->prev = flist; } flist->pool_boundary = pool_boundary(flist->file_pool, 0); flist_cnt++; @@ -2375,7 +2363,7 @@ void flist_free(struct file_list *flist) /* This routine ensures we don't have any duplicate names in our file list. * duplicate names can cause corruption because of the pipelining. */ -static void clean_flist(struct file_list *flist, int strip_root) +static void flist_sort_and_clean(struct file_list *flist, int strip_root) { char fbuf[MAXPATHLEN]; int i, prev_i; @@ -2555,8 +2543,8 @@ static void output_flist(struct file_list *flist) const char *who = who_am_i(); int i; - rprintf(FINFO, "[%s] flist start=%d, end=%d, used=%d, low=%d, high=%d\n", - who, flist->ndx_start, flist->ndx_end, flist->used, flist->low, flist->high); + rprintf(FINFO, "[%s] flist start=%d, used=%d, low=%d, high=%d\n", + who, flist->ndx_start, flist->used, flist->low, flist->high); for (i = 0; i < flist->used; i++) { file = flist->files[i]; if ((am_root || am_sender) && uid_ndx) { @@ -2806,7 +2794,7 @@ struct file_list *get_dirlist(char *dirname, int dlen, int ignore_filter_rules) prune_empty_dirs = 0; dirlist->sorted = dirlist->files; - clean_flist(dirlist, 0); + flist_sort_and_clean(dirlist, 0); prune_empty_dirs = save_prune_empty_dirs; if (verbose > 3)