From a16778a6243e271d501da95232cbe7c9ff58649b Mon Sep 17 00:00:00 2001 From: Joel Rosdahl Date: Fri, 22 May 2020 21:16:48 +0200 Subject: [PATCH] Copy directly from cache to destination file instead of via tmp file MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit ccache copies files to the cache via a temporary file which is then renamed into place. For simplicity reasons the same file copy function is used when copying files from the cache as well. This however makes ccache fail for very long destination filenames. Fix this by introducing a “via_tmp_file” parameter to copy_file, similar to how it works on master. Closes #593. --- src/ccache.c | 4 ++-- src/ccache.h | 3 ++- src/util.c | 54 ++++++++++++++++++++++++++++++++++++---------------- 3 files changed, 42 insertions(+), 19 deletions(-) diff --git a/src/ccache.c b/src/ccache.c index 54e8f21e0..7ad1f3b34 100644 --- a/src/ccache.c +++ b/src/ccache.c @@ -1237,7 +1237,7 @@ do_copy_or_move_file_to_cache(const char *source, const char *dest, bool copy) } } if (!do_link) { - int ret = copy_file(source, dest, compression_level); + int ret = copy_file(source, dest, compression_level, true); if (ret != 0) { cc_log("Failed to copy %s to %s: %s", source, dest, strerror(errno)); stats_update(STATS_ERROR); @@ -1307,7 +1307,7 @@ do_copy_or_link_file_from_cache(const char *source, const char *dest, bool copy) x_unlink(dest); ret = link(source, dest); } else { - ret = copy_file(source, dest, 0); + ret = copy_file(source, dest, 0, false); } if (ret == -1) { diff --git a/src/ccache.h b/src/ccache.h index 0d6be609a..e5524a6da 100644 --- a/src/ccache.h +++ b/src/ccache.h @@ -149,7 +149,8 @@ void fatal(const char *format, ...) ATTR_FORMAT(printf, 1, 2) ATTR_NORETURN; void warn(const char *format, ...) ATTR_FORMAT(printf, 1, 2); void copy_fd(int fd_in, int fd_out); -int copy_file(const char *src, const char *dest, int compress_level); +int copy_file(const char *src, const char *dest, int compress_level, + bool via_tmp_file); int move_file(const char *src, const char *dest, int compress_level); int move_uncompressed_file(const char *src, const char *dest, int compress_level); diff --git a/src/util.c b/src/util.c index 0fd3f0fe3..eff2eed02 100644 --- a/src/util.c +++ b/src/util.c @@ -315,18 +315,34 @@ get_umask(void) // whether dest will be compressed, and with which compression level. Returns 0 // on success and -1 on failure. On failure, errno represents the error. int -copy_file(const char *src, const char *dest, int compress_level) +copy_file(const char *src, + const char *dest, + int compress_level, + bool via_tmp_file) { int fd_out; + char *tmp_name = NULL; gzFile gz_in = NULL; gzFile gz_out = NULL; int saved_errno = 0; // Open destination file. - char *tmp_name = x_strdup(dest); - fd_out = create_tmp_fd(&tmp_name); - cc_log("Copying %s to %s via %s (%scompressed)", - src, dest, tmp_name, compress_level > 0 ? "" : "un"); + if (via_tmp_file) { + tmp_name = x_strdup(dest); + fd_out = create_tmp_fd(&tmp_name); + cc_log("Copying %s to %s via %s (%scompressed)", + src, dest, tmp_name, compress_level > 0 ? "" : "un"); + } else { + fd_out = open(dest, O_WRONLY | O_CREAT | O_BINARY, 0666); + if (fd_out == -1) { + saved_errno = errno; + close(fd_out); + errno = saved_errno; + return -1; + } + cc_log("Copying %s to %s (%scompressed)", + src, dest, compress_level > 0 ? "" : "un"); + } // Open source file. int fd_in = open(src, O_RDONLY | O_BINARY); @@ -410,8 +426,10 @@ copy_file(const char *src, const char *dest, int compress_level) gzclose(gz_out); } close(fd_out); - tmp_unlink(tmp_name); - free(tmp_name); + if (via_tmp_file) { + tmp_unlink(tmp_name); + free(tmp_name); + } return -1; } @@ -433,13 +451,15 @@ copy_file(const char *src, const char *dest, int compress_level) goto error; } - if (x_rename(tmp_name, dest) == -1) { - saved_errno = errno; - cc_log("rename error: %s", strerror(saved_errno)); - goto error; - } + if (via_tmp_file) { + if (x_rename(tmp_name, dest) == -1) { + saved_errno = errno; + cc_log("rename error: %s", strerror(saved_errno)); + goto error; + } - free(tmp_name); + free(tmp_name); + } return 0; @@ -453,8 +473,10 @@ error: if (fd_out != -1) { close(fd_out); } - tmp_unlink(tmp_name); - free(tmp_name); + if (via_tmp_file) { + tmp_unlink(tmp_name); + free(tmp_name); + } errno = saved_errno; return -1; } @@ -463,7 +485,7 @@ error: int move_file(const char *src, const char *dest, int compress_level) { - int ret = copy_file(src, dest, compress_level); + int ret = copy_file(src, dest, compress_level, true); if (ret != -1) { x_unlink(src); } -- 2.47.2