| 
					
				 | 
			
			
				@@ -1394,8 +1394,10 @@ size_t cmWriteToFileCallback(void* ptr, size_t size, size_t nmemb, void* data) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   int realsize = static_cast<int>(size * nmemb); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   cmsys::ofstream* fout = static_cast<cmsys::ofstream*>(data); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  const char* chPtr = static_cast<char*>(ptr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  fout->write(chPtr, realsize); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (fout) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const char* chPtr = static_cast<char*>(ptr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    fout->write(chPtr, realsize); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return realsize; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1551,15 +1553,14 @@ bool HandleDownloadCommand(std::vector<std::string> const& args, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #if !defined(CMAKE_BOOTSTRAP) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   auto i = args.begin(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (args.size() < 3) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    status.SetError("DOWNLOAD must be called with at least three arguments."); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (args.size() < 2) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    status.SetError("DOWNLOAD must be called with at least two arguments."); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   ++i; // Get rid of subcommand 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   std::string url = *i; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   ++i; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  std::string file = *i; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  ++i; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  std::string file; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   long timeout = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   long inactivity_timeout = 0; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1690,6 +1691,8 @@ bool HandleDownloadCommand(std::vector<std::string> const& args, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       curl_headers.push_back(*i); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } else if (file.empty()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      file = *i; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       // Do not return error for compatibility reason. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       std::string err = cmStrCat("Unexpected argument: ", *i); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1697,11 +1700,18 @@ bool HandleDownloadCommand(std::vector<std::string> const& args, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ++i; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // Can't calculate hash if we don't save the file. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // TODO Incrementally calculate hash in the write callback as the file is 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // being downloaded so this check can be relaxed. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (file.empty() && hash) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    status.SetError("DOWNLOAD cannot calculate hash if file is not saved."); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // If file exists already, and caller specified an expected md5 or sha, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // and the existing file already has the expected hash, then simply 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // return. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (cmSystemTools::FileExists(file) && hash.get()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (!file.empty() && cmSystemTools::FileExists(file) && hash.get()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     std::string msg; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     std::string actualHash = hash->HashFile(file); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (actualHash == expectedHash) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1716,20 +1726,26 @@ bool HandleDownloadCommand(std::vector<std::string> const& args, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // Make sure parent directory exists so we can write to the file 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // as we receive downloaded bits from curl... 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  std::string dir = cmSystemTools::GetFilenamePath(file); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (!dir.empty() && !cmSystemTools::FileExists(dir) && 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      !cmSystemTools::MakeDirectory(dir)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    std::string errstring = "DOWNLOAD error: cannot create directory '" + dir + 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      "' - Specify file by full path name and verify that you " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      "have directory creation and file write privileges."; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    status.SetError(errstring); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (!file.empty()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    std::string dir = cmSystemTools::GetFilenamePath(file); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (!dir.empty() && !cmSystemTools::FileExists(dir) && 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        !cmSystemTools::MakeDirectory(dir)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      std::string errstring = "DOWNLOAD error: cannot create directory '" + 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        dir + 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        "' - Specify file by full path name and verify that you " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        "have directory creation and file write privileges."; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      status.SetError(errstring); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  cmsys::ofstream fout(file.c_str(), std::ios::binary); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (!fout) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    status.SetError("DOWNLOAD cannot open file for write."); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  cmsys::ofstream fout; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (!file.empty()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    fout.open(file.c_str(), std::ios::binary); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (!fout) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      status.SetError("DOWNLOAD cannot open file for write."); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #  if defined(_WIN32) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1791,7 +1807,8 @@ bool HandleDownloadCommand(std::vector<std::string> const& args, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   cmFileCommandVectorOfChar chunkDebug; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  res = ::curl_easy_setopt(curl, CURLOPT_WRITEDATA, &fout); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  res = ::curl_easy_setopt(curl, CURLOPT_WRITEDATA, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                           file.empty() ? nullptr : &fout); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   check_curl_result(res, "DOWNLOAD cannot set write data: "); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   res = ::curl_easy_setopt(curl, CURLOPT_DEBUGDATA, &chunkDebug); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1865,8 +1882,10 @@ bool HandleDownloadCommand(std::vector<std::string> const& args, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // Explicitly flush/close so we can measure the md5 accurately. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  fout.flush(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  fout.close(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (!file.empty()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    fout.flush(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    fout.close(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // Verify MD5 sum if requested: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // 
			 |