| 495 | | copy_tempfile(int fd, const char *out) |
| 496 | | { |
| 497 | | struct stat sb; |
| 498 | | char *buf; |
| 499 | | int out_fd, bytes; |
| 500 | | |
| 501 | | if (fstat(fd, &sb) == -1) |
| 502 | | err(EXIT_FAILURE, "fstat tmpfile failed"); |
| 503 | | if ((buf = malloc((size_t) sb.st_blksize)) == NULL) |
| 504 | | err(EXIT_FAILURE, "malloc failed"); |
| 505 | | if (unlink(out) < 0) |
| 506 | | err(EXIT_FAILURE, "unlink %s failed", out); |
| 507 | | if ((out_fd = open(out, O_CREAT | O_WRONLY, 0755)) == -1) |
| 508 | | err(EXIT_FAILURE, "create %s failed", out); |
| 509 | | |
| 510 | | if (lseek(fd, 0, SEEK_SET) < 0) |
| 511 | | err(EXIT_FAILURE, "lseek tmpfile failed"); |
| 512 | | while ((bytes = read(fd, buf, sb.st_blksize)) > 0) { |
| 513 | | if (write(out_fd, buf, (size_t) bytes) != bytes) { |
| 514 | | (void) unlink(out); |
| 515 | | err(EXIT_FAILURE, "write %s failed", out); |
| 516 | | } |
| 517 | | } |
| 518 | | if (bytes < 0) { |
| 519 | | (void) unlink(out); |
| 520 | | err(EXIT_FAILURE, "read failed"); |
| 521 | | } |
| 522 | | |
| 523 | | free(buf); |
| 524 | | close(fd); |
| 525 | | |
| 526 | | return (out_fd); |
| | 496 | copy_from_tempfile(const char *src, const char *dst, int infd, int *outfd) |
| | 497 | { |
| | 498 | int tmpfd; |
| | 499 | |
| | 500 | /* |
| | 501 | * First, check if we can use rename(). |
| | 502 | */ |
| | 503 | if (rename(src, dst) >= 0) { |
| | 504 | *outfd = infd; |
| | 505 | return (0); |
| | 506 | } else if (errno != EXDEV) |
| | 507 | return (-1); |
| | 508 | |
| | 509 | /* |
| | 510 | * If the rename() failed due to 'src' and 'dst' residing in |
| | 511 | * two different file systems, invoke a helper function in |
| | 512 | * libelftc to do the copy. |
| | 513 | */ |
| | 514 | |
| | 515 | if (unlink(dst) < 0) |
| | 516 | return (-1); |
| | 517 | |
| | 518 | if ((tmpfd = open(dst, O_CREAT | O_WRONLY, 0755)) < 0) |
| | 519 | return (-1); |
| | 520 | |
| | 521 | if (lseek(infd, 0, SEEK_SET) < 0) |
| | 522 | return (-1); |
| | 523 | |
| | 524 | if (elftc_copyfile(infd, tmpfd) < 0) |
| | 525 | return (-1); |
| | 526 | |
| | 527 | /* |
| | 528 | * Remove the temporary file from the file system |
| | 529 | * namespace, and close its file descriptor. |
| | 530 | */ |
| | 531 | if (unlink(src) < 0) |
| | 532 | return (-1); |
| | 533 | |
| | 534 | (void) close(infd); |
| | 535 | |
| | 536 | /* |
| | 537 | * Return the file descriptor for the destination. |
| | 538 | */ |
| | 539 | *outfd = tmpfd; |
| | 540 | |
| | 541 | return (0); |
| 670 | | if (rename(tempfile, dst) == -1) { |
| 671 | | if (errno == EXDEV) { |
| 672 | | ofd = copy_tempfile(ofd, dst); |
| 673 | | if (unlink(tempfile) < 0) |
| 674 | | err(EXIT_FAILURE, "unlink %s failed", |
| 675 | | tempfile); |
| 676 | | } else |
| 677 | | err(EXIT_FAILURE, "rename %s to %s failed", |
| 678 | | tempfile, dst); |
| 679 | | } |
| | 685 | |
| | 686 | if (copy_from_tempfile(tempfile, dst, ofd, &tfd) < 0) |
| | 687 | err(EXIT_FAILURE, "creation of %s failed", dst); |
| | 688 | |