X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/a8f7e4b835a39b180ee728bfe8c44650096f99c0..530adb762573d9f37be07eb38d0ffc7b5c401e6a:/util.c diff --git a/util.c b/util.c index fd01283a..cb47c2a1 100644 --- a/util.c +++ b/util.c @@ -353,18 +353,33 @@ int robust_unlink(char *fname) #endif } -int robust_rename(char *from, char *to) +/* Returns 0 on success, -1 on most errors, and -2 if we got an error + * trying to copy the file across file systems. */ +int robust_rename(char *from, char *to, int mode) { -#ifndef ETXTBSY - return do_rename(from, to); -#else - int rc = do_rename(from, to); - if (rc == 0 || errno != ETXTBSY) - return rc; - if (robust_unlink(to) != 0) - return -1; - return do_rename(from, to); + int tries = 4; + + while (tries--) { + if (do_rename(from, to) == 0) + return 0; + + switch (errno) { +#ifdef ETXTBSY + case ETXTBSY: + if (robust_unlink(to) != 0) + return -1; + break; #endif + case EXDEV: + if (copy_file(from, to, mode) != 0) + return -2; + do_unlink(from); + return 0; + default: + return -1; + } + } + return -1; }