diff options
Diffstat (limited to 'Source/cmFileCommand.cxx')
-rw-r--r-- | Source/cmFileCommand.cxx | 453 |
1 files changed, 376 insertions, 77 deletions
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 1325cec..579e715 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -20,7 +20,8 @@ #include "cmTimestamp.h" #if defined(CMAKE_BUILD_WITH_CMAKE) -#include "cm_curl.h" +#include "cmCurl.h" +#include "cmFileLockResult.h" #endif #undef GetCurrentDirectory @@ -33,6 +34,7 @@ #include <cmsys/Glob.hxx> #include <cmsys/RegularExpression.hxx> #include <cmsys/FStream.hxx> +#include <cmsys/Encoding.hxx> // Table of permissions flags. #if defined(_WIN32) && !defined(__CYGWIN__) @@ -61,6 +63,35 @@ static mode_t mode_setuid = S_ISUID; static mode_t mode_setgid = S_ISGID; #endif +#if defined(WIN32) && defined(CMAKE_ENCODING_UTF8) +// libcurl doesn't support file:// urls for unicode filenames on Windows. +// Convert string from UTF-8 to ACP if this is a file:// URL. +static std::string fix_file_url_windows(const std::string& url) +{ + std::string ret = url; + if(strncmp(url.c_str(), "file://", 7) == 0) + { + cmsys_stl::wstring wurl = cmsys::Encoding::ToWide(url); + if(!wurl.empty()) + { + int mblen = WideCharToMultiByte(CP_ACP, 0, wurl.c_str(), -1, + NULL, 0, NULL, NULL); + if(mblen > 0) + { + std::vector<char> chars(mblen); + mblen = WideCharToMultiByte(CP_ACP, 0, wurl.c_str(), -1, + &chars[0], mblen, NULL, NULL); + if(mblen > 0) + { + ret = &chars[0]; + } + } + } + } + return ret; +} +#endif + // cmLibraryCommand bool cmFileCommand ::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &) @@ -172,6 +203,10 @@ bool cmFileCommand { return this->HandleGenerateCommand(args); } + else if ( subCommand == "LOCK" ) + { + return this->HandleLockCommand(args); + } std::string e = "does not recognize sub-command "+subCommand; this->SetError(e); @@ -220,8 +255,6 @@ bool cmFileCommand::HandleWriteCommand(std::vector<std::string> const& args, cmSystemTools::SetPermissions(fileName.c_str(), #if defined( _MSC_VER ) || defined( __MINGW32__ ) mode | S_IWRITE -#elif defined( __BORLANDC__ ) - mode | S_IWUSR #else mode | S_IWUSR | S_IWGRP #endif @@ -303,14 +336,14 @@ bool cmFileCommand::HandleReadCommand(std::vector<std::string> const& args) // is there a limit? long sizeLimit = -1; - if (limitArg.GetString().size() > 0) + if (!limitArg.GetString().empty()) { sizeLimit = atoi(limitArg.GetCString()); } // is there an offset? long offset = 0; - if (offsetArg.GetString().size() > 0) + if (!offsetArg.GetString().empty()) { offset = atoi(offsetArg.GetCString()); } @@ -371,7 +404,7 @@ bool cmFileCommand::HandleHashCommand(std::vector<std::string> const& args) #if defined(CMAKE_BUILD_WITH_CMAKE) if(args.size() != 3) { - cmOStringStream e; + std::ostringstream e; e << args[0] << " requires a file name and output variable"; this->SetError(e.str()); return false; @@ -386,14 +419,14 @@ bool cmFileCommand::HandleHashCommand(std::vector<std::string> const& args) this->Makefile->AddDefinition(args[2], out.c_str()); return true; } - cmOStringStream e; + std::ostringstream e; e << args[0] << " failed to read file \"" << args[1] << "\": " << cmSystemTools::GetLastSystemError(); this->SetError(e.str()); } return false; #else - cmOStringStream e; + std::ostringstream e; e << args[0] << " not available during bootstrap"; this->SetError(e.str().c_str()); return false; @@ -439,7 +472,13 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args) bool have_regex = false; bool newline_consume = false; bool hex_conversion_enabled = true; - bool utf8_encoding = false; + enum { encoding_none = cmsys::FStream::BOM_None, + encoding_utf8 = cmsys::FStream::BOM_UTF8, + encoding_utf16le = cmsys::FStream::BOM_UTF16LE, + encoding_utf16be = cmsys::FStream::BOM_UTF16BE, + encoding_utf32le = cmsys::FStream::BOM_UTF32LE, + encoding_utf32be = cmsys::FStream::BOM_UTF32BE}; + int encoding = encoding_none; int arg_mode = arg_none; for(unsigned int i=3; i < args.size(); ++i) { @@ -486,7 +525,7 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args) if(sscanf(args[i].c_str(), "%d", &limit_input) != 1 || limit_input < 0) { - cmOStringStream e; + std::ostringstream e; e << "STRINGS option LIMIT_INPUT value \"" << args[i] << "\" is not an unsigned integer."; this->SetError(e.str()); @@ -499,7 +538,7 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args) if(sscanf(args[i].c_str(), "%d", &limit_output) != 1 || limit_output < 0) { - cmOStringStream e; + std::ostringstream e; e << "STRINGS option LIMIT_OUTPUT value \"" << args[i] << "\" is not an unsigned integer."; this->SetError(e.str()); @@ -512,7 +551,7 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args) int count; if(sscanf(args[i].c_str(), "%d", &count) != 1 || count < 0) { - cmOStringStream e; + std::ostringstream e; e << "STRINGS option LIMIT_COUNT value \"" << args[i] << "\" is not an unsigned integer."; this->SetError(e.str()); @@ -526,7 +565,7 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args) int len; if(sscanf(args[i].c_str(), "%d", &len) != 1 || len < 0) { - cmOStringStream e; + std::ostringstream e; e << "STRINGS option LENGTH_MINIMUM value \"" << args[i] << "\" is not an unsigned integer."; this->SetError(e.str()); @@ -540,7 +579,7 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args) int len; if(sscanf(args[i].c_str(), "%d", &len) != 1 || len < 0) { - cmOStringStream e; + std::ostringstream e; e << "STRINGS option LENGTH_MAXIMUM value \"" << args[i] << "\" is not an unsigned integer."; this->SetError(e.str()); @@ -553,7 +592,7 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args) { if(!regex.compile(args[i].c_str())) { - cmOStringStream e; + std::ostringstream e; e << "STRINGS option REGEX value \"" << args[i] << "\" could not be compiled."; this->SetError(e.str()); @@ -566,11 +605,27 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args) { if(args[i] == "UTF-8") { - utf8_encoding = true; + encoding = encoding_utf8; + } + else if(args[i] == "UTF-16LE") + { + encoding = encoding_utf16le; + } + else if(args[i] == "UTF-16BE") + { + encoding = encoding_utf16be; + } + else if(args[i] == "UTF-32LE") + { + encoding = encoding_utf32le; + } + else if(args[i] == "UTF-32BE") + { + encoding = encoding_utf32be; } else { - cmOStringStream e; + std::ostringstream e; e << "STRINGS option ENCODING \"" << args[i] << "\" not recognized."; this->SetError(e.str()); @@ -580,7 +635,7 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args) } else { - cmOStringStream e; + std::ostringstream e; e << "STRINGS given unknown argument \"" << args[i] << "\""; this->SetError(e.str()); @@ -608,12 +663,29 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args) #endif if(!fin) { - cmOStringStream e; + std::ostringstream e; e << "STRINGS file \"" << fileName << "\" cannot be read."; this->SetError(e.str()); return false; } + //If BOM is found and encoding was not specified, use the BOM + int bom_found = cmsys::FStream::ReadBOM(fin); + if(encoding == encoding_none && bom_found != cmsys::FStream::BOM_None) + { + encoding = bom_found; + } + + unsigned int bytes_rem = 0; + if(encoding == encoding_utf16le || encoding == encoding_utf16be) + { + bytes_rem = 1; + } + if(encoding == encoding_utf32le || encoding == encoding_utf32be) + { + bytes_rem = 3; + } + // Parse strings out of the file. int output_size = 0; std::vector<std::string> strings; @@ -625,6 +697,25 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args) std::string current_str; int c = fin.get(); + for(unsigned int i=0; i<bytes_rem; ++i) + { + int c1 = fin.get(); + if(!fin) + { + fin.putback(static_cast<char>(c1)); + break; + } + c = (c << 8) | c1; + } + if(encoding == encoding_utf16le) + { + c = ((c & 0xFF) << 8) | ((c & 0xFF00) >> 8); + } + else if(encoding == encoding_utf32le) + { + c = (((c & 0xFF) << 24) | ((c & 0xFF00) << 8) | + ((c & 0xFF0000) >> 8) | ((c & 0xFF000000) >> 24)); + } if(c == '\r') { @@ -640,7 +731,7 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args) // c is guaranteed to fit in char by the above if... current_str += static_cast<char>(c); } - else if(utf8_encoding) + else if(encoding == encoding_utf8) { // Check for UTF-8 encoded string (up to 4 octets) static const unsigned char utf8_check_table[3][2] = @@ -712,7 +803,7 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args) // A non-string character has been found. Check if the current // string matches the requirements. We require that the length // be at least one no matter what the user specified. - if(s.length() >= minlen && s.length() >= 1 && + if(s.length() >= minlen && !s.empty() && (!have_regex || regex.find(s.c_str()))) { output_size += static_cast<int>(s.size()) + 1; @@ -866,7 +957,7 @@ bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args, { std::string expr = this->Makefile->GetCurrentDirectory(); // Handle script mode - if ( expr.size() > 0 ) + if (!expr.empty()) { expr += "/" + *i; g.FindFiles(expr); @@ -1004,7 +1095,7 @@ cmFileCommand::HandleDifferentCommand(std::vector<std::string> const& args) } else { - cmOStringStream e; + std::ostringstream e; e << "DIFFERENT given unknown argument " << args[i]; this->SetError(e.str()); return false; @@ -1119,7 +1210,7 @@ protected: { if(permissions && !cmSystemTools::SetPermissions(toFile, permissions)) { - cmOStringStream e; + std::ostringstream e; e << this->Name << " cannot set permissions on \"" << toFile << "\""; this->FileCommand->SetError(e.str()); return false; @@ -1143,7 +1234,7 @@ protected: else if(arg == "SETGID") { permissions |= mode_setgid; } else { - cmOStringStream e; + std::ostringstream e; e << this->Name << " given invalid permission \"" << arg << "\"."; this->FileCommand->SetError(e.str()); return false; @@ -1170,7 +1261,7 @@ protected: virtual bool ReportMissing(const char* fromFile) { // The input file does not exist and installation is not optional. - cmOStringStream e; + std::ostringstream e; e << this->Name << " cannot find \"" << fromFile << "\"."; this->FileCommand->SetError(e.str()); return false; @@ -1203,14 +1294,14 @@ protected: void NotBeforeMatch(std::string const& arg) { - cmOStringStream e; + std::ostringstream e; e << "option " << arg << " may not appear before PATTERN or REGEX."; this->FileCommand->SetError(e.str()); this->Doing = DoingError; } void NotAfterMatch(std::string const& arg) { - cmOStringStream e; + std::ostringstream e; e << "option " << arg << " may not appear after PATTERN or REGEX."; this->FileCommand->SetError(e.str()); this->Doing = DoingError; @@ -1248,7 +1339,7 @@ bool cmFileCopier::Parse(std::vector<std::string> const& args) if(!this->CheckKeyword(args[i]) && !this->CheckValue(args[i])) { - cmOStringStream e; + std::ostringstream e; e << "called with unknown argument \"" << args[i] << "\"."; this->FileCommand->SetError(e.str()); return false; @@ -1264,7 +1355,7 @@ bool cmFileCopier::Parse(std::vector<std::string> const& args) // Require a destination. if(this->Destination.empty()) { - cmOStringStream e; + std::ostringstream e; e << this->Name << " given no DESTINATION"; this->FileCommand->SetError(e.str()); return false; @@ -1444,7 +1535,7 @@ bool cmFileCopier::CheckValue(std::string const& arg) } else { - cmOStringStream e; + std::ostringstream e; e << "could not compile PATTERN \"" << arg << "\"."; this->FileCommand->SetError(e.str()); this->Doing = DoingError; @@ -1460,7 +1551,7 @@ bool cmFileCopier::CheckValue(std::string const& arg) } else { - cmOStringStream e; + std::ostringstream e; e << "could not compile REGEX \"" << arg << "\"."; this->FileCommand->SetError(e.str()); this->Doing = DoingError; @@ -1504,7 +1595,7 @@ bool cmFileCopier::Run(std::vector<std::string> const& args) { // Split the input file into its directory and name components. std::vector<std::string> fromPathComponents; - cmSystemTools::SplitPath(files[i].c_str(), fromPathComponents); + cmSystemTools::SplitPath(files[i], fromPathComponents); std::string fromName = *(fromPathComponents.end()-1); std::string fromDir = cmSystemTools::JoinPath(fromPathComponents.begin(), fromPathComponents.end()-1); @@ -1540,7 +1631,7 @@ bool cmFileCopier::Install(const char* fromFile, const char* toFile) { if(!*fromFile) { - cmOStringStream e; + std::ostringstream e; e << "INSTALL encountered an empty string input file name."; this->FileCommand->SetError(e.str()); return false; @@ -1581,7 +1672,7 @@ bool cmFileCopier::InstallSymlink(const char* fromFile, const char* toFile) std::string symlinkTarget; if(!cmSystemTools::ReadSymlink(fromFile, symlinkTarget)) { - cmOStringStream e; + std::ostringstream e; e << this->Name << " cannot read symlink \"" << fromFile << "\" to duplicate at \"" << toFile << "\"."; this->FileCommand->SetError(e.str()); @@ -1612,9 +1703,9 @@ bool cmFileCopier::InstallSymlink(const char* fromFile, const char* toFile) cmSystemTools::RemoveFile(toFile); // Create the symlink. - if(!cmSystemTools::CreateSymlink(symlinkTarget.c_str(), toFile)) + if(!cmSystemTools::CreateSymlink(symlinkTarget, toFile)) { - cmOStringStream e; + std::ostringstream e; e << this->Name << " cannot duplicate symlink \"" << fromFile << "\" at \"" << toFile << "\"."; this->FileCommand->SetError(e.str()); @@ -1646,7 +1737,7 @@ bool cmFileCopier::InstallFile(const char* fromFile, const char* toFile, // Copy the file. if(copy && !cmSystemTools::CopyAFile(fromFile, toFile, true)) { - cmOStringStream e; + std::ostringstream e; e << this->Name << " cannot copy file \"" << fromFile << "\" to \"" << toFile << "\"."; this->FileCommand->SetError(e.str()); @@ -1665,7 +1756,7 @@ bool cmFileCopier::InstallFile(const char* fromFile, const char* toFile, } if (!cmSystemTools::CopyFileTime(fromFile, toFile)) { - cmOStringStream e; + std::ostringstream e; e << this->Name << " cannot set modification time on \"" << toFile << "\""; this->FileCommand->SetError(e.str()); @@ -1697,7 +1788,7 @@ bool cmFileCopier::InstallDirectory(const char* source, // Make sure the destination directory exists. if(!cmSystemTools::MakeDirectory(destination)) { - cmOStringStream e; + std::ostringstream e; e << this->Name << " cannot make directory \"" << destination << "\": " << cmSystemTools::GetLastSystemError(); this->FileCommand->SetError(e.str()); @@ -2042,7 +2133,7 @@ bool cmFileInstaller::CheckKeyword(std::string const& arg) else if(arg == "COMPONENTS" || arg == "CONFIGURATIONS" || arg == "PROPERTIES") { - cmOStringStream e; + std::ostringstream e; e << "INSTALL called with old-style " << arg << " argument. " << "This script was generated with an older version of CMake. " << "Re-run this cmake version on your build tree."; @@ -2110,7 +2201,7 @@ bool cmFileInstaller } else { - cmOStringStream e; + std::ostringstream e; e << "Option TYPE given unknown value \"" << stype << "\"."; this->FileCommand->SetError(e.str()); return false; @@ -2203,7 +2294,7 @@ bool cmFileInstaller::HandleInstallDestination() return false; } } - if ( !cmSystemTools::FileIsDirectory(destination.c_str()) ) + if ( !cmSystemTools::FileIsDirectory(destination) ) { std::string errstring = "INSTALL destination: " + destination + " is not a directory."; @@ -2255,7 +2346,7 @@ cmFileCommand::HandleRPathChangeCommand(std::vector<std::string> const& args) } else { - cmOStringStream e; + std::ostringstream e; e << "RPATH_CHANGE given unknown argument " << args[i]; this->SetError(e.str()); return false; @@ -2278,7 +2369,7 @@ cmFileCommand::HandleRPathChangeCommand(std::vector<std::string> const& args) } if(!cmSystemTools::FileExists(file, true)) { - cmOStringStream e; + std::ostringstream e; e << "RPATH_CHANGE given FILE \"" << file << "\" that does not exist."; this->SetError(e.str()); return false; @@ -2290,7 +2381,7 @@ cmFileCommand::HandleRPathChangeCommand(std::vector<std::string> const& args) bool changed; if(!cmSystemTools::ChangeRPath(file, oldRPath, newRPath, &emsg, &changed)) { - cmOStringStream e; + std::ostringstream e; e << "RPATH_CHANGE could not write new RPATH:\n" << " " << newRPath << "\n" << "to the file:\n" @@ -2340,7 +2431,7 @@ cmFileCommand::HandleRPathRemoveCommand(std::vector<std::string> const& args) } else { - cmOStringStream e; + std::ostringstream e; e << "RPATH_REMOVE given unknown argument " << args[i]; this->SetError(e.str()); return false; @@ -2353,7 +2444,7 @@ cmFileCommand::HandleRPathRemoveCommand(std::vector<std::string> const& args) } if(!cmSystemTools::FileExists(file, true)) { - cmOStringStream e; + std::ostringstream e; e << "RPATH_REMOVE given FILE \"" << file << "\" that does not exist."; this->SetError(e.str()); return false; @@ -2365,7 +2456,7 @@ cmFileCommand::HandleRPathRemoveCommand(std::vector<std::string> const& args) bool removed; if(!cmSystemTools::RemoveRPath(file, &emsg, &removed)) { - cmOStringStream e; + std::ostringstream e; e << "RPATH_REMOVE could not remove RPATH from file:\n" << " " << file << "\n" << emsg; @@ -2421,7 +2512,7 @@ cmFileCommand::HandleRPathCheckCommand(std::vector<std::string> const& args) } else { - cmOStringStream e; + std::ostringstream e; e << "RPATH_CHECK given unknown argument " << args[i]; this->SetError(e.str()); return false; @@ -2522,7 +2613,7 @@ bool cmFileCommand::HandleRename(std::vector<std::string> const& args) if(!cmSystemTools::RenameFile(oldname.c_str(), newname.c_str())) { std::string err = cmSystemTools::GetLastSystemError(); - cmOStringStream e; + std::ostringstream e; e << "RENAME failed to rename\n" << " " << oldname << "\n" << "to\n" @@ -2553,14 +2644,14 @@ bool cmFileCommand::HandleRemove(std::vector<std::string> const& args, fileName += "/" + *i; } - if(cmSystemTools::FileIsDirectory(fileName.c_str()) && - !cmSystemTools::FileIsSymlink(fileName.c_str()) && recurse) + if(cmSystemTools::FileIsDirectory(fileName) && + !cmSystemTools::FileIsSymlink(fileName) && recurse) { - cmSystemTools::RemoveADirectory(fileName.c_str()); + cmSystemTools::RemoveADirectory(fileName); } else { - cmSystemTools::RemoveFile(fileName.c_str()); + cmSystemTools::RemoveFile(fileName); } } return true; @@ -2584,7 +2675,7 @@ bool cmFileCommand::HandleCMakePathCommand(std::vector<std::string> #else char pathSep = ':'; #endif - std::vector<cmsys::String> path = cmSystemTools::SplitString(i->c_str(), + std::vector<cmsys::String> path = cmSystemTools::SplitString(*i, pathSep); i++; const char* var = i->c_str(); @@ -2689,7 +2780,7 @@ namespace { if (updated) { - cmOStringStream oss; + std::ostringstream oss; oss << "[" << this->Text << " " << this->CurrentPercentage << "% complete]"; status = oss.str(); @@ -2959,9 +3050,9 @@ cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) msg = "returning early; file already exists with expected "; msg += hashMatchMSG; msg += "\""; - if(statusVar.size()) + if(!statusVar.empty()) { - cmOStringStream result; + std::ostringstream result; result << (int)0 << ";\"" << msg; this->Makefile->AddDefinition(statusVar, result.str().c_str()); @@ -2990,6 +3081,10 @@ cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) return false; } +#if defined(WIN32) && defined(CMAKE_ENCODING_UTF8) + url = fix_file_url_windows(url); +#endif + ::CURL *curl; ::curl_global_init(CURL_GLOBAL_DEFAULT); curl = ::curl_easy_init(); @@ -3031,10 +3126,11 @@ cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) } // check to see if a CAINFO file has been specified // command arg comes first - if(cainfo && *cainfo) + std::string const& cainfo_err = cmCurlSetCAInfo(curl, cainfo); + if (!cainfo_err.empty()) { - res = ::curl_easy_setopt(curl, CURLOPT_CAINFO, cainfo); - check_curl_result(res, "Unable to set TLS/SSL Verify CAINFO: "); + this->SetError(cainfo_err); + return false; } cmFileCommandVectorOfChar chunkDebug; @@ -3048,7 +3144,7 @@ cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) res = ::curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); check_curl_result(res, "DOWNLOAD cannot set follow-redirect option: "); - if(verboseLog.size()) + if(!verboseLog.empty()) { res = ::curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); check_curl_result(res, "DOWNLOAD cannot set verbose: "); @@ -3094,9 +3190,9 @@ cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) g_curl.release(); ::curl_easy_cleanup(curl); - if(statusVar.size()) + if(!statusVar.empty()) { - cmOStringStream result; + std::ostringstream result; result << (int)res << ";\"" << ::curl_easy_strerror(res) << "\""; this->Makefile->AddDefinition(statusVar, result.str().c_str()); @@ -3114,7 +3210,7 @@ cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) if (hash.get()) { std::string actualHash = hash->HashFile(file); - if (actualHash.size() == 0) + if (actualHash.empty()) { this->SetError("DOWNLOAD cannot compute hash on downloaded file"); return false; @@ -3122,7 +3218,7 @@ cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) if (expectedHash != actualHash) { - cmOStringStream oss; + std::ostringstream oss; oss << "DOWNLOAD HASH mismatch" << std::endl << " for file: [" << file << "]" << std::endl << " expected hash: [" << expectedHash << "]" << std::endl @@ -3135,14 +3231,14 @@ cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) } } - if(chunkDebug.size()) + if(!chunkDebug.empty()) { chunkDebug.push_back(0); if(CURLE_OPERATION_TIMEOUTED == res) { std::string output = &*chunkDebug.begin(); - if(verboseLog.size()) + if(!verboseLog.empty()) { this->Makefile->AddDefinition(verboseLog, &*chunkDebug.begin()); @@ -3241,7 +3337,7 @@ cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args) // Open file for reading: // - FILE *fin = cmsys::SystemTools::Fopen(filename.c_str(), "rb"); + FILE *fin = cmsys::SystemTools::Fopen(filename, "rb"); if(!fin) { std::string errStr = "UPLOAD cannot open file '"; @@ -3250,7 +3346,11 @@ cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args) return false; } - unsigned long file_size = cmsys::SystemTools::FileLength(filename.c_str()); + unsigned long file_size = cmsys::SystemTools::FileLength(filename); + +#if defined(WIN32) && defined(CMAKE_ENCODING_UTF8) + url = fix_file_url_windows(url); +#endif ::CURL *curl; ::curl_global_init(CURL_GLOBAL_DEFAULT); @@ -3294,7 +3394,7 @@ cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args) res = ::curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); check_curl_result(res, "UPLOAD cannot set follow-redirect option: "); - if(logVar.size()) + if(!logVar.empty()) { res = ::curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); check_curl_result(res, "UPLOAD cannot set verbose: "); @@ -3349,9 +3449,9 @@ cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args) g_curl.release(); ::curl_easy_cleanup(curl); - if(statusVar.size()) + if(!statusVar.empty()) { - cmOStringStream result; + std::ostringstream result; result << (int)res << ";\"" << ::curl_easy_strerror(res) << "\""; this->Makefile->AddDefinition(statusVar, result.str().c_str()); @@ -3362,11 +3462,11 @@ cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args) fclose(fin); fin = NULL; - if(logVar.size()) + if(!logVar.empty()) { std::string log; - if(chunkResponse.size()) + if(!chunkResponse.empty()) { chunkResponse.push_back(0); log += "Response:\n"; @@ -3374,7 +3474,7 @@ cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args) log += "\n"; } - if(chunkDebug.size()) + if(!chunkDebug.empty()) { chunkDebug.push_back(0); log += "Debug:\n"; @@ -3466,6 +3566,205 @@ bool cmFileCommand::HandleGenerateCommand( } //---------------------------------------------------------------------------- +bool cmFileCommand::HandleLockCommand( + std::vector<std::string> const& args) +{ +#if defined(CMAKE_BUILD_WITH_CMAKE) + // Default values + bool directory = false; + bool release = false; + enum Guard { + GUARD_FUNCTION, + GUARD_FILE, + GUARD_PROCESS + }; + Guard guard = GUARD_PROCESS; + std::string resultVariable; + unsigned long timeout = static_cast<unsigned long>(-1); + + // Parse arguments + if(args.size() < 2) + { + this->Makefile->IssueMessage( + cmake::FATAL_ERROR, + "sub-command LOCK requires at least two arguments."); + return false; + } + + std::string path = args[1]; + for (unsigned i = 2; i < args.size(); ++i) + { + if (args[i] == "DIRECTORY") + { + directory = true; + } + else if (args[i] == "RELEASE") + { + release = true; + } + else if (args[i] == "GUARD") + { + ++i; + const char* merr = "expected FUNCTION, FILE or PROCESS after GUARD"; + if (i >= args.size()) + { + this->Makefile->IssueMessage(cmake::FATAL_ERROR, merr); + return false; + } + else + { + if (args[i] == "FUNCTION") + { + guard = GUARD_FUNCTION; + } + else if (args[i] == "FILE") + { + guard = GUARD_FILE; + } + else if (args[i] == "PROCESS") + { + guard = GUARD_PROCESS; + } + else + { + std::ostringstream e; + e << merr << ", but got:\n \"" << args[i] << "\"."; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + return false; + } + } + } + else if (args[i] == "RESULT_VARIABLE") + { + ++i; + if (i >= args.size()) + { + this->Makefile->IssueMessage( + cmake::FATAL_ERROR, + "expected variable name after RESULT_VARIABLE"); + return false; + } + resultVariable = args[i]; + } + else if (args[i] == "TIMEOUT") + { + ++i; + if (i >= args.size()) + { + this->Makefile->IssueMessage( + cmake::FATAL_ERROR, + "expected timeout value after TIMEOUT"); + return false; + } + long scanned; + if(!cmSystemTools::StringToLong(args[i].c_str(), &scanned) + || scanned < 0) + { + std::ostringstream e; + e << "TIMEOUT value \"" << args[i] << "\" is not an unsigned integer."; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + return false; + } + timeout = static_cast<unsigned long>(scanned); + } + else + { + std::ostringstream e; + e << "expected DIRECTORY, RELEASE, GUARD, RESULT_VARIABLE or TIMEOUT\n"; + e << "but got: \"" << args[i] << "\"."; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + return false; + } + } + + if (directory) + { + path += "/cmake.lock"; + } + + if (!cmsys::SystemTools::FileIsFullPath(path)) + { + path = this->Makefile->GetCurrentDirectory() + ("/" + path); + } + + // Unify path (remove '//', '/../', ...) + path = cmSystemTools::CollapseFullPath(path); + + // Create file and directories if needed + std::string parentDir = cmSystemTools::GetParentDirectory(path); + if (!cmSystemTools::MakeDirectory(parentDir)) + { + std::ostringstream e; + e << "directory\n \"" << parentDir << "\"\ncreation failed "; + e << "(check permissions)."; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + FILE *file = cmsys::SystemTools::Fopen(path, "w"); + if (!file) + { + std::ostringstream e; + e << "file\n \"" << path << "\"\ncreation failed (check permissions)."; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + fclose(file); + + // Actual lock/unlock + cmFileLockPool& lockPool = this->Makefile->GetLocalGenerator()-> + GetGlobalGenerator()->GetFileLockPool(); + + cmFileLockResult fileLockResult(cmFileLockResult::MakeOk()); + if (release) + { + fileLockResult = lockPool.Release(path); + } + else + { + switch (guard) + { + case GUARD_FUNCTION: + fileLockResult = lockPool.LockFunctionScope(path, timeout); + break; + case GUARD_FILE: + fileLockResult = lockPool.LockFileScope(path, timeout); + break; + case GUARD_PROCESS: + fileLockResult = lockPool.LockProcessScope(path, timeout); + break; + default: + cmSystemTools::SetFatalErrorOccured(); + return false; + } + } + + const std::string result = fileLockResult.GetOutputMessage(); + + if (resultVariable.empty() && !fileLockResult.IsOk()) + { + std::ostringstream e; + e << "error locking file\n \"" << path << "\"\n" << result << "."; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + + if (!resultVariable.empty()) + { + this->Makefile->AddDefinition(resultVariable, result.c_str()); + } + + return true; +#else + static_cast<void>(args); + this->SetError("sub-command LOCK not implemented in bootstrap cmake"); + return false; +#endif +} + +//---------------------------------------------------------------------------- bool cmFileCommand::HandleTimestampCommand( std::vector<std::string> const& args) { |