1
/* Copyright (c) 2006 Timo Sirainen */
12
static int file_copy_to_tmp(const char *srcpath, const char *tmppath,
15
struct istream *input;
16
struct ostream *output;
21
/* see if hardlinking works */
22
if (link(srcpath, tmppath) == 0)
24
if (errno == EEXIST) {
25
if (unlink(tmppath) < 0 && errno != ENOENT) {
26
i_error("unlink(%s) failed: %m", tmppath);
29
if (link(srcpath, tmppath) == 0)
34
if (!ECANTLINK(errno)) {
35
i_error("link(%s, %s) failed: %m", srcpath, tmppath);
39
/* fallback to manual copying */
42
fd_in = open(srcpath, O_RDONLY);
46
i_error("open(%s) failed: %m", srcpath);
50
fd_out = open(tmppath, O_WRONLY | O_CREAT | O_TRUNC, 0644);
52
i_error("open(%s, O_CREAT) failed: %m", tmppath);
56
input = i_stream_create_file(fd_in, default_pool, 0, FALSE);
57
output = o_stream_create_file(fd_out, default_pool, 0, FALSE);
59
while ((ret = o_stream_send_istream(output, input)) > 0) ;
61
i_stream_destroy(&input);
62
o_stream_destroy(&output);
64
if (close(fd_in) < 0) {
65
i_error("close(%s) failed: %m", srcpath);
68
if (close(fd_out) < 0) {
69
i_error("close(%s) failed: %m", tmppath);
72
return ret < 0 ? -1 : 1;
75
int file_copy(const char *srcpath, const char *destpath, bool try_hardlink)
81
tmppath = t_strconcat(destpath, ".tmp", NULL);
83
ret = file_copy_to_tmp(srcpath, tmppath, try_hardlink);
85
if (rename(tmppath, destpath) < 0) {
86
i_error("rename(%s, %s) failed: %m", tmppath, destpath);
91
(void)unlink(tmppath);