On Thu, Sep 15, 2005 at 08:49:33AM -0700, Wayne Davison wrote: > (At least, that's all the side-effects I can think of off the top of > my head.)
At least one more was that backing up a directory without a --backup-dir still requires using rename(). Attached is a patch that I think effects the change of using link() instead of rename() when possible. It is very minimally tested -- i.e. it passes "make test". If you choose to try it out, run "make proto" after applying the patch. ..wayne..
--- backup.c 10 Jun 2005 17:57:18 -0000 1.45 +++ backup.c 15 Sep 2005 16:55:56 -0000 @@ -52,43 +52,6 @@ char *get_backup_name(char *fname) return NULL; } -/* simple backup creates a backup with a suffix in the same directory */ -static int make_simple_backup(char *fname) -{ - int rename_errno; - char *fnamebak = get_backup_name(fname); - - if (!fnamebak) - return 0; - - while (1) { - if (do_rename(fname, fnamebak) == 0) { - if (verbose > 1) { - rprintf(FINFO, "backed up %s to %s\n", - safe_fname(fname), - safe_fname(fnamebak)); - } - break; - } - /* cygwin (at least version b19) reports EINVAL */ - if (errno == ENOENT || errno == EINVAL) - break; - - rename_errno = errno; - if (errno == EISDIR && do_rmdir(fnamebak) == 0) - continue; - if (errno == ENOTDIR && do_unlink(fnamebak) == 0) - continue; - - rsyserr(FERROR, rename_errno, "rename %s to backup %s", - safe_fname(fname), safe_fname(fnamebak)); - errno = rename_errno; - return 0; - } - - return 1; -} - /**************************************************************************** Create a directory given an absolute path, perms based upon another directory @@ -157,19 +120,75 @@ failure: return -1; } -/* robustly move a file, creating new directory structures if necessary */ -static int robust_move(char *src, char *dst) +static int do_backup(char *src, char *dst, int use_rename, + int make_missing_dirs, int nlinks) { - if (robust_rename(src, dst, 0755) < 0 && (errno != ENOENT - || make_bak_dir(dst) < 0 || robust_rename(src, dst, 0755) < 0)) + int backup_errno; + +#ifndef SUPPORT_LINKS + use_rename = 1; +#endif + + while (1) { + /* CAUTION: the calling logic must take this into account! */ + if (use_rename) { + if (do_rename(src, dst) == 0) { + if (nlinks > 1) { + /* If file is hard-linked into backup dir, + * rename() might succeed but do nothing! */ + robust_unlink(src); /* Just in case... */ + } + break; + } + } else { +#ifdef SUPPORT_LINKS + robust_unlink(dst); + if (do_link(src, dst) == 0) + break; +#endif + } + + backup_errno = errno; + + if (make_missing_dirs && backup_errno == ENOENT + && make_bak_dir(dst) == 0) + continue; + + /* cygwin (at least version b19) reports EINVAL */ + if (backup_errno == ENOENT || backup_errno == EINVAL) + break; + + if (backup_errno == EISDIR && do_rmdir(src) == 0) + continue; + if (backup_errno == ENOTDIR && do_unlink(src) == 0) + continue; + + rsyserr(FERROR, backup_errno, "backup of %s to %s", + safe_fname(src), safe_fname(dst)); + errno = backup_errno; return -1; + } + + if (verbose > 1) { + rprintf(FINFO, "backed up %s to %s\n", + safe_fname(src), safe_fname(dst)); + } return 0; } +/* simple backup creates a backup with a suffix in the same directory */ +static int make_simple_backup(char *fname, int use_rename) +{ + char *fnamebak = get_backup_name(fname); + + if (fnamebak && do_backup(fname, fnamebak, use_rename, 0, 0) == 0) + return 1; + return 0; +} /* If we have a --backup-dir, then we get here from make_backup(). - * We will move the file to be deleted into a parallel directory tree. */ -static int keep_backup(char *fname) + * We will move/link the file into a parallel directory tree. */ +static int keep_backup(char *fname, int use_rename) { STRUCT_STAT st; struct file_struct *file; @@ -199,8 +218,9 @@ static int keep_backup(char *fname) rprintf(FINFO, "make_backup: DEVICE %s successful.\n", safe_fname(fname)); } + if (use_rename) + do_unlink(fname); kept = 1; - do_unlink(fname); } if (!kept && S_ISDIR(file->mode)) { @@ -212,6 +232,7 @@ static int keep_backup(char *fname) full_fname(buf)); } + /* Note: use_rename must be non-zero when hadling a dir. */ ret_code = do_rmdir(fname); if (verbose > 2) { rprintf(FINFO, "make_backup: RMDIR %s returns %i\n", @@ -237,7 +258,8 @@ static int keep_backup(char *fname) full_fname(buf), safe_fname(file->u.link)); } - do_unlink(fname); + if (use_rename) + do_unlink(fname); kept = 1; } } @@ -249,32 +271,20 @@ static int keep_backup(char *fname) return 1; } - /* move to keep tree if a file */ - if (!kept) { - if (robust_move(fname, buf) != 0) { - rsyserr(FERROR, errno, "keep_backup failed: %s -> \"%s\"", - full_fname(fname), safe_fname(buf)); - } else if (st.st_nlink > 1) { - /* If someone has hard-linked the file into the backup - * dir, rename() might return success but do nothing! */ - robust_unlink(fname); /* Just in case... */ - } - } + /* If a normal file, make a backup. */ + if (!kept) + do_backup(fname, buf, use_rename, 1, st.st_nlink); set_perms(buf, file, NULL, 0); free(file); - if (verbose > 1) { - rprintf(FINFO, "backed up %s to %s\n", - safe_fname(fname), safe_fname(buf)); - } return 1; } /* main backup switch routine */ -int make_backup(char *fname) +int make_backup(char *fname, int use_rename) { if (backup_dir) - return keep_backup(fname); - return make_simple_backup(fname); + return keep_backup(fname, use_rename); + return make_simple_backup(fname, use_rename); } --- generator.c 6 Sep 2005 18:12:38 -0000 1.222 +++ generator.c 15 Sep 2005 16:55:57 -0000 @@ -114,7 +114,7 @@ static int delete_item(char *fname, int if (max_delete && ++deletion_count > max_delete) return 0; if (make_backups && (backup_dir || !is_backup_file(fname))) - ok = make_backup(fname); + ok = make_backup(fname, 1); else ok = robust_unlink(fname) == 0; if (ok) { @@ -139,7 +139,7 @@ static int delete_item(char *fname, int errno = ENOTEMPTY; } else if (make_backups && !backup_dir && !is_backup_file(fname) && !(flags & DEL_FORCE_RECURSE)) - ok = make_backup(fname); + ok = make_backup(fname, 1); else ok = do_rmdir(fname) == 0; if (ok) { --- hlink.c 31 Jul 2005 23:19:42 -0000 1.54 +++ hlink.c 15 Sep 2005 16:55:57 -0000 @@ -154,7 +154,7 @@ static int maybe_hard_link(struct file_s return 0; } if (make_backups) { - if (!make_backup(fname)) + if (!make_backup(fname, 1)) return -1; } else if (robust_unlink(fname)) { rsyserr(FERROR, errno, "unlink %s failed", --- receiver.c 30 Aug 2005 02:58:42 -0000 1.164 +++ receiver.c 15 Sep 2005 16:55:57 -0000 @@ -347,7 +347,7 @@ static void handle_delayed_updates(struc struct file_struct *file = flist->files[i]; fname = local_name ? local_name : f_name(file); if ((partialptr = partial_dir_fname(fname)) != NULL) { - if (make_backups && !make_backup(fname)) + if (make_backups && !make_backup(fname, 0)) continue; if (verbose > 2) { rprintf(FINFO, "renaming %s to %s\n", --- rsync.c 27 Jul 2005 23:30:58 -0000 1.168 +++ rsync.c 15 Sep 2005 16:55:57 -0000 @@ -179,7 +179,7 @@ void finish_transfer(char *fname, char * goto do_set_perms; } - if (make_backups && overwriting_basis && !make_backup(fname)) + if (make_backups && overwriting_basis && !make_backup(fname, 0)) return; /* Change permissions before putting the file into place. */ --- t_stub.c 25 Jan 2005 10:39:14 -0000 1.10 +++ t_stub.c 15 Sep 2005 16:55:57 -0000 @@ -28,6 +28,7 @@ int modify_window = 0; int module_id = -1; +int make_backups = 0; char *partial_dir; struct filter_list_struct server_filter_list; --- util.c 3 Aug 2005 04:51:29 -0000 1.186 +++ util.c 15 Sep 2005 17:05:33 -0000 @@ -31,6 +31,7 @@ extern int verbose; extern int dry_run; extern int module_id; extern int modify_window; +extern int make_backups; extern char *partial_dir; extern struct filter_list_struct server_filter_list; @@ -392,6 +393,12 @@ int robust_rename(char *from, char *to, break; #endif case EXDEV: +#ifdef SUPPORT_LINKS + if (make_backups && robust_unlink(to) != 0 + && errno != ENOENT) + return -1; +#endif + if (copy_file(from, to, mode) != 0) return -2; do_unlink(from);
-- To unsubscribe or change options: https://lists.samba.org/mailman/listinfo/rsync Before posting, read: http://www.catb.org/~esr/faqs/smart-questions.html