--- generator.c.orig 2011-03-26 11:17:14.000000000 -0600 +++ generator.c 2011-08-09 12:39:17.000000000 -0600 @@ -54,6 +54,7 @@ extern int delay_updates; extern int update_only; extern int ignore_existing; +extern int move_existing; extern int ignore_non_existing; extern int inplace; extern int append_mode; @@ -1442,6 +1443,98 @@ goto cleanup; } + /* DEVIN - move-existing */ + /* If move is not possible, revert to ignore-existing behavior */ + if (move_existing > 0 && statret == 0 && S_ISREG(sx.st.st_mode) + && (!is_dir || !S_ISDIR(sx.st.st_mode))) { + char *new_fname, *base_fname, *ext, *p, *q; + time_t t = time(NULL); + struct tm *tm = localtime(&t); + STRUCT_STAT st; + char uniq[100], count_str[10]; + int count, moved, len, ret; + + rprintf(FINFO, "starting rsync move-existing processing for fname %s\n", fname); + + /* get base_fname and ext */ + base_fname = malloc(strlen(fname) + 1); + if (base_fname == NULL) { + rsyserr(FERROR, errno, "base_fname malloc failure, cleanup"); + goto cleanup; + } + ext = strrchr(fname, '.'); + p = fname; + q = base_fname; + while (p != ext && *p != '\0') { + *q++ = *p++; + } + *q = '\0'; + + rprintf(FINFO, "base_fname is: %s, ext is %s, fname is: %s\n", base_fname, ext, fname); + + /* get uniq time stamp */ + if (strftime(uniq, sizeof uniq - 1, "_%Y-%m-%d-%H-%M-%S", tm) == 0) { + rsyserr(FERROR, errno, "strftime error, cleanup"); + free(base_fname); + goto cleanup; + } + + /* alloc new filename mem, +3 for count_str */ + len = strlen(fname) + strlen(uniq) + 3; + if (len > MAXPATHLEN) { + rprintf(FERROR, "new_fname is larger than MAXPATHLEN, cleanup\n"); + free(base_fname); + goto cleanup; + } + new_fname = malloc(len + 1); + if (new_fname == NULL) { + rsyserr(FERROR, errno, "new_fname malloc failure, cleanup"); + free(base_fname); + goto cleanup; + } + + count = 0; + moved = 0; + while (moved != 1 && count <= 99) { + /* build new filename */ + strcpy(new_fname, base_fname); + strcat(new_fname, uniq); + sprintf(count_str, "-%d", count); + strcat(new_fname, count_str); + if (ext != NULL) + strcat(new_fname, ext); + + rprintf(FINFO, "attempting to use new_fname of %s\n", new_fname); + + /* attempt to move the file */ + ret = link_stat(new_fname, &st, 0); + if (ret != 0 && errno == ENOENT) { + rprintf(FINFO, "new_fname %s does not exist, attempting do_rename\n", new_fname); + if (do_rename(fname, new_fname) == 0) { + rprintf(FINFO, "do_rename from %s to %s succeeded\n", fname, new_fname); + moved = 1; + break; + } else { + rprintf(FINFO, "do_rename from %s to %s failed\n", fname, new_fname); + } + } else { + rprintf(FINFO, "new_fname exists or other error: ret = %d, errno = %d\n", ret, errno); + } + count++; + } + free(base_fname); + free(new_fname); + + if (moved != 1) { + rprintf(FERROR, "move-existing did not succeed for %s, skipping\n", fname); + goto cleanup; + } + + /* Redo statret, since the file has moved */ + statret = link_stat(fname, &sx.st, keep_dirlinks && is_dir); + stat_errno = errno; + } + fnamecmp = fname; if (is_dir) { --- options.c.orig 2011-08-06 22:01:22.000000000 -0600 +++ options.c 2011-08-06 22:04:17.000000000 -0600 @@ -109,6 +109,7 @@ int fuzzy_basis = 0; size_t bwlimit_writemax = 0; int ignore_existing = 0; +int move_existing = 0; int ignore_non_existing = 0; int need_messages_from_generator = 0; int max_delete = INT_MIN; @@ -365,6 +366,7 @@ rprintf(F," --rsync-path=PROGRAM specify the rsync to run on the remote machine\n"); rprintf(F," --existing skip creating new files on receiver\n"); rprintf(F," --ignore-existing skip updating files that already exist on receiver\n"); + rprintf(F," --move-existing move files that already exist on receiver\n"); rprintf(F," --remove-source-files sender removes synchronized files (non-dirs)\n"); rprintf(F," --del an alias for --delete-during\n"); rprintf(F," --delete delete extraneous files from destination dirs\n"); @@ -536,6 +538,7 @@ {"existing", 0, POPT_ARG_NONE, &ignore_non_existing, 0, 0, 0 }, {"ignore-non-existing",0,POPT_ARG_NONE, &ignore_non_existing, 0, 0, 0 }, {"ignore-existing", 0, POPT_ARG_NONE, &ignore_existing, 0, 0, 0 }, + {"move-existing", 0, POPT_ARG_NONE, &move_existing, 0, 0, 0 }, {"max-size", 0, POPT_ARG_STRING, &max_size_arg, OPT_MAX_SIZE, 0, 0 }, {"min-size", 0, POPT_ARG_STRING, &min_size_arg, OPT_MIN_SIZE, 0, 0 }, {"sparse", 'S', POPT_ARG_VAL, &sparse_files, 1, 0, 0 }, @@ -2021,6 +2024,9 @@ if (ignore_existing) args[ac++] = "--ignore-existing"; + if (move_existing) + args[ac++] = "--move-existing"; + /* Backward compatibility: send --existing, not --ignore-non-existing. */ if (ignore_non_existing) args[ac++] = "--existing";