diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-09 13:34:27 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-09 13:34:27 +0000 |
commit | 4dbdc42d9e7c3968ff7f690d00680419c9b8cb0f (patch) | |
tree | 47c1d492e9c956c1cd2b74dbd3b9d8b0db44dc4e /copy.c | |
parent | Initial commit. (diff) | |
download | git-4dbdc42d9e7c3968ff7f690d00680419c9b8cb0f.tar.xz git-4dbdc42d9e7c3968ff7f690d00680419c9b8cb0f.zip |
Adding upstream version 1:2.43.0.upstream/1%2.43.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'copy.c')
-rw-r--r-- | copy.c | 69 |
1 files changed, 69 insertions, 0 deletions
@@ -0,0 +1,69 @@ +#include "git-compat-util.h" +#include "copy.h" +#include "path.h" + +int copy_fd(int ifd, int ofd) +{ + while (1) { + char buffer[8192]; + ssize_t len = xread(ifd, buffer, sizeof(buffer)); + if (!len) + break; + if (len < 0) + return COPY_READ_ERROR; + if (write_in_full(ofd, buffer, len) < 0) + return COPY_WRITE_ERROR; + } + return 0; +} + +static int copy_times(const char *dst, const char *src) +{ + struct stat st; + struct utimbuf times; + if (stat(src, &st) < 0) + return -1; + times.actime = st.st_atime; + times.modtime = st.st_mtime; + if (utime(dst, ×) < 0) + return -1; + return 0; +} + +int copy_file(const char *dst, const char *src, int mode) +{ + int fdi, fdo, status; + + mode = (mode & 0111) ? 0777 : 0666; + if ((fdi = open(src, O_RDONLY)) < 0) + return fdi; + if ((fdo = open(dst, O_WRONLY | O_CREAT | O_EXCL, mode)) < 0) { + close(fdi); + return fdo; + } + status = copy_fd(fdi, fdo); + switch (status) { + case COPY_READ_ERROR: + error_errno("copy-fd: read returned"); + break; + case COPY_WRITE_ERROR: + error_errno("copy-fd: write returned"); + break; + } + close(fdi); + if (close(fdo) != 0) + return error_errno("%s: close error", dst); + + if (!status && adjust_shared_perm(dst)) + return -1; + + return status; +} + +int copy_file_with_time(const char *dst, const char *src, int mode) +{ + int status = copy_file(dst, src, mode); + if (!status) + return copy_times(dst, src); + return status; +} |