X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/85909931857090541511e7ab9a085225e0db0407..6b2a3d5de667e4abf938c453121340ad47ccc5c0:/receiver.c diff --git a/receiver.c b/receiver.c index 07fe3f4d..b9931b8f 100644 --- a/receiver.c +++ b/receiver.c @@ -39,8 +39,9 @@ extern int preserve_hard_links; extern int preserve_perms; extern int basis_dir_cnt; extern int make_backups; +extern int flist_extra_ndx; extern int cleanup_got_literal; -extern int remove_sent_files; +extern int remove_source_files; extern int append_mode; extern int sparse_files; extern int keep_partial; @@ -57,6 +58,8 @@ extern struct filter_list_struct server_filter_list; static struct bitbag *delayed_bits = NULL; static int phase = 0; +/* We're either updating the basis file or an identical copy: */ +static int updating_basis; /* @@ -80,17 +83,15 @@ static int phase = 0; * As long as it's unique, rsync will work. */ -static int get_tmpname(char *fnametmp, char *fname) +int get_tmpname(char *fnametmp, char *fname) { + int maxname, added, length = 0; char *f; - int length = 0; - int maxname; if (tmpdir) { /* Note: this can't overflow, so the return value is safe */ length = strlcpy(fnametmp, tmpdir, MAXPATHLEN - 2); fnametmp[length++] = '/'; - fnametmp[length] = '\0'; /* always NULL terminated */ } if ((f = strrchr(fname, '/')) != NULL) { @@ -103,8 +104,9 @@ static int get_tmpname(char *fnametmp, char *fname) } else f = fname; fnametmp[length++] = '.'; - fnametmp[length] = '\0'; /* always NULL terminated */ + /* The maxname value is bufsize, and includes space for the '\0'. + * (Note that NAME_MAX get -8 for the leading '.' above.) */ maxname = MIN(MAXPATHLEN - 7 - length, NAME_MAX - 8); if (maxname < 1) { @@ -113,8 +115,10 @@ static int get_tmpname(char *fnametmp, char *fname) return 0; } - strlcpy(fnametmp + length, f, maxname); - strcat(fnametmp + length, ".XXXXXX"); + added = strlcpy(fnametmp + length, f, maxname); + if (added >= maxname) + added = maxname - 1; + memcpy(fnametmp + length + added, ".XXXXXX", 8); return 1; } @@ -161,7 +165,7 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r, offset = j; } if (offset < sum.flength) { - int32 len = sum.flength - offset; + int32 len = (int32)(sum.flength - offset); if (do_progress) show_progress(offset, total_size); sum_update(map_ptr(mapbuf, offset, len), len); @@ -216,7 +220,7 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r, sum_update(map, len); } - if (inplace) { + if (updating_basis) { if (offset == offset2 && fd != -1) { OFF_T pos; if (flush_write_file(fd) < 0) @@ -296,9 +300,8 @@ static void handle_delayed_updates(struct file_list *flist, char *local_name) "rename failed for %s (from %s)", full_fname(fname), partialptr); } else { - if (remove_sent_files - || (preserve_hard_links - && file->link_u.links)) { + if (remove_source_files + || (preserve_hard_links && IS_HLINKED(file))) { SIVAL(numbuf, 0, i); send_msg(MSG_SUCCESS,numbuf,4); } @@ -360,11 +363,13 @@ int recv_files(int f_in, struct file_list *flist, char *local_name) if (delay_updates) delayed_bits = bitbag_create(flist->count); + updating_basis = inplace; + while (1) { cleanup_disable(); i = read_int(f_in); - if (i == -1) { + if (i == NDX_DONE) { if (read_batch) { get_next_gen_i(batch_gen_fd, next_gen_i, flist->count); @@ -459,6 +464,7 @@ int recv_files(int f_in, struct file_list *flist, char *local_name) fnamecmp = get_backup_name(fname); break; case FNAMECMP_FUZZY: + updating_basis = 0; if (file->dirname) { pathjoin(fnamecmpbuf, MAXPATHLEN, file->dirname, xname); @@ -467,6 +473,7 @@ int recv_files(int f_in, struct file_list *flist, char *local_name) fnamecmp = xname; break; default: + updating_basis = 0; if (fnamecmp_type >= basis_dir_cnt) { rprintf(FERROR, "invalid basis_dir index: %d.\n", @@ -513,7 +520,10 @@ int recv_files(int f_in, struct file_list *flist, char *local_name) } } - if (fd1 != -1 && do_fstat(fd1,&st) != 0) { + if (fd1 == -1) { + st.st_mode = 0; + st.st_size = 0; + } else if (do_fstat(fd1,&st) != 0) { rsyserr(FERROR, errno, "fstat %s failed", full_fname(fnamecmp)); discard_receive_data(f_in, file->length); @@ -546,7 +556,7 @@ int recv_files(int f_in, struct file_list *flist, char *local_name) file->mode = dest_mode(file->mode, st.st_mode, exists); } - /* We now check to see if we are writing file "inplace" */ + /* We now check to see if we are writing the file "inplace" */ if (inplace) { fd2 = do_open(fname, O_WRONLY|O_CREAT, 0600); if (fd2 == -1) { @@ -644,13 +654,13 @@ int recv_files(int f_in, struct file_list *flist, char *local_name) cleanup_disable(); if (recv_ok > 0) { - if (remove_sent_files - || (preserve_hard_links && file->link_u.links)) { + if (remove_source_files + || (preserve_hard_links && IS_HLINKED(file))) { SIVAL(numbuf, 0, i); send_msg(MSG_SUCCESS, numbuf, 4); } } else if (!recv_ok) { - int msgtype = phase || read_batch ? FERROR : FINFO; + enum logcode msgtype = phase || read_batch ? FERROR : FINFO; if (msgtype == FERROR || verbose) { char *errstr, *redostr, *keptstr; if (!(keep_partial && partialptr) && !inplace)