From: Joel Rosdahl Date: Fri, 22 May 2020 19:16:48 +0000 (+0200) Subject: Copy directly from cache to destination file instead of via tmp file X-Git-Tag: v3.7.10~9 X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=a16778a6243e271d501da95232cbe7c9ff58649b;p=thirdparty%2Fccache.git Copy directly from cache to destination file instead of via tmp file 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. --- 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); }