* Robust unlink: some OS'es (HPUX) refuse to unlink busy files, so * rename to /.rsyncNNN instead. * * Note that successive rsync runs will shuffle the filenames around a * bit as long as the file is still busy; this is because this function * does not know if the unlink call is due to a new file coming in, or * --delete trying to remove old .rsyncNNN files, hence it renames it * each
| 494 | * each time. |
| 495 | **/ |
| 496 | int robust_unlink(const char *fname) |
| 497 | { |
| 498 | #ifndef ETXTBSY |
| 499 | return do_unlink_at(fname); |
| 500 | #else |
| 501 | static int counter = 1; |
| 502 | int rc, pos, start; |
| 503 | char path[MAXPATHLEN]; |
| 504 | |
| 505 | rc = do_unlink_at(fname); |
| 506 | if (rc == 0 || errno != ETXTBSY) |
| 507 | return rc; |
| 508 | |
| 509 | if ((pos = strlcpy(path, fname, MAXPATHLEN)) >= MAXPATHLEN) |
| 510 | pos = MAXPATHLEN - 1; |
| 511 | |
| 512 | while (pos > 0 && path[pos-1] != '/') |
| 513 | pos--; |
| 514 | pos += strlcpy(path+pos, ".rsync", MAXPATHLEN-pos); |
| 515 | |
| 516 | if (pos > (MAXPATHLEN-MAX_RENAMES_DIGITS-1)) { |
| 517 | errno = ETXTBSY; |
| 518 | return -1; |
| 519 | } |
| 520 | |
| 521 | /* start where the last one left off to reduce chance of clashes */ |
| 522 | start = counter; |
| 523 | do { |
| 524 | snprintf(&path[pos], MAX_RENAMES_DIGITS+1, "%03d", counter); |
| 525 | if (++counter >= MAX_RENAMES) |
| 526 | counter = 1; |
| 527 | } while ((rc = access(path, 0)) == 0 && counter != start); |
| 528 | |
| 529 | if (INFO_GTE(MISC, 1)) { |
| 530 | rprintf(FWARNING, "renaming %s to %s because of text busy\n", |
| 531 | fname, path); |
| 532 | } |
| 533 | |
| 534 | /* maybe we should return rename()'s exit status? Nah. */ |
| 535 | if (do_rename_at(fname, path) != 0) { |
| 536 | errno = ETXTBSY; |
| 537 | return -1; |
| 538 | } |
| 539 | return 0; |
| 540 | #endif |
| 541 | } |
| 542 | |
| 543 | /* Returns 0 on successful rename, 1 if we successfully copied the file |
| 544 | * across filesystems, -2 if copy_file() failed, and -1 on other errors. |
no test coverage detected