Merge branch 'jk/ewah-bounds-check'
[git] / copy.c
1 #include "cache.h"
2
3 int 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
18 static 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
31 int 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
61 int 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 }