Junio C Hamano | f3123c4 | 2005-10-22 01:28:13 -0700 | [diff] [blame] | 1 | #include "cache.h" |
| 2 | |
| 3 | int copy_fd(int ifd, int ofd) |
| 4 | { |
| 5 | while (1) { |
Junio C Hamano | f3123c4 | 2005-10-22 01:28:13 -0700 | [diff] [blame] | 6 | char buffer[8192]; |
| 7 | char *buf = buffer; |
Johan Herland | 8a912bc | 2007-05-15 14:49:22 +0200 | [diff] [blame] | 8 | ssize_t len = xread(ifd, buffer, sizeof(buffer)); |
Junio C Hamano | f3123c4 | 2005-10-22 01:28:13 -0700 | [diff] [blame] | 9 | if (!len) |
| 10 | break; |
| 11 | if (len < 0) { |
Ariel Badichi | 8b1f6de | 2008-04-23 04:05:29 +0300 | [diff] [blame] | 12 | int read_error = errno; |
Junio C Hamano | e6c64fc | 2005-11-05 11:02:56 -0800 | [diff] [blame] | 13 | close(ifd); |
Junio C Hamano | f3123c4 | 2005-10-22 01:28:13 -0700 | [diff] [blame] | 14 | return error("copy-fd: read returned %s", |
Junio C Hamano | e6c64fc | 2005-11-05 11:02:56 -0800 | [diff] [blame] | 15 | strerror(read_error)); |
Junio C Hamano | f3123c4 | 2005-10-22 01:28:13 -0700 | [diff] [blame] | 16 | } |
Junio C Hamano | 1c15afb | 2005-12-19 16:18:28 -0800 | [diff] [blame] | 17 | while (len) { |
| 18 | int written = xwrite(ofd, buf, len); |
Junio C Hamano | f3123c4 | 2005-10-22 01:28:13 -0700 | [diff] [blame] | 19 | if (written > 0) { |
| 20 | buf += written; |
| 21 | len -= written; |
Junio C Hamano | f3123c4 | 2005-10-22 01:28:13 -0700 | [diff] [blame] | 22 | } |
Sam Ravnborg | 08337a9 | 2005-12-27 09:19:05 +0100 | [diff] [blame] | 23 | else if (!written) { |
| 24 | close(ifd); |
Junio C Hamano | f3123c4 | 2005-10-22 01:28:13 -0700 | [diff] [blame] | 25 | return error("copy-fd: write returned 0"); |
Sam Ravnborg | 08337a9 | 2005-12-27 09:19:05 +0100 | [diff] [blame] | 26 | } else { |
Ariel Badichi | 8b1f6de | 2008-04-23 04:05:29 +0300 | [diff] [blame] | 27 | int write_error = errno; |
Sam Ravnborg | 08337a9 | 2005-12-27 09:19:05 +0100 | [diff] [blame] | 28 | close(ifd); |
Junio C Hamano | 1c15afb | 2005-12-19 16:18:28 -0800 | [diff] [blame] | 29 | return error("copy-fd: write returned %s", |
Ariel Badichi | 8b1f6de | 2008-04-23 04:05:29 +0300 | [diff] [blame] | 30 | strerror(write_error)); |
Sam Ravnborg | 08337a9 | 2005-12-27 09:19:05 +0100 | [diff] [blame] | 31 | } |
Junio C Hamano | f3123c4 | 2005-10-22 01:28:13 -0700 | [diff] [blame] | 32 | } |
| 33 | } |
| 34 | close(ifd); |
| 35 | return 0; |
| 36 | } |
Daniel Barkalow | 1468bd4 | 2008-02-25 14:24:48 -0500 | [diff] [blame] | 37 | |
Clemens Buchacher | f7835a2 | 2009-09-12 11:03:48 +0200 | [diff] [blame] | 38 | static int copy_times(const char *dst, const char *src) |
| 39 | { |
| 40 | struct stat st; |
| 41 | struct utimbuf times; |
| 42 | if (stat(src, &st) < 0) |
| 43 | return -1; |
| 44 | times.actime = st.st_atime; |
| 45 | times.modtime = st.st_mtime; |
| 46 | if (utime(dst, ×) < 0) |
| 47 | return -1; |
| 48 | return 0; |
| 49 | } |
| 50 | |
Daniel Barkalow | 1468bd4 | 2008-02-25 14:24:48 -0500 | [diff] [blame] | 51 | int copy_file(const char *dst, const char *src, int mode) |
| 52 | { |
| 53 | int fdi, fdo, status; |
| 54 | |
| 55 | mode = (mode & 0111) ? 0777 : 0666; |
| 56 | if ((fdi = open(src, O_RDONLY)) < 0) |
| 57 | return fdi; |
| 58 | if ((fdo = open(dst, O_WRONLY | O_CREAT | O_EXCL, mode)) < 0) { |
| 59 | close(fdi); |
| 60 | return fdo; |
| 61 | } |
| 62 | status = copy_fd(fdi, fdo); |
| 63 | if (close(fdo) != 0) |
Ariel Badichi | 8b1f6de | 2008-04-23 04:05:29 +0300 | [diff] [blame] | 64 | return error("%s: close error: %s", dst, strerror(errno)); |
Daniel Barkalow | 1468bd4 | 2008-02-25 14:24:48 -0500 | [diff] [blame] | 65 | |
| 66 | if (!status && adjust_shared_perm(dst)) |
| 67 | return -1; |
| 68 | |
| 69 | return status; |
| 70 | } |
Clemens Buchacher | f7835a2 | 2009-09-12 11:03:48 +0200 | [diff] [blame] | 71 | |
| 72 | int copy_file_with_time(const char *dst, const char *src, int mode) |
| 73 | { |
| 74 | int status = copy_file(dst, src, mode); |
| 75 | if (!status) |
| 76 | return copy_times(dst, src); |
| 77 | return status; |
| 78 | } |