1 #include "cache.h"
2 
copy_fd(int ifd,int ofd)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 
copy_times(const char * dst,const char * src)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 
copy_file(const char * dst,const char * src,int mode)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 
copy_file_with_time(const char * dst,const char * src,int mode)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 }
68