X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/3ab56a20eef93b07da6229dbb7277d82a26d8009..dc3afaf6aa699c4b8a1318a48bc65b27e2eddb82:/receiver.c diff --git a/receiver.c b/receiver.c index 80e645a0..dc6f5e21 100644 --- a/receiver.c +++ b/receiver.c @@ -48,8 +48,9 @@ extern int orig_umask; extern int keep_partial; extern int checksum_seed; extern int inplace; +extern int delay_updates; -extern struct exclude_list_struct server_exclude_list; +extern struct filter_list_struct server_filter_list; /* This deletes any files on the receiving side that are not present on the @@ -222,7 +223,7 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r, if (flush_write_file(fd) < 0) goto report_write_error; -#ifdef HAVE_FTRUNCATE +#if HAVE_FTRUNCATE if (inplace && fd != -1) ftruncate(fd, offset); #endif @@ -272,6 +273,7 @@ int recv_files(int f_in, struct file_list *flist, char *local_name, char fnametmp[MAXPATHLEN]; char *fnamecmp, *partialptr; char fnamecmpbuf[MAXPATHLEN]; + uchar *delayed_bits = NULL; struct file_struct *file; struct stats initial_stats; int save_make_backups = make_backups; @@ -285,6 +287,13 @@ int recv_files(int f_in, struct file_list *flist, char *local_name, flist->hlink_pool = NULL; } + if (delay_updates) { + int sz = (flist->count + 7) / 8; + if (!(delayed_bits = new_array(uchar, sz))) + out_of_memory("recv_files"); + memset(delayed_bits, 0, sz); + } + while (1) { cleanup_disable(); @@ -360,8 +369,8 @@ int recv_files(int f_in, struct file_list *flist, char *local_name, next_gen_i = -1; } - if (server_exclude_list.head - && check_exclude(&server_exclude_list, fname, + if (server_filter_list.head + && check_filter(&server_filter_list, fname, S_ISDIR(file->mode)) < 0) { rprintf(FERROR, "attempt to hack rsync failed.\n"); exit_cleanup(RERR_PROTOCOL); @@ -499,7 +508,7 @@ int recv_files(int f_in, struct file_list *flist, char *local_name, exit_cleanup(RERR_FILEIO); } - if (recv_ok || inplace) { + if ((recv_ok && !delay_updates) || inplace) { finish_transfer(fname, fnametmp, file, recv_ok, 1); if (partialptr != fname && fnamecmp == partialptr) { do_unlink(partialptr); @@ -509,6 +518,8 @@ int recv_files(int f_in, struct file_list *flist, char *local_name, && handle_partial_dir(partialptr, PDIR_CREATE)) { finish_transfer(partialptr, fnametmp, file, recv_ok, !partial_dir); + if (delay_updates && recv_ok) + delayed_bits[i/8] |= 1 << (i % 8); } else { partialptr = NULL; do_unlink(fnametmp); @@ -548,6 +559,33 @@ int recv_files(int f_in, struct file_list *flist, char *local_name, } make_backups = save_make_backups; + if (delay_updates) { + for (i = 0; i < flist->count; i++) { + struct file_struct *file = flist->files[i]; + if (!file->basename + || !(delayed_bits[i/8] & (1 << (i % 8)))) + continue; + fname = local_name ? local_name : f_name(file); + partialptr = partial_dir_fname(fname); + if (partialptr) { + if (make_backups && !make_backup(fname)) + continue; + if (verbose > 2) { + rprintf(FINFO, "renaming %s to %s\n", + partialptr, fname); + } + if (do_rename(partialptr, fname) < 0) { + rsyserr(FERROR, errno, + "rename failed for %s (from %s)", + fname, partialptr); + } else { + handle_partial_dir(partialptr, + PDIR_DELETE); + } + } + } + } + if (delete_after && recurse && !local_name && flist->count > 0) delete_files(flist);