copy.con commit Merge branch 'jk/tighten-alloc' (2f66456)
   1#include "cache.h"
   2
   3int copy_fd(int ifd, int ofd)
   4{
   5        while (1) {
   6                char buffer[8192];
   7                ssize_t len = xread(ifd, buffer, sizeof(buffer));
   8                if (!len)
   9                        break;
  10                if (len < 0)
  11                        return COPY_READ_ERROR;
  12                if (write_in_full(ofd, buffer, len) < 0)
  13                        return COPY_WRITE_ERROR;
  14        }
  15        return 0;
  16}
  17
  18static int copy_times(const char *dst, const char *src)
  19{
  20        struct stat st;
  21        struct utimbuf times;
  22        if (stat(src, &st) < 0)
  23                return -1;
  24        times.actime = st.st_atime;
  25        times.modtime = st.st_mtime;
  26        if (utime(dst, &times) < 0)
  27                return -1;
  28        return 0;
  29}
  30
  31int copy_file(const char *dst, const char *src, int mode)
  32{
  33        int fdi, fdo, status;
  34
  35        mode = (mode & 0111) ? 0777 : 0666;
  36        if ((fdi = open(src, O_RDONLY)) < 0)
  37                return fdi;
  38        if ((fdo = open(dst, O_WRONLY | O_CREAT | O_EXCL, mode)) < 0) {
  39                close(fdi);
  40                return fdo;
  41        }
  42        status = copy_fd(fdi, fdo);
  43        switch (status) {
  44        case COPY_READ_ERROR:
  45                error_errno("copy-fd: read returned");
  46                break;
  47        case COPY_WRITE_ERROR:
  48                error_errno("copy-fd: write returned");
  49                break;
  50        }
  51        close(fdi);
  52        if (close(fdo) != 0)
  53                return error_errno("%s: close error", dst);
  54
  55        if (!status && adjust_shared_perm(dst))
  56                return -1;
  57
  58        return status;
  59}
  60
  61int copy_file_with_time(const char *dst, const char *src, int mode)
  62{
  63        int status = copy_file(dst, src, mode);
  64        if (!status)
  65                return copy_times(dst, src);
  66        return status;
  67}