From d7f4551f6f4aa782ce8a1ae510e9eed23b8b588f Mon Sep 17 00:00:00 2001 From: David Anderson Date: Thu, 14 Jul 2016 14:56:31 -0700 Subject: [PATCH] client: fix bug where concurrent async file operations use same temp file For situations where there are multiple big input or app_version files, this could lead to MD5 errors and/or garbled file contents. --- client/async_file.cpp | 26 ++++++++++++++++++++------ doc/index.php | 1 + 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/client/async_file.cpp b/client/async_file.cpp index b19660e862..fb19955288 100644 --- a/client/async_file.cpp +++ b/client/async_file.cpp @@ -15,6 +15,12 @@ // You should have received a copy of the GNU Lesser General Public License // along with BOINC. If not, see . +// logic for "asynchronous" file copy and unzip/verify operations. +// "asynchronous" means that the the operations are done in 64KB chunks +// in the client's polling loop, +// so that the client continues to respond to GUI RPCs +// and the manager won't freeze. + #ifdef _WIN32 #include "boinc_win.h" #else @@ -46,6 +52,8 @@ vector async_copies; #define BUFSIZE 64*1024 +// set up an async copy operation. +// int ASYNC_COPY::init( ACTIVE_TASK* _atp, FILE_INFO* _fip, const char* from_path, const char* _to_path @@ -53,6 +61,7 @@ int ASYNC_COPY::init( atp = _atp; fip = _fip; safe_strcpy(to_path, _to_path); + char to_dir[MAXPATHLEN]; if (log_flags.async_file_debug) { msg_printf(atp->wup->project, MSG_INFO, @@ -61,10 +70,14 @@ int ASYNC_COPY::init( } in = boinc_fopen(from_path, "rb"); if (!in) return ERR_FOPEN; - safe_strcpy(temp_path, to_path); - char* p = strrchr(temp_path, '/'); + + // Copy the file to a temp file in the target directory. + // It will be renamed later. + // + safe_strcpy(to_dir, to_path); + char* p = strrchr(to_dir, '/'); *(p+1) = 0; - strlcat(temp_path, "copy_temp", sizeof(temp_path)); + safe_strcpy(temp_path, tempnam(to_dir, "copy_temp_")); #ifdef _WIN32 boinc_allocate_file(temp_path, fip->nbytes); #endif @@ -176,11 +189,12 @@ int ASYNC_VERIFY::init(FILE_INFO* _fip) { ); } if (fip->download_gzipped) { + char out_dir[MAXPATHLEN]; safe_strcpy(outpath, inpath); - safe_strcpy(temp_path, outpath); - char* p = strrchr(temp_path, '/'); + safe_strcpy(out_dir, outpath); + char* p = strrchr(out_dir, '/'); *(p+1) = 0; - strlcat(temp_path, "verify_temp", sizeof(temp_path)); + safe_strcpy(temp_path, tempnam(out_dir, "verify_temp_")); #ifdef _WIN32 boinc_allocate_file(temp_path, fip->nbytes); #endif diff --git a/doc/index.php b/doc/index.php index e6d940a858..efb904dea1 100644 --- a/doc/index.php +++ b/doc/index.php @@ -190,6 +190,7 @@ function show_other() {
  • ".tra("Development process")."
  • ".tra("Volunteer")."
  • ".tra("APIs")." +
  • BOINC and Docker