copy.con commit push: Provide situational hints for non-fast-forward errors (f25950f)
   1#include "cache.h"
   2
   3int copy_fd(int ifd, int ofd)
   4{
   5        while (1) {
   6                char buffer[8192];
   7                char *buf = buffer;
   8                ssize_t len = xread(ifd, buffer, sizeof(buffer));
   9                if (!len)
  10                        break;
  11                if (len < 0) {
  12                        int read_error = errno;
  13                        close(ifd);
  14                        return error("copy-fd: read returned %s",
  15                                     strerror(read_error));
  16                }
  17                while (len) {
  18                        int written = xwrite(ofd, buf, len);
  19                        if (written > 0) {
  20                                buf += written;
  21                                len -= written;
  22                        }
  23                        else if (!written) {
  24                                close(ifd);
  25                                return error("copy-fd: write returned 0");
  26                        } else {
  27                                int write_error = errno;
  28                                close(ifd);
  29                                return error("copy-fd: write returned %s",
  30                                             strerror(write_error));
  31                        }
  32                }
  33        }
  34        close(ifd);
  35        return 0;
  36}
  37
  38static 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, &times) < 0)
  47                return -1;
  48        return 0;
  49}
  50
  51int 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)
  64                return error("%s: close error: %s", dst, strerror(errno));
  65
  66        if (!status && adjust_shared_perm(dst))
  67                return -1;
  68
  69        return status;
  70}
  71
  72int 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}