Mercurial > dovecot > core-2.2
changeset 4406:18c7c5215b53 HEAD
Added file_copy().
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sat, 17 Jun 2006 19:24:55 +0300 |
parents | fe17f63521ea |
children | 2e4857a2b858 |
files | src/lib/Makefile.am src/lib/file-copy.c src/lib/file-copy.h |
diffstat | 3 files changed, 91 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib/Makefile.am Sat Jun 17 19:01:14 2006 +0300 +++ b/src/lib/Makefile.am Sat Jun 17 19:24:55 2006 +0300 @@ -13,6 +13,7 @@ fd-set-nonblock.c \ fdpass.c \ file-cache.c \ + file-copy.c \ file-dotlock.c \ file-lock.c \ file-set-size.c \ @@ -98,6 +99,7 @@ fd-set-nonblock.h \ fdpass.h \ file-cache.h \ + file-copy.h \ file-dotlock.h \ file-lock.h \ file-set-size.h \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/file-copy.c Sat Jun 17 19:24:55 2006 +0300 @@ -0,0 +1,77 @@ +/* Copyright (c) 2006 Timo Sirainen */ + +#include "lib.h" +#include "istream.h" +#include "ostream.h" +#include "file-copy.h" + +#include <stdio.h> +#include <unistd.h> +#include <fcntl.h> + +int file_copy(const char *srcpath, const char *destpath, bool try_hardlink) +{ + const char *tmppath; + struct istream *input; + struct ostream *output; + int fd_in, fd_out; + off_t ret; + + if (try_hardlink) { + /* see if hardlinking works */ + if (link(srcpath, destpath) == 0 || errno == EEXIST) + return 1; + if (errno == ENOENT) + return 0; + if (!ECANTLINK(errno)) { + i_error("link(%s, %s) failed: %m", srcpath, destpath); + return -1; + } + + /* fallback to manual copying */ + } + + fd_in = open(srcpath, O_RDONLY); + if (fd_in == -1) { + if (errno == ENOENT) + return 0; + i_error("open(%s) failed: %m", srcpath); + return -1; + } + + t_push(); + tmppath = t_strconcat(destpath, ".tmp", NULL); + fd_out = open(tmppath, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd_out == -1) { + i_error("open(%s, O_CREAT) failed: %m", tmppath); + (void)close(fd_in); + t_pop(); + return -1; + } + input = i_stream_create_file(fd_in, default_pool, 0, FALSE); + output = o_stream_create_file(fd_out, default_pool, 0, FALSE); + + while ((ret = o_stream_send_istream(output, input)) > 0) ; + + i_stream_destroy(&input); + o_stream_destroy(&output); + + if (close(fd_in) < 0) { + i_error("close(%s) failed: %m", srcpath); + ret = -1; + } + if (close(fd_out) < 0) { + i_error("close(%s) failed: %m", tmppath); + ret = -1; + } + if (ret == 0) { + if (rename(tmppath, destpath) < 0) { + i_error("rename(%s, %s) failed: %m", tmppath, destpath); + ret = -1; + } + } + if (ret < 0) + (void)unlink(tmppath); + t_pop(); + return ret < 0 ? -1 : 1; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/file-copy.h Sat Jun 17 19:24:55 2006 +0300 @@ -0,0 +1,12 @@ +#ifndef __FILE_COPY_H +#define __FILE_COPY_H + +/* Copy file atomically. First try hardlinking, then fallback to creating + a temporary file (destpath.tmp) and rename()ing it over srcpath. + If the destination file already exists, it may or may not be overwritten, + so that shouldn't be relied on. + + Returns -1 = error, 0 = source file not found, 1 = ok */ +int file_copy(const char *srcpath, const char *destpath, bool try_hardlink); + +#endif