#include "rsync.h"
extern int verbose;
-extern int recurse;
extern int delete_after;
-extern int max_delete;
extern int csum_length;
extern struct stats stats;
extern int dry_run;
extern int keep_dirlinks;
extern int preserve_hard_links;
extern int preserve_perms;
-extern int cvs_exclude;
extern int io_error;
extern char *tmpdir;
extern char *partial_dir;
extern char *basis_dir[];
+extern int basis_dir_cnt;
extern int make_backups;
extern int do_progress;
-extern char *backup_dir;
-extern char *backup_suffix;
-extern int backup_suffix_len;
extern int cleanup_got_literal;
extern int module_id;
extern int ignore_errors;
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;
-static void delete_one(char *fn, int is_dir)
-{
- if (!is_dir) {
- if (robust_unlink(fn) != 0) {
- rsyserr(FERROR, errno, "delete_one: unlink %s failed",
- full_fname(fn));
- } else if (verbose)
- rprintf(FINFO, "deleting %s\n", safe_fname(fn));
- } else {
- if (do_rmdir(fn) != 0) {
- if (errno != ENOTEMPTY && errno != EEXIST) {
- rsyserr(FERROR, errno,
- "delete_one: rmdir %s failed",
- full_fname(fn));
- }
- } else if (verbose) {
- rprintf(FINFO, "deleting directory %s\n",
- safe_fname(fn));
- }
- }
-}
-
-
-static int is_backup_file(char *fn)
-{
- int k = strlen(fn) - backup_suffix_len;
- return k > 0 && strcmp(fn+k, backup_suffix) == 0;
-}
-
-
-/* This deletes any files on the receiving side that are not present
- * on the sending side. */
+/* This deletes any files on the receiving side that are not present on the
+ * sending side. This is used by --delete-before and --delete-after. */
void delete_files(struct file_list *flist)
{
- struct file_list *local_file_list;
- int i, j;
- char *argv[1], fbuf[MAXPATHLEN];
- static int deletion_count;
-
- if (cvs_exclude)
- add_cvs_excludes();
-
- if (io_error && !(lp_ignore_errors(module_id) || ignore_errors)) {
- rprintf(FINFO,"IO error encountered - skipping file deletion\n");
- return;
- }
+ char fbuf[MAXPATHLEN];
+ int j;
for (j = 0; j < flist->count; j++) {
- if (!(flist->files[j]->flags & FLAG_TOP_DIR)
- || !S_ISDIR(flist->files[j]->mode))
- continue;
-
- argv[0] = f_name_to(flist->files[j], fbuf);
+ struct file_struct *file = flist->files[j];
- if (!(local_file_list = send_file_list(-1, 1, argv)))
+ if (!(file->flags & FLAG_DEL_HERE))
continue;
- if (verbose > 1)
+ f_name_to(file, fbuf);
+ if (verbose > 1 && file->flags & FLAG_TOP_DIR)
rprintf(FINFO, "deleting in %s\n", safe_fname(fbuf));
- for (i = local_file_list->count-1; i >= 0; i--) {
- if (max_delete && deletion_count >= max_delete)
- break;
- if (!local_file_list->files[i]->basename)
- continue;
- if (flist_find(flist,local_file_list->files[i]) < 0) {
- char *f = f_name(local_file_list->files[i]);
- int mode = local_file_list->files[i]->mode;
- if (make_backups && (backup_dir || !is_backup_file(f))
- && !S_ISDIR(mode)) {
- make_backup(f);
- if (verbose) {
- rprintf(FINFO, "deleting %s\n",
- safe_fname(f));
- }
- } else
- delete_one(f, S_ISDIR(mode) != 0);
- deletion_count++;
- }
- }
- flist_free(local_file_list);
+ delete_in_dir(flist, fbuf, file);
}
}
maxname = MIN(MAXPATHLEN - 7 - length, NAME_MAX - 8);
if (maxname < 1) {
- rprintf(FERROR, "temporary filename too long: %s\n", fname);
+ rprintf(FERROR, "temporary filename too long: %s\n",
+ safe_fname(fname));
fnametmp[0] = '\0';
return 0;
}
static char file_sum2[MD4_SUM_LENGTH];
struct map_struct *mapbuf;
struct sum_struct sum;
- unsigned int len;
+ int32 len;
OFF_T offset = 0;
OFF_T offset2;
char *data;
- int i;
+ int32 i;
char *map = NULL;
read_sum_head(f_in, &sum);
if (fd_r >= 0 && size_r > 0) {
- OFF_T map_size = MAX(sum.blength * 2, 16*1024);
- mapbuf = map_file(fd_r, size_r, map_size, sum.blength);
+ int32 read_size = MAX(sum.blength * 2, 16*1024);
+ mapbuf = map_file(fd_r, size_r, read_size, sum.blength);
if (verbose > 2) {
rprintf(FINFO, "recv mapped %s of size %.0f\n",
safe_fname(fname_r), (double)size_r);
stats.literal_data += i;
cleanup_got_literal = 1;
- sum_update(data,i);
+ sum_update(data, i);
if (fd != -1 && write_file(fd,data,i) != i)
goto report_write_error;
}
i = -(i+1);
- offset2 = i*(OFF_T)sum.blength;
+ offset2 = i * (OFF_T)sum.blength;
len = sum.blength;
if (i == (int)sum.count-1 && sum.remainder != 0)
len = sum.remainder;
stats.matched_data += len;
- if (verbose > 3)
- rprintf(FINFO,"chunk[%d] of size %d at %.0f offset=%.0f\n",
- i,len,(double)offset2,(double)offset);
+ if (verbose > 3) {
+ rprintf(FINFO,
+ "chunk[%d] of size %ld at %.0f offset=%.0f\n",
+ i, (long)len, (double)offset2, (double)offset);
+ }
if (mapbuf) {
map = map_ptr(mapbuf,offset2,len);
see_token(map, len);
- sum_update(map,len);
+ sum_update(map, len);
}
if (inplace) {
offset += len;
}
- flush_write_file(fd);
+ if (flush_write_file(fd) < 0)
+ goto report_write_error;
#ifdef HAVE_FTRUNCATE
if (inplace && fd != -1)
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;
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();
if (verbose > 2)
rprintf(FINFO, "recv_files phase=%d\n", phase);
send_msg(MSG_DONE, "", 0);
- if (keep_partial)
+ if (keep_partial && !partial_dir)
make_backups = 0; /* prevents double backup */
continue;
}
}
file = flist->files[i];
+ if (S_ISDIR(file->mode)) {
+ rprintf(FERROR, "[%s] got index of directory: %d\n",
+ who_am_i(), i);
+ exit_cleanup(RERR_PROTOCOL);
+ }
stats.current_file_index = i;
stats.num_transferred_files++;
stats.total_transferred_size += file->length;
cleanup_got_literal = 0;
- if (local_name)
- fname = local_name;
- else
- fname = f_name_to(file, fbuf);
+ fname = local_name ? local_name : f_name_to(file, fbuf);
+
+ if (server_filter_list.head
+ && check_filter(&server_filter_list, fname, 0) < 0) {
+ rprintf(FERROR, "attempt to hack rsync failed.\n");
+ exit_cleanup(RERR_PROTOCOL);
+ }
+
+ if (verbose > 2)
+ rprintf(FINFO, "recv_files(%s)\n", safe_fname(fname));
if (dry_run) {
if (!am_server && verbose) /* log the transfer */
initial_stats = stats;
- if (verbose > 2)
- rprintf(FINFO, "recv_files(%s)\n", safe_fname(fname));
-
if (read_batch) {
while (i > next_gen_i) {
if (f_in_name >= 0 && next_gen_i >= 0)
next_gen_i = -1;
}
- if (server_exclude_list.head
- && check_exclude(&server_exclude_list, fname,
- S_ISDIR(file->mode)) < 0) {
- rprintf(FERROR, "attempt to hack rsync failed.\n");
- exit_cleanup(RERR_PROTOCOL);
- }
-
partialptr = partial_dir ? partial_dir_fname(fname) : fname;
if (f_in_name >= 0) {
case FNAMECMP_BACKUP:
fnamecmp = get_backup_name(fname);
break;
- case FNAMECMP_BASIS_DIR:
default:
+ if (j >= basis_dir_cnt) {
+ rprintf(FERROR,
+ "invalid basis_dir index: %d.\n",
+ j);
+ exit_cleanup(RERR_PROTOCOL);
+ }
pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
basis_dir[j], fname);
fnamecmp = fnamecmpbuf;
exit_cleanup(RERR_FILEIO);
}
- if (recv_ok || inplace)
- finish_transfer(fname, fnametmp, file, recv_ok);
- else if (keep_partial && partialptr
- && handle_partial_dir(partialptr, PDIR_CREATE))
- finish_transfer(partialptr, fnametmp, file, 0);
- else {
+ if ((recv_ok && (!delay_updates || !partialptr)) || inplace) {
+ finish_transfer(fname, fnametmp, file, recv_ok, 1);
+ if (partialptr != fname && fnamecmp == partialptr) {
+ do_unlink(partialptr);
+ handle_partial_dir(partialptr, PDIR_DELETE);
+ }
+ } else if (keep_partial && partialptr
+ && 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);
}
- if (partialptr != fname && fnamecmp == partialptr && recv_ok) {
- do_unlink(partialptr);
- handle_partial_dir(partialptr, PDIR_DELETE);
- }
-
cleanup_disable();
if (!recv_ok) {
}
make_backups = save_make_backups;
- if (delete_after && recurse && !local_name && flist->count > 0)
+ 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",
+ safe_fname(partialptr),
+ safe_fname(fname));
+ }
+ if (do_rename(partialptr, fname) < 0) {
+ rsyserr(FERROR, errno,
+ "rename failed for %s (from %s)",
+ full_fname(fname),
+ safe_fname(partialptr));
+ } else {
+ handle_partial_dir(partialptr,
+ PDIR_DELETE);
+ }
+ }
+ }
+ }
+
+ if (delete_after && !local_name && flist->count > 0)
delete_files(flist);
if (verbose > 2)